Do a lot of things

- Get audio library implements from LineageOS/gts4lv
- Move device manifests from configs to the root dir
- Revive Samsung, LineageOS HIDL
- Edit BoardConfig.mk a little

Signed-off-by: Deokgyu Yang <secugyu@gmail.com>
Change-Id: I70cc11946f936373d06ce37f5c7868f844abed71
This commit is contained in:
Deokgyu Yang 2021-05-12 22:19:10 +09:00
parent ab2c24db63
commit aefed99fcd
24 changed files with 4163 additions and 672 deletions

View file

@ -1,5 +1,5 @@
#
# Copyright (C) 2016 The CyanogenMod Project
# Copyright (C) 2019-2020 The LineageOS Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@ -12,35 +12,105 @@
# 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.
#
# WARNING: Everything listed here will be built on ALL platforms,
# including x86, the emulator, and the SDK. Modules must be uniquely
# named (liblights.tuna), and must build everywhere, or limit themselves
# to only building on ARM if they include assembly. Individual makefiles
# are responsible for having their own logic, for fine-grained control.
# This contains the module build definitions for the hardware-specific
# components for this device.
#
# As much as possible, those components should be built unconditionally,
# with device-specific names to avoid collisions, to avoid device-specific
# bitrot and build breakages. Building a component unconditionally does
# *not* include it on all devices, so it is safe even with hardware-specific
# components.
LOCAL_PATH := $(call my-dir)
ifeq ($(TARGET_DEVICE),gts3llte)
ifneq ($(filter gts3llte gts3lwifi,$(TARGET_DEVICE)),)
include $(call all-makefiles-under,$(LOCAL_PATH))
include $(CLEAR_VARS)
MODEM_IMAGES := \
modem.b00 modem.b01 modem.b02 modem.b03 modem.b04 modem.b05 \
modem.b06 modem.b07 modem.b08 modem.b09 modem.b10 modem.b11 \
modem.b12 modem.b13 modem.b15 modem.b16 modem.b17 modem.b18 \
modem.b19 modem.b20 modem.mdt
MODEM_SYMLINKS := $(addprefix $(TARGET_OUT_ETC)/firmware/,$(notdir $(MODEM_IMAGES)))
$(MODEM_SYMLINKS): $(LOCAL_INSTALLED_MODULE)
@echo "MODEM firmware link: $@"
@mkdir -p $(dir $@)
DSP_SYMLINK := $(TARGET_OUT_VENDOR)/lib/dsp
$(DSP_SYMLINK): $(LOCAL_INSTALLED_MODULE)
@echo "Creating DSP folder symlink: $@"
@rm -rf $@
$(hide) ln -sf /firmware-modem/image/$(notdir $@) $@
@mkdir -p $(TARGET_OUT_VENDOR)/lib/dsp
ALL_DEFAULT_INSTALLED_MODULES += $(MODEM_SYMLINKS)
ALL_DEFAULT_INSTALLED_MODULES += $(DSP_SYMLINK)
FIRMWARE_MODEM_MOUNT_POINT := $(TARGET_OUT_VENDOR)/firmware-modem
FIRMWARE_MOUNT_POINT := $(TARGET_OUT_VENDOR)/firmware_mnt
DSP_MOUNT_POINT := $(TARGET_OUT_VENDOR)/dsp
$(FIRMWARE_MODEM_MOUNT_POINT):
@echo "Creating $(FIRMWARE_MODEM_MOUNT_POINT)"
@mkdir -p $(TARGET_OUT_VENDOR)/firmware-modem
$(FIRMWARE_MOUNT_POINT):
@echo "Creating $(FIRMWARE_MOUNT_POINT)"
@mkdir -p $(TARGET_OUT_VENDOR)/firmware_mnt
$(DSP_MOUNT_POINT):
@echo "Creating $(DSP_MOUNT_POINT)"
@mkdir -p $(TARGET_OUT_VENDOR)/dsp
ALL_DEFAULT_INSTALLED_MODULES += \
$(FIRMWARE_MODEM_MOUNT_POINT) \
$(FIRMWARE_MOUNT_POINT) \
$(DSP_MOUNT_POINT)
RFS_MSM_ADSP_SYMLINKS := $(TARGET_OUT_VENDOR)/rfs/msm/adsp/
$(RFS_MSM_ADSP_SYMLINKS): $(LOCAL_INSTALLED_MODULE)
@echo "Creating RFS MSM ADSP folder structure: $@"
@rm -rf $@/*
@mkdir -p $(dir $@)/readonly/vendor
$(hide) ln -sf /data/vendor/tombstones/rfs/lpass $@/ramdumps
$(hide) ln -sf /mnt/vendor/persist/rfs/msm/adsp $@/readwrite
$(hide) ln -sf /mnt/vendor/persist/rfs/shared $@/shared
$(hide) ln -sf /mnt/vendor/persist/hlos_rfs/shared $@/hlos
$(hide) ln -sf /vendor/firmware_mnt $@/readonly/firmware
$(hide) ln -sf /vendor/firmware $@/readonly/vendor/firmware
RFS_MSM_CDSP_SYMLINKS := $(TARGET_OUT_VENDOR)/rfs/msm/cdsp/
$(RFS_MSM_CDSP_SYMLINKS): $(LOCAL_INSTALLED_MODULE)
@echo "Creating RFS MSM CDSP folder structure: $@"
@rm -rf $@/*
@mkdir -p $(dir $@)/readonly/vendor
$(hide) ln -sf /data/vendor/tombstones/rfs/cdsp $@/ramdumps
$(hide) ln -sf /mnt/vendor/persist/rfs/msm/cdsp $@/readwrite
$(hide) ln -sf /mnt/vendor/persist/rfs/shared $@/shared
$(hide) ln -sf /mnt/vendor/persist/hlos_rfs/shared $@/hlos
$(hide) ln -sf /vendor/firmware_mnt $@/readonly/firmware
$(hide) ln -sf /vendor/firmware $@/readonly/vendor/firmware
RFS_MSM_MPSS_SYMLINKS := $(TARGET_OUT_VENDOR)/rfs/msm/mpss/
$(RFS_MSM_MPSS_SYMLINKS): $(LOCAL_INSTALLED_MODULE)
@echo "Creating RFS MSM MPSS folder structure: $@"
@rm -rf $@/*
@mkdir -p $(dir $@)/readonly/vendor
$(hide) ln -sf /data/vendor/tombstones/rfs/modem $@/ramdumps
$(hide) ln -sf /mnt/vendor/persist/rfs/msm/mpss $@/readwrite
$(hide) ln -sf /mnt/vendor/persist/rfs/shared $@/shared
$(hide) ln -sf /mnt/vendor/persist/hlos_rfs/shared $@/hlos
$(hide) ln -sf /vendor/firmware-modem $@/readonly/firmware
$(hide) ln -sf /vendor/firmware $@/readonly/vendor/firmware
RFS_MSM_SLPI_SYMLINKS := $(TARGET_OUT_VENDOR)/rfs/msm/slpi/
$(RFS_MSM_SLPI_SYMLINKS): $(LOCAL_INSTALLED_MODULE)
@echo "Creating RFS MSM SLPI folder structure: $@"
@rm -rf $@/*
@mkdir -p $(dir $@)/readonly/vendor
$(hide) ln -sf /data/vendor/tombstones/rfs/slpi $@/ramdumps
$(hide) ln -sf /mnt/vendor/persist/rfs/msm/slpi $@/readwrite
$(hide) ln -sf /mnt/vendor/persist/rfs/shared $@/shared
$(hide) ln -sf /mnt/vendor/persist/hlos_rfs/shared $@/hlos
$(hide) ln -sf /vendor/firmware_mnt $@/readonly/firmware
$(hide) ln -sf /vendor/firmware $@/readonly/vendor/firmware
ALL_DEFAULT_INSTALLED_MODULES += \
$(RFS_MSM_ADSP_SYMLINKS) \
$(RFS_MSM_CDSP_SYMLINKS) \
$(RFS_MSM_MPSS_SYMLINKS) \
$(RFS_MSM_SLPI_SYMLINKS)
WCNSS_INI_SYMLINK := $(TARGET_OUT_VENDOR)/firmware/wlan/qca_cld/WCNSS_qcom_cfg.ini
$(WCNSS_INI_SYMLINK): $(LOCAL_INSTALLED_MODULE)
@ -49,369 +119,6 @@ $(WCNSS_INI_SYMLINK): $(LOCAL_INSTALLED_MODULE)
@rm -rf $@
$(hide) ln -sf /vendor/etc/wifi/$(notdir $@) $@
WCNSS_MAC_SYMLINK := $(TARGET_OUT_VENDOR)/firmware/wlan/qca_cld/wlan_mac.bin
$(WCNSS_MAC_SYMLINK): $(LOCAL_INSTALLED_MODULE)
@echo "WCNSS MAC bin link: $@"
@mkdir -p $(dir $@)
@rm -rf $@
$(hide) ln -sf /persist/$(notdir $@) $@
ALL_DEFAULT_INSTALLED_MODULES += $(WCNSS_INI_SYMLINK)
ALL_DEFAULT_INSTALLED_MODULES += $(WCNSS_INI_SYMLINK) $(WCNSS_MAC_SYMLINK)
# Create links for audcal data files
$(shell mkdir -p $(TARGET_OUT)/etc/firmware/wcd9320; \
ln -sf /data/misc/audio/wcd9320_anc.bin \
$(TARGET_OUT)/etc/firmware/wcd9320/wcd9320_anc.bin;\
ln -sf /data/misc/audio/mbhc.bin \
$(TARGET_OUT)/etc/firmware/wcd9320/wcd9320_mbhc.bin; \
ln -sf /data/misc/audio/wcd9320_mad_audio.bin \
$(TARGET_OUT)/etc/firmware/wcd9320/wcd9320_mad_audio.bin)
RFS_MSM_ADSP_SYMLINKS := $(TARGET_OUT_VENDOR)/rfs/msm/adsp/
$(RFS_MSM_ADSP_SYMLINKS): $(LOCAL_INSTALLED_MODULE)
@echo "Creating RFS MSM ADSP folder structure: $@"
@rm -rf $@/*
@mkdir -p $(dir $@)/readonly/vendor
$(hide) ln -sf /data/vendor/tombstones/rfs/lpass $@/ramdumps
$(hide) ln -sf /persist/rfs/msm/adsp $@/readwrite
$(hide) ln -sf /persist/rfs/shared $@/shared
$(hide) ln -sf /persist/hlos_rfs/shared $@/hlos
$(hide) ln -sf /firmware $@/readonly/firmware
$(hide) ln -sf /vendor/firmware $@/readonly/vendor/firmware
RFS_MSM_MPSS_SYMLINKS := $(TARGET_OUT_VENDOR)/rfs/msm/mpss/
$(RFS_MSM_MPSS_SYMLINKS): $(LOCAL_INSTALLED_MODULE)
@echo "Creating RFS MSM MPSS folder structure: $@"
@rm -rf $@/*
@mkdir -p $(dir $@)/readonly/vendor
$(hide) ln -sf /data/vendor/tombstones/rfs/modem $@/ramdumps
$(hide) ln -sf /persist/rfs/msm/mpss $@/readwrite
$(hide) ln -sf /persist/rfs/shared $@/shared
$(hide) ln -sf /persist/hlos_rfs/shared $@/hlos
$(hide) ln -sf /firmware $@/readonly/firmware
$(hide) ln -sf /vendor/firmware $@/readonly/vendor/firmware
RFS_MSM_SLPI_SYMLINKS := $(TARGET_OUT_VENDOR)/rfs/msm/slpi/
$(RFS_MSM_SLPI_SYMLINKS): $(LOCAL_INSTALLED_MODULE)
@echo "Creating RFS MSM SLPI folder structure: $@"
@rm -rf $@/*
@mkdir -p $(dir $@)/readonly/vendor
$(hide) ln -sf /data/vendor/tombstones/rfs/modem $@/ramdumps
$(hide) ln -sf /persist/rfs/msm/slpi $@/readwrite
$(hide) ln -sf /persist/rfs/shared $@/shared
$(hide) ln -sf /persist/hlos_rfs/shared $@/hlos
$(hide) ln -sf /firmware $@/readonly/firmware
$(hide) ln -sf /vendor/firmware $@/readonly/vendor/firmware
RFS_MDM_SPARROW_SYMLINKS := $(TARGET_OUT_VENDOR)/rfs/mdm/sparrow/
$(RFS_MDM_SPARROW_SYMLINKS): $(LOCAL_INSTALLED_MODULE)
@echo "Creating RFS MDM SPARROW folder structure: $@"
@rm -rf $@/*
@mkdir -p $(dir $@)/readonly/vendor
$(hide) ln -sf /data/vendor/tombstones/sparrow $@/ramdumps
$(hide) ln -sf /persist/rfs/mdm/sparrow $@/readwrite
$(hide) ln -sf /persist/rfs/shared $@/shared
$(hide) ln -sf /persist/hlos_rfs/shared $@/hlos
$(hide) ln -sf /firmware $@/readonly/firmware
$(hide) ln -sf /vendor/firmware $@/readonly/vendor/firmware
RFS_APQ_GNSS_SYMLINKS := $(TARGET_OUT_VENDOR)/rfs/apq/gnss/
$(RFS_APQ_GNSS_SYMLINKS): $(LOCAL_INSTALLED_MODULE)
@echo "Creating RFS APQ GNSS folder structure: $@"
@rm -rf $@/*
@mkdir -p $(dir $@)/readonly/vendor
$(hide) ln -sf /data/vendor/tombstones/modem $@/ramdumps
$(hide) ln -sf /persist/rfs/apq/gnss $@/readwrite
$(hide) ln -sf /persist/rfs/shared $@/shared
$(hide) ln -sf /persist/hlos_rfs/shared $@/hlos
$(hide) ln -sf /firmware $@/readonly/firmware
$(hide) ln -sf /vendor/firmware $@/readonly/vendor/firmware
ALL_DEFAULT_INSTALLED_MODULES += \
$(RFS_MSM_ADSP_SYMLINKS) \
$(RFS_MSM_MPSS_SYMLINKS) \
$(RFS_MSM_SLPI_SYMLINKS) \
$(RFS_MDM_SPARROW_SYMLINKS) \
$(RFS_APQ_GNSS_SYMLINKS)
ADSP_IMAGES := \
adsp.b00 adsp.b01 adsp.b02 adsp.b03 adsp.b04 \
adsp.b05 adsp.b06 adsp.b08 adsp.b09 adsp.mdt
ADSP_SYMLINKS := $(addprefix $(TARGET_OUT_VENDOR)/firmware/,$(notdir $(ADSP_IMAGES)))
$(ADSP_SYMLINKS): $(LOCAL_INSTALLED_MODULE)
@echo "ADSP firmware link: $@"
@mkdir -p $(dir $@)
@rm -rf $@
$(hide) ln -sf /firmware-modem/image/$(notdir $@) $@
ALL_DEFAULT_INSTALLED_MODULES += $(ADSP_SYMLINKS)
MBA_IMAGES := mba.mbn
MBA_SYMLINKS := $(addprefix $(TARGET_OUT_VENDOR)/firmware/,$(notdir $(MBA_IMAGES)))
$(MBA_SYMLINKS): $(LOCAL_INSTALLED_MODULE)
@echo "MBA firmware link: $@"
@mkdir -p $(dir $@)
@rm -rf $@
$(hide) ln -sf /firmware-modem/image/$(notdir $@) $@
ALL_DEFAULT_INSTALLED_MODULES += $(MBA_SYMLINKS)
AUTHHAT_IMAGES := authhat.b00 authhat.b01 authhat.b02 authhat.b03 authhat.b04 authhat.b05 authhat.b06 authhat.mdt
AUTHHAT_SYMLINKS := $(addprefix $(TARGET_OUT_VENDOR)/firmware/,$(notdir $(AUTHHAT_IMAGES)))
$(AUTHHAT_SYMLINKS): $(LOCAL_INSTALLED_MODULE)
@echo "AUTHHAT firmware link: $@"
@mkdir -p $(dir $@)
@rm -rf $@
$(hide) ln -sf /firmware/image/$(notdir $@) $@
ALL_DEFAULT_INSTALLED_MODULES += $(AUTHHAT_SYMLINKS)
AUTHHAT_SYMLINKS1 := $(addprefix $(TARGET_OUT_VENDOR)/firmware_mnt/image/,$(notdir $(AUTHHAT_IMAGES)))
$(AUTHHAT_SYMLINKS1): $(LOCAL_INSTALLED_MODULE)
@echo "AUTHHAT firmware link: $@"
@mkdir -p $(dir $@)
@rm -rf $@
$(hide) ln -sf /firmware/image/$(notdir $@) $@
ALL_DEFAULT_INSTALLED_MODULES += $(AUTHHAT_SYMLINKS1)
BDWLAN_IMAGES := \
bdwlan30.b01 bdwlan30.b02 bdwlan30.b03 bdwlan30.b04 bdwlan30.b05 bdwlan30.b06 bdwlan30.b07 \
bdwlan30.b08 bdwlan30.b09 bdwlan30.b0a bdwlan30.b0b bdwlan30.b0c bdwlan30.b0d bdwlan30.b0e \
bdwlan30.b11 bdwlan30.b15 bdwlan30.b18 bdwlan30.b1c bdwlan30.bin
BDWLAN_SYMLINKS := $(addprefix $(TARGET_OUT_VENDOR)/firmware/,$(notdir $(BDWLAN_IMAGES)))
$(BDWLAN_SYMLINKS): $(LOCAL_INSTALLED_MODULE)
@echo "BDWLAN firmware link: $@"
@mkdir -p $(dir $@)
@rm -rf $@
$(hide) ln -sf /firmware/image/$(notdir $@) $@
ALL_DEFAULT_INSTALLED_MODULES += $(BDWLAN_SYMLINKS)
BDWLAN_SYMLINKS1 := $(addprefix $(TARGET_OUT_VENDOR)/firmware_mnt/image/,$(notdir $(BDWLAN_IMAGES)))
$(BDWLAN_SYMLINKS1): $(LOCAL_INSTALLED_MODULE)
@echo "BDWLAN firmware link: $@"
@mkdir -p $(dir $@)
@rm -rf $@
$(hide) ln -sf /firmware/image/$(notdir $@) $@
ALL_DEFAULT_INSTALLED_MODULES += $(BDWLAN_SYMLINKS1)
CPE_IMAGES := \
cpe_9335.b08 cpe_9335.b09 cpe_9335.b11 cpe_9335.b14 cpe_9335.b16 \
cpe_9335.b18 cpe_9335.b19 cpe_9335.b20 cpe_9335.b22 cpe_9335.b24 \
cpe_9335.b26 cpe_9335.b28 cpe_9335.b29 cpe_9335.mdt
CPE_SYMLINKS := $(addprefix $(TARGET_OUT_VENDOR)/firmware/,$(notdir $(CPE_IMAGES)))
$(CPE_SYMLINKS): $(LOCAL_INSTALLED_MODULE)
@echo "CPE firmware link: $@"
@mkdir -p $(dir $@)
@rm -rf $@
$(hide) ln -sf /firmware/image/$(notdir $@) $@
ALL_DEFAULT_INSTALLED_MODULES += $(CPE_SYMLINKS)
CPPF_IMAGES := cppf.b00 cppf.b01 cppf.b02 cppf.b03 cppf.b04 cppf.b05 cppf.b06 cppf.mdt
CPPF_SYMLINKS := $(addprefix $(TARGET_OUT_VENDOR)/firmware/,$(notdir $(CPPF_IMAGES)))
$(CPPF_SYMLINKS): $(LOCAL_INSTALLED_MODULE)
@echo "CPPF firmware link: $@"
@mkdir -p $(dir $@)
@rm -rf $@
$(hide) ln -sf /firmware/image/$(notdir $@) $@
ALL_DEFAULT_INSTALLED_MODULES += $(CPPF_SYMLINKS)
DATA_IMAGES := data.msc
DATA_SYMLINKS := $(addprefix $(TARGET_OUT_VENDOR)/firmware/,$(notdir $(DATA_IMAGES)))
$(DATA_SYMLINKS): $(LOCAL_INSTALLED_MODULE)
@echo "DATA firmware link: $@"
@mkdir -p $(dir $@)
@rm -rf $@
$(hide) ln -sf /firmware/image/$(notdir $@) $@
ALL_DEFAULT_INSTALLED_MODULES += $(DATA_SYMLINKS)
ADD_IMAGES := \
dhsecapp.b00 dhsecapp.b01 dhsecapp.b02 dhsecapp.b03 dhsecapp.b04 dhsecapp.b05 dhsecapp.b06 dhsecapp.mdt \
dmverity.b00 dmverity.b01 dmverity.b02 dmverity.b03 dmverity.b04 dmverity.b05 dmverity.b06 dmverity.mdt \
dualfp.b00 dualfp.b01 dualfp.b02 dualfp.b03 dualfp.b04 dualfp.b05 dualfp.b06 dualfp.mdt \
dxprdy.b00 dxprdy.b01 dxprdy.b02 dxprdy.b03 dxprdy.b04 dxprdy.b05 dxprdy.b06 dxprdy.mdt \
esecomm.b00 esecomm.b01 esecomm.b02 esecomm.b03 esecomm.b04 esecomm.b05 esecomm.b06 esecomm.mdt \
isdbtmm.b00 isdbtmm.b01 isdbtmm.b02 isdbtmm.b03 isdbtmm.b04 isdbtmm.b05 isdbtmm.b06 isdbtmm.mdt \
lksecapp.b00 lksecapp.b01 lksecapp.b02 lksecapp.b03 lksecapp.b04 lksecapp.b05 lksecapp.b06 lksecapp.mdt \
mldap.b00 mldap.b01 mldap.b02 mldap.b03 mldap.b04 mldap.b05 mldap.b06 mldap.mdt \
mst.b00 mst.b01 mst.b02 mst.b03 mst.b04 mst.b05 mst.b06 mst.mdt \
otp30.bin \
prov.b00 prov.b01 prov.b02 prov.b03 prov.b04 prov.b05 prov.b06 prov.mdt \
qmpsecap.b00 qmpsecap.b01 qmpsecap.b02 qmpsecap.b03 qmpsecap.b04 qmpsecap.b05 qmpsecap.b06 qmpsecap.mdt \
qwlan30.bin \
sdtvrmp.b00 sdtvrmp.b01 sdtvrmp.b02 sdtvrmp.b03 sdtvrmp.b04 sdtvrmp.b05 sdtvrmp.b06 sdtvrmp.mdt \
securemm.b00 securemm.b01 securemm.b02 securemm.b03 securemm.b04 securemm.b05 securemm.b06 securemm.mdt \
sem.b00 sem.b01 sem.b02 sem.b03 sem.b04 sem.b05 sem.b06 sem.mdt \
skeymast.b00 skeymast.b01 skeymast.b02 skeymast.b03 skeymast.b04 skeymast.b05 skeymast.b06 skeymast.mdt \
slpi.b00 slpi.b01 slpi.b02 slpi.b03 slpi.b04 slpi.b05 slpi.b06 slpi.b07 \
slpi.b08 slpi.b09 slpi.b10 slpi.b11 slpi.b12 slpi.b13 slpi.b14 slpi.mdt \
smplap32.b00 smplap32.b01 smplap32.b02 smplap32.b03 smplap32.b04 smplap32.b05 smplap32.b06 smplap32.mdt \
smplap64.b00 smplap64.b01 smplap64.b02 smplap64.b03 smplap64.b04 smplap64.b05 smplap64.b06 smplap64.mdt \
softsim.b00 softsim.b01 softsim.b02 softsim.b03 softsim.b04 softsim.b05 softsim.b06 softsim.mdt \
tbase.b00 tbase.b01 tbase.b02 tbase.b03 tbase.b04 tbase.b05 tbase.b06 tbase.mdt \
utf30.bin
ADD_SYMLINKS := $(addprefix $(TARGET_OUT_VENDOR)/firmware/,$(notdir $(ADD_IMAGES)))
$(ADD_SYMLINKS): $(LOCAL_INSTALLED_MODULE)
@echo "Additional firmware link: $@"
@mkdir -p $(dir $@)
@rm -rf $@
$(hide) ln -sf /firmware/image/$(notdir $@) $@
ALL_DEFAULT_INSTALLED_MODULES += $(ADD_SYMLINKS)
ADD_SYMLINKS1 := $(addprefix $(TARGET_OUT_VENDOR)/firmware_mnt/image/,$(notdir $(ADD_IMAGES)))
$(ADD_SYMLINKS1): $(LOCAL_INSTALLED_MODULE)
@echo "Additional firmware link: $@"
@mkdir -p $(dir $@)
@rm -rf $@
$(hide) ln -sf /firmware/image/$(notdir $@) $@
ALL_DEFAULT_INSTALLED_MODULES += $(ADD_SYMLINKS1)
FINGERPR_IMAGES := fingerpr.b00 fingerpr.b01 fingerpr.b02 fingerpr.b03 fingerpr.b04 fingerpr.b05 fingerpr.b06 fingerpr.mdt
FINGERPR_SYMLINKS := $(addprefix $(TARGET_OUT_VENDOR)/firmware/,$(notdir $(FINGERPR_IMAGES)))
$(FINGERPR_SYMLINKS): $(LOCAL_INSTALLED_MODULE)
@echo "FINGERPR firmware link: $@"
@mkdir -p $(dir $@)
@rm -rf $@
$(hide) ln -sf /firmware/image/$(notdir $@) $@
ALL_DEFAULT_INSTALLED_MODULES += $(FINGERPR_SYMLINKS)
FINGERPR_SYMLINKS1 := $(addprefix $(TARGET_OUT_VENDOR)/firmware/,$(notdir $(FINGERPR_IMAGES)))
$(FINGERPR_SYMLINKS1): $(LOCAL_INSTALLED_MODULE)
@echo "FINGERPR firmware link: $@"
@mkdir -p $(dir $@)
@rm -rf $@
$(hide) ln -sf /firmware/image/$(notdir $@) $@
ALL_DEFAULT_INSTALLED_MODULES += $(FINGERPR_SYMLINKS1)
GPSTEST_IMAGES := gptest.b00 gptest.b01 gptest.b02 gptest.b03 gptest.b04 gptest.b05 gptest.b06 gptest.mdt
GPSTEST_SYMLINKS := $(addprefix $(TARGET_OUT_VENDOR)/firmware/,$(notdir $(GPSTEST_IMAGES)))
$(GPSTEST_SYMLINKS): $(LOCAL_INSTALLED_MODULE)
@echo "GPSTEST firmware link: $@"
@mkdir -p $(dir $@)
@rm -rf $@
$(hide) ln -sf /firmware/image/$(notdir $@) $@
ALL_DEFAULT_INSTALLED_MODULES += $(GPSTEST_SYMLINKS)
SKM_IMAGES := \
skm.b00 skm.b01 skm.b02 skm.b03 skm.b04 skm.b05 skm.b06 skm.mdt \
SKM_SYMLINKS := $(addprefix $(TARGET_OUT_VENDOR)/firmware/,$(notdir $(SKM_IMAGES)))
$(SKM_SYMLINKS): $(LOCAL_INSTALLED_MODULE)
@echo "SKM firmware link: $@"
@mkdir -p $(dir $@)
@rm -rf $@
$(hide) ln -sf /firmware/image/$(notdir $@) $@
ALL_DEFAULT_INSTALLED_MODULES += $(SKM_SYMLINKS)
SKMM_TA_IMAGES := \
skmm_ta.b00 skmm_ta.b01 skmm_ta.b02 skmm_ta.b03 skmm_ta.b04 skmm_ta.b05 skmm_ta.b06 skmm_ta.mdt \
SKMM_TA_SYMLINKS := $(addprefix $(TARGET_OUT_VENDOR)/firmware/,$(notdir $(SKMM_TA_IMAGES)))
$(SKMM_TA_SYMLINKS): $(LOCAL_INSTALLED_MODULE)
@echo "SKMM firmware link: $@"
@mkdir -p $(dir $@)
@rm -rf $@
$(hide) ln -sf /firmware/image/$(notdir $@) $@
ALL_DEFAULT_INSTALLED_MODULES += $(SKMM_TA_SYMLINKS)
SSHDCPAP_IMAGES := \
sshdcpap.b00 sshdcpap.b01 sshdcpap.b02 sshdcpap.b03 sshdcpap.b04 sshdcpap.b05 sshdcpap.b06 sshdcpap.mdt \
SSHDCPAP_SYMLINKS := $(addprefix $(TARGET_OUT_VENDOR)/firmware/,$(notdir $(SSHDCPAP_IMAGES)))
$(SSHDCPAP_SYMLINKS): $(LOCAL_INSTALLED_MODULE)
@echo "SSHDCPAP firmware link: $@"
@mkdir -p $(dir $@)
@rm -rf $@
$(hide) ln -sf /firmware/image/$(notdir $@) $@
ALL_DEFAULT_INSTALLED_MODULES += $(SSHDCPAP_SYMLINKS)
TIMA_IMAGES := \
tima_atn.b00 tima_atn.b01 tima_atn.b02 tima_atn.b03 tima_atn.b04 tima_atn.b05 tima_atn.b06 tima_atn.mdt \
tima_key.b00 tima_key.b01 tima_key.b02 tima_key.b03 tima_key.b04 tima_key.b05 tima_key.b06 tima_key.mdt \
tima_lkm.b00 tima_lkm.b01 tima_lkm.b02 tima_lkm.b03 tima_lkm.b04 tima_lkm.b05 tima_lkm.b06 tima_lkm.mdt \
tima_pkm.b00 tima_pkm.b01 tima_pkm.b02 tima_pkm.b03 tima_pkm.b04 tima_pkm.b05 tima_pkm.b06 tima_pkm.mdt
TIMA_SYMLINKS := $(addprefix $(TARGET_OUT_VENDOR)/firmware/,$(notdir $(TIMA_IMAGES)))
$(TIMA_SYMLINKS): $(LOCAL_INSTALLED_MODULE)
@echo "TIMA firmware link: $@"
@mkdir -p $(dir $@)
@rm -rf $@
$(hide) ln -sf /firmware/image/$(notdir $@) $@
ALL_DEFAULT_INSTALLED_MODULES += $(TIMA_SYMLINKS)
TZ_IMAGES := \
tz_ccm.b00 tz_ccm.b01 tz_ccm.b02 tz_ccm.b03 tz_ccm.b04 tz_ccm.b05 tz_ccm.b06 tz_ccm.mdt \
tz_iccc.b00 tz_iccc.b01 tz_iccc.b02 tz_iccc.b03 tz_iccc.b04 tz_iccc.b05 tz_iccc.b06 tz_iccc.mdt \
tz_otp.b00 tz_otp.b01 tz_otp.b02 tz_otp.b03 tz_otp.b04 tz_otp.b05 tz_otp.b06 tz_otp.mdt
TZ_SYMLINKS := $(addprefix $(TARGET_OUT_VENDOR)/firmware/,$(notdir $(TZ_IMAGES)))
$(TZ_SYMLINKS): $(LOCAL_INSTALLED_MODULE)
@echo "TZ firmware link: $@"
@mkdir -p $(dir $@)
@rm -rf $@
$(hide) ln -sf /firmware/image/$(notdir $@) $@
ALL_DEFAULT_INSTALLED_MODULES += $(TZ_SYMLINKS)
VENUS_IMAGES := venus.b00 venus.b01 venus.b02 venus.b03 venus.b04 venus.mdt
VENUS_SYMLINKS := $(addprefix $(TARGET_OUT_VENDOR)/firmware/,$(notdir $(VENUS_IMAGES)))
$(VENUS_SYMLINKS): $(LOCAL_INSTALLED_MODULE)
@echo "Venus firmware link: $@"
@mkdir -p $(dir $@)
@rm -rf $@
$(hide) ln -sf /firmware/image/$(notdir $@) $@
ALL_DEFAULT_INSTALLED_MODULES += $(VENUS_SYMLINKS)
WV_IMAGES := \
cmnlib.b00 cmnlib.b01 cmnlib.b02 cmnlib.b03 cmnlib.b04 cmnlib.b05 cmnlib.mdt \
cmnlib64.b00 cmnlib64.b01 cmnlib64.b02 cmnlib64.b03 cmnlib64.b04 cmnlib64.b05 cmnlib64.mdt \
widevine.b00 widevine.b01 widevine.b02 widevine.b03 widevine.b04 widevine.b05 widevine.b06 widevine.mdt
WV_SYMLINKS := $(addprefix $(TARGET_OUT_VENDOR)/firmware/,$(notdir $(WV_IMAGES)))
$(WV_SYMLINKS): $(LOCAL_INSTALLED_MODULE)
@echo "Widevine firmware link: $@"
@mkdir -p $(dir $@)
@rm -rf $@
$(hide) ln -sf /firmware/image/$(notdir $@) $@
ALL_DEFAULT_INSTALLED_MODULES += $(WV_SYMLINKS)
WSM_IMAGES := wsm.b00 wsm.b01 wsm.b02 wsm.b03 wsm.b04 wsm.b05 wsm.b06 wsm.mdt
WSM_SYMLINKS := $(addprefix $(TARGET_OUT_VENDOR)/firmware/,$(notdir $(WSM_IMAGES)))
$(WSM_SYMLINKS): $(LOCAL_INSTALLED_MODULE)
@echo "WSM firmware link: $@"
@mkdir -p $(dir $@)
@rm -rf $@
$(hide) ln -sf /firmware/image/$(notdir $@) $@
ALL_DEFAULT_INSTALLED_MODULES += $(WSM_SYMLINKS)
endif
endif

View file

@ -15,9 +15,6 @@
# limitations under the License.
#
# temporary
BUILD_BROKEN_DUP_RULES := true
BOARD_VENDOR := samsung
DEVICE_PATH := device/samsung/gts3llte
@ -51,17 +48,16 @@ TARGET_NO_BOOTLOADER := true
# Kernel
BOARD_KERNEL_BASE := 0x80000000
BOARD_KERNEL_CMDLINE := androidboot.hardware=qcom msm_rtb.filter=0x237 ehci-hcd.park=3 androidboot.bootdevice=7464900.sdhci lpm_levels.sleep_disabled=1 rcupdate.rcu_expedited=1 cma=32M@0-0xffffffff
BOARD_KERNEL_CMDLINE += androidboot.selinux=permissive
BOARD_KERNEL_CMDLINE += androidboot.selinux=disabled
BOARD_KERNEL_IMAGE_NAME := Image.gz
BOARD_KERNEL_PAGESIZE := 4096
BOARD_KERNEL_SEPARATED_DT := true
BOARD_MKBOOTIMG_ARGS := --kernel_offset 0x00008000 --ramdisk_offset 0x02200000 --tags_offset 0x02000000
TARGET_KERNEL_SOURCE := kernel/samsung/msm8996
BOARD_CUSTOM_BOOTIMG := true
BOARD_CUSTOM_BOOTIMG_MK := hardware/samsung/mkbootimg.mk
#TARGET_KERNEL_CROSS_COMPILE_PREFIX := aarch64-linux-android-
TARGET_KERNEL_ARCH := arm64
TARGET_KERNEL_SOURCE := kernel/samsung/msm8996
TARGET_KERNEL_CONFIG := lineage_gts3llte_defconfig
TARGET_COMPILE_WITH_MSM_KERNEL := true
# Platform
@ -103,9 +99,7 @@ BOARD_HAVE_BLUETOOTH_QCOM := true
QCOM_BT_USE_BTNV := true
# Camera
USE_CAMERA_STUB := true
USE_DEVICE_SPECIFIC_CAMERA := true
TARGET_USES_MEDIA_EXTENSIONS := true
TARGET_USES_QTI_CAMERA_DEVICE := true
# Charger
BOARD_CHARGER_ENABLE_SUSPEND := true
@ -141,9 +135,9 @@ TARGET_HW_DISK_ENCRYPTION := true
TARGET_FS_CONFIG_GEN := $(DEVICE_PATH)/config.fs
# HIDL
DEVICE_FRAMEWORK_MANIFEST_FILE := $(DEVICE_PATH)/configs/framework_manifest.xml
DEVICE_MANIFEST_FILE := $(DEVICE_PATH)/configs/manifest.xml
DEVICE_MATRIX_FILE := $(DEVICE_PATH)/configs/compatibility_matrix.xml
DEVICE_FRAMEWORK_MANIFEST_FILE := $(DEVICE_PATH)/framework_manifest.xml
DEVICE_MANIFEST_FILE := $(DEVICE_PATH)/manifest.xml
DEVICE_MATRIX_FILE := $(DEVICE_PATH)/compatibility_matrix.xml
# Partitions
BOARD_BOOTIMAGE_PARTITION_SIZE := 79691776
@ -151,7 +145,7 @@ BOARD_CACHEIMAGE_PARTITION_SIZE := 209715200
BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE := f2fs
BOARD_PERSISTIMAGE_PARTITION_SIZE := 33554432
BOARD_RECOVERYIMAGE_PARTITION_SIZE := 79691776
BOARD_SYSTEMIMAGE_PARTITION_SIZE := 3072000000
BOARD_SYSTEMIMAGE_PARTITION_SIZE := 3072000000
#BOARD_SYSTEMIMAGE_PARTITION_SIZE := 4194304000
BOARD_USERDATAIMAGE_PARTITION_SIZE := 26226982912
BOARD_FLASH_BLOCK_SIZE := 131072
@ -160,21 +154,24 @@ TARGET_USES_MKE2FS := true
# Fingerprint
TARGET_SEC_FP_HAL_VARIANT := bauth
# Init
TARGET_PLATFORM_DEVICE_BASE := /devices/soc/
# Keymaster
TARGET_PROVIDES_KEYMASTER := true
# Power
TARGET_TAP_TO_WAKE_NODE := "/proc/touchpanel/double_tap_enable"
TARGET_USES_INTERACTION_BOOST := true
# QCOM
BOARD_USES_QCOM_HARDWARE := true
# Ramdisk
BOARD_ROOT_EXTRA_FOLDERS := efs firmware firmware-modem persist
BOARD_ROOT_EXTRA_SYMLINKS := /system/vendor/firmware/btfw32.tlv:/bt_firmware/image/btfw32.tlv
BOARD_ROOT_EXTRA_FOLDERS := efs omr firmware firmware-modem persist
BOARD_ROOT_EXTRA_SYMLINKS := \
/mnt/vendor/persist:/persist \
/vendor/dsp:/dsp \
/vendor/firmware_mnt:/firmware \
/vendor/bt_firmware:/bt_firmware
BOARD_ROOT_EXTRA_SYMLINKS += /system/vendor/firmware/btfw32.tlv:/bt_firmware/image/btfw32.tlv
BOARD_ROOT_EXTRA_SYMLINKS += /system/vendor/firmware/btnv32.bin:/bt_firmware/image/btnv32.bin
# Recovery
@ -189,11 +186,10 @@ ENABLE_VENDOR_RIL_SERVICE := true
# Security patch level - T825N0KOU3CTD1
VENDOR_SECURITY_PATCH := 2020-03-01
SELINUX_IGNORE_NEVERALLOWS := true
# SELinux
include device/qcom/sepolicy/sepolicy.mk
BOARD_SEPOLICY_DIRS += $(DEVICE_PATH)/sepolicy
SELINUX_IGNORE_NEVERALLOWS := true
# Wifi
BOARD_HAS_QCOM_WLAN := true

View file

@ -1,30 +1,3 @@
<!-- Copyright (c) 2017, The Linux Foundation. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of The Linux Foundation nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-->
<compatibility-matrix version="1.0" type="device">
<hal format="hidl" optional="false">
<name>android.frameworks.schedulerservice</name>
@ -82,5 +55,17 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<instance>default</instance>
</interface>
</hal>
<hal format="native" optional="false">
<name>netutils-wrapper</name>
<!--
netutils-wrapper should only list a single version x.0.
netutils-wrapper next version has less functionalities than
previous versions, so unlike a HAL, netutils-wrapper are not
backwards compatible. Hence the major version must be bumped for
each update.
Vendor code should switch to (x+1).0 completely before when the
requirement is updated here.
-->
<version>1.0</version>
</hal>
</compatibility-matrix>

View file

@ -0,0 +1,96 @@
cc_defaults {
name: "android.hardware.audio-impl_gts3l",
relative_install_path: "hw",
proprietary: true,
vendor: true,
srcs: [
"Conversions.cpp",
"Device.cpp",
"DevicesFactory.cpp",
"ParametersUtil.cpp",
"PrimaryDevice.cpp",
"Stream.cpp",
"StreamIn.cpp",
"StreamOut.cpp",
],
defaults: ["hidl_defaults"],
export_include_dirs: ["include"],
shared_libs: [
"libbase",
"libcutils",
"libfmq",
"libhardware",
"libhidlbase",
"libhidltransport",
"liblog",
"libtinyalsa",
"libutils",
"android.hardware.audio.common-util",
],
header_libs: [
"android.hardware.audio.common.util@all-versions",
"libaudioclient_headers",
"libaudio_system_headers",
"libhardware_headers",
"libmedia_headers",
],
whole_static_libs: [
"libmedia_helper",
],
}
cc_library_shared {
name: "android.hardware.audio@2.0-impl.gts3l",
defaults: ["android.hardware.audio-impl_gts3l"],
shared_libs: [
"android.hardware.audio@2.0",
"android.hardware.audio.common@2.0",
"android.hardware.audio.common@2.0-util",
],
cflags: [
"-DMAJOR_VERSION=2",
"-DMINOR_VERSION=0",
"-include common/all-versions/VersionMacro.h",
]
}
cc_library_shared {
name: "android.hardware.audio@4.0-impl.gts3l",
defaults: ["android.hardware.audio-impl_gts3l"],
shared_libs: [
"android.hardware.audio@4.0",
"android.hardware.audio.common@4.0",
"android.hardware.audio.common@4.0-util",
],
cflags: [
"-DMAJOR_VERSION=4",
"-DMINOR_VERSION=0",
"-include common/all-versions/VersionMacro.h",
]
}
cc_library_shared {
name: "android.hardware.audio@5.0-impl.gts3l",
defaults: ["android.hardware.audio-impl_gts3l"],
shared_libs: [
"android.hardware.audio@5.0",
"android.hardware.audio.common@5.0",
"android.hardware.audio.common@5.0-util",
],
cflags: [
"-DMAJOR_VERSION=5",
"-DMINOR_VERSION=0",
"-include common/all-versions/VersionMacro.h",
]
}

View file

@ -0,0 +1,192 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "core/default/Conversions.h"
#include <stdio.h>
#include <log/log.h>
namespace android {
namespace hardware {
namespace audio {
namespace CPP_VERSION {
namespace implementation {
std::string deviceAddressToHal(const DeviceAddress& address) {
// HAL assumes that the address is NUL-terminated.
char halAddress[AUDIO_DEVICE_MAX_ADDRESS_LEN];
memset(halAddress, 0, sizeof(halAddress));
uint32_t halDevice = static_cast<uint32_t>(address.device);
const bool isInput = (halDevice & AUDIO_DEVICE_BIT_IN) != 0;
if (isInput) halDevice &= ~AUDIO_DEVICE_BIT_IN;
if ((!isInput && (halDevice & AUDIO_DEVICE_OUT_ALL_A2DP) != 0) ||
(isInput && (halDevice & AUDIO_DEVICE_IN_BLUETOOTH_A2DP) != 0)) {
snprintf(halAddress, sizeof(halAddress), "%02X:%02X:%02X:%02X:%02X:%02X",
address.address.mac[0], address.address.mac[1], address.address.mac[2],
address.address.mac[3], address.address.mac[4], address.address.mac[5]);
} else if ((!isInput && (halDevice & AUDIO_DEVICE_OUT_IP) != 0) ||
(isInput && (halDevice & AUDIO_DEVICE_IN_IP) != 0)) {
snprintf(halAddress, sizeof(halAddress), "%d.%d.%d.%d", address.address.ipv4[0],
address.address.ipv4[1], address.address.ipv4[2], address.address.ipv4[3]);
} else if ((!isInput && (halDevice & AUDIO_DEVICE_OUT_ALL_USB) != 0) ||
(isInput && (halDevice & AUDIO_DEVICE_IN_ALL_USB) != 0)) {
snprintf(halAddress, sizeof(halAddress), "card=%d;device=%d", address.address.alsa.card,
address.address.alsa.device);
} else if ((!isInput && (halDevice & AUDIO_DEVICE_OUT_BUS) != 0) ||
(isInput && (halDevice & AUDIO_DEVICE_IN_BUS) != 0)) {
snprintf(halAddress, sizeof(halAddress), "%s", address.busAddress.c_str());
} else if ((!isInput && (halDevice & AUDIO_DEVICE_OUT_REMOTE_SUBMIX)) != 0 ||
(isInput && (halDevice & AUDIO_DEVICE_IN_REMOTE_SUBMIX) != 0)) {
snprintf(halAddress, sizeof(halAddress), "%s", address.rSubmixAddress.c_str());
}
return halAddress;
}
#if MAJOR_VERSION >= 4
status_t deviceAddressFromHal(audio_devices_t device, const char* halAddress,
DeviceAddress* address) {
if (address == nullptr) {
return BAD_VALUE;
}
address->device = AudioDevice(device);
if (halAddress == nullptr || strnlen(halAddress, AUDIO_DEVICE_MAX_ADDRESS_LEN) == 0) {
return OK;
}
const bool isInput = (device & AUDIO_DEVICE_BIT_IN) != 0;
if (isInput) device &= ~AUDIO_DEVICE_BIT_IN;
if ((!isInput && (device & AUDIO_DEVICE_OUT_ALL_A2DP) != 0) ||
(isInput && (device & AUDIO_DEVICE_IN_BLUETOOTH_A2DP) != 0)) {
int status =
sscanf(halAddress, "%hhX:%hhX:%hhX:%hhX:%hhX:%hhX", &address->address.mac[0],
&address->address.mac[1], &address->address.mac[2], &address->address.mac[3],
&address->address.mac[4], &address->address.mac[5]);
return status == 6 ? OK : BAD_VALUE;
} else if ((!isInput && (device & AUDIO_DEVICE_OUT_IP) != 0) ||
(isInput && (device & AUDIO_DEVICE_IN_IP) != 0)) {
int status =
sscanf(halAddress, "%hhu.%hhu.%hhu.%hhu", &address->address.ipv4[0],
&address->address.ipv4[1], &address->address.ipv4[2], &address->address.ipv4[3]);
return status == 4 ? OK : BAD_VALUE;
} else if ((!isInput && (device & AUDIO_DEVICE_OUT_ALL_USB)) != 0 ||
(isInput && (device & AUDIO_DEVICE_IN_ALL_USB)) != 0) {
int status = sscanf(halAddress, "card=%d;device=%d", &address->address.alsa.card,
&address->address.alsa.device);
return status == 2 ? OK : BAD_VALUE;
} else if ((!isInput && (device & AUDIO_DEVICE_OUT_BUS) != 0) ||
(isInput && (device & AUDIO_DEVICE_IN_BUS) != 0)) {
address->busAddress = halAddress;
return OK;
} else if ((!isInput && (device & AUDIO_DEVICE_OUT_REMOTE_SUBMIX)) != 0 ||
(isInput && (device & AUDIO_DEVICE_IN_REMOTE_SUBMIX) != 0)) {
address->rSubmixAddress = halAddress;
return OK;
}
address->busAddress = halAddress;
return OK;
}
AudioMicrophoneChannelMapping halToChannelMapping(audio_microphone_channel_mapping_t mapping) {
switch (mapping) {
case AUDIO_MICROPHONE_CHANNEL_MAPPING_UNUSED:
return AudioMicrophoneChannelMapping::UNUSED;
case AUDIO_MICROPHONE_CHANNEL_MAPPING_DIRECT:
return AudioMicrophoneChannelMapping::DIRECT;
case AUDIO_MICROPHONE_CHANNEL_MAPPING_PROCESSED:
return AudioMicrophoneChannelMapping::PROCESSED;
default:
ALOGE("Invalid channel mapping type: %d", mapping);
return AudioMicrophoneChannelMapping::UNUSED;
}
}
AudioMicrophoneLocation halToLocation(audio_microphone_location_t location) {
switch (location) {
default:
case AUDIO_MICROPHONE_LOCATION_UNKNOWN:
return AudioMicrophoneLocation::UNKNOWN;
case AUDIO_MICROPHONE_LOCATION_MAINBODY:
return AudioMicrophoneLocation::MAINBODY;
case AUDIO_MICROPHONE_LOCATION_MAINBODY_MOVABLE:
return AudioMicrophoneLocation::MAINBODY_MOVABLE;
case AUDIO_MICROPHONE_LOCATION_PERIPHERAL:
return AudioMicrophoneLocation::PERIPHERAL;
}
}
AudioMicrophoneDirectionality halToDirectionality(audio_microphone_directionality_t dir) {
switch (dir) {
default:
case AUDIO_MICROPHONE_DIRECTIONALITY_UNKNOWN:
return AudioMicrophoneDirectionality::UNKNOWN;
case AUDIO_MICROPHONE_DIRECTIONALITY_OMNI:
return AudioMicrophoneDirectionality::OMNI;
case AUDIO_MICROPHONE_DIRECTIONALITY_BI_DIRECTIONAL:
return AudioMicrophoneDirectionality::BI_DIRECTIONAL;
case AUDIO_MICROPHONE_DIRECTIONALITY_CARDIOID:
return AudioMicrophoneDirectionality::CARDIOID;
case AUDIO_MICROPHONE_DIRECTIONALITY_HYPER_CARDIOID:
return AudioMicrophoneDirectionality::HYPER_CARDIOID;
case AUDIO_MICROPHONE_DIRECTIONALITY_SUPER_CARDIOID:
return AudioMicrophoneDirectionality::SUPER_CARDIOID;
}
}
bool halToMicrophoneCharacteristics(MicrophoneInfo* pDst,
const struct audio_microphone_characteristic_t& src) {
bool status = false;
if (pDst != NULL) {
pDst->deviceId = src.device_id;
if (deviceAddressFromHal(src.device, src.address, &pDst->deviceAddress) != OK) {
return false;
}
pDst->channelMapping.resize(AUDIO_CHANNEL_COUNT_MAX);
for (size_t ch = 0; ch < pDst->channelMapping.size(); ch++) {
pDst->channelMapping[ch] = halToChannelMapping(src.channel_mapping[ch]);
}
pDst->location = halToLocation(src.location);
pDst->group = (AudioMicrophoneGroup)src.group;
pDst->indexInTheGroup = (uint32_t)src.index_in_the_group;
pDst->sensitivity = src.sensitivity;
pDst->maxSpl = src.max_spl;
pDst->minSpl = src.min_spl;
pDst->directionality = halToDirectionality(src.directionality);
pDst->frequencyResponse.resize(src.num_frequency_responses);
for (size_t k = 0; k < src.num_frequency_responses; k++) {
pDst->frequencyResponse[k].frequency = src.frequency_responses[0][k];
pDst->frequencyResponse[k].level = src.frequency_responses[1][k];
}
pDst->position.x = src.geometric_location.x;
pDst->position.y = src.geometric_location.y;
pDst->position.z = src.geometric_location.z;
pDst->orientation.x = src.orientation.x;
pDst->orientation.y = src.orientation.y;
pDst->orientation.z = src.orientation.z;
status = true;
}
return status;
}
#endif
} // namespace implementation
} // namespace CPP_VERSION
} // namespace audio
} // namespace hardware
} // namespace android

View file

@ -0,0 +1,390 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_TAG "DeviceHAL"
#include "core/default/Device.h"
#include <HidlUtils.h>
#include "core/default/Conversions.h"
#include "core/default/StreamIn.h"
#include "core/default/StreamOut.h"
#include "core/default/Util.h"
//#define LOG_NDEBUG 0
#include <memory.h>
#include <string.h>
#include <algorithm>
#include <android/log.h>
namespace android {
namespace hardware {
namespace audio {
namespace CPP_VERSION {
namespace implementation {
using ::android::hardware::audio::common::CPP_VERSION::implementation::HidlUtils;
Device::Device(audio_hw_device_t* device) : mDevice(device) {}
Device::~Device() {
int status = audio_hw_device_close(mDevice);
ALOGW_IF(status, "Error closing audio hw device %p: %s", mDevice, strerror(-status));
mDevice = nullptr;
}
Result Device::analyzeStatus(const char* funcName, int status,
const std::vector<int>& ignoreErrors) {
return util::analyzeStatus("Device", funcName, status, ignoreErrors);
}
void Device::closeInputStream(audio_stream_in_t* stream) {
mDevice->close_input_stream(mDevice, stream);
}
void Device::closeOutputStream(audio_stream_out_t* stream) {
mDevice->close_output_stream(mDevice, stream);
}
char* Device::halGetParameters(const char* keys) {
return mDevice->get_parameters(mDevice, keys);
}
int Device::halSetParameters(const char* keysAndValues) {
return mDevice->set_parameters(mDevice, keysAndValues);
}
// Methods from ::android::hardware::audio::CPP_VERSION::IDevice follow.
Return<Result> Device::initCheck() {
return analyzeStatus("init_check", mDevice->init_check(mDevice));
}
Return<Result> Device::setMasterVolume(float volume) {
if (mDevice->set_master_volume == NULL) {
return Result::NOT_SUPPORTED;
}
if (!isGainNormalized(volume)) {
ALOGW("Can not set a master volume (%f) outside [0,1]", volume);
return Result::INVALID_ARGUMENTS;
}
return analyzeStatus("set_master_volume", mDevice->set_master_volume(mDevice, volume));
}
Return<void> Device::getMasterVolume(getMasterVolume_cb _hidl_cb) {
Result retval(Result::NOT_SUPPORTED);
float volume = 0;
if (mDevice->get_master_volume != NULL) {
retval = analyzeStatus("get_master_volume", mDevice->get_master_volume(mDevice, &volume));
}
_hidl_cb(retval, volume);
return Void();
}
Return<Result> Device::setMicMute(bool mute) {
return analyzeStatus("set_mic_mute", mDevice->set_mic_mute(mDevice, mute));
}
Return<void> Device::getMicMute(getMicMute_cb _hidl_cb) {
bool mute = false;
Result retval = analyzeStatus("get_mic_mute", mDevice->get_mic_mute(mDevice, &mute));
_hidl_cb(retval, mute);
return Void();
}
Return<Result> Device::setMasterMute(bool mute) {
Result retval(Result::NOT_SUPPORTED);
if (mDevice->set_master_mute != NULL) {
retval = analyzeStatus("set_master_mute", mDevice->set_master_mute(mDevice, mute));
}
return retval;
}
Return<void> Device::getMasterMute(getMasterMute_cb _hidl_cb) {
Result retval(Result::NOT_SUPPORTED);
bool mute = false;
if (mDevice->get_master_mute != NULL) {
retval = analyzeStatus("get_master_mute", mDevice->get_master_mute(mDevice, &mute));
}
_hidl_cb(retval, mute);
return Void();
}
Return<void> Device::getInputBufferSize(const AudioConfig& config, getInputBufferSize_cb _hidl_cb) {
audio_config_t halConfig;
HidlUtils::audioConfigToHal(config, &halConfig);
size_t halBufferSize = mDevice->get_input_buffer_size(mDevice, &halConfig);
Result retval(Result::INVALID_ARGUMENTS);
uint64_t bufferSize = 0;
if (halBufferSize != 0) {
retval = Result::OK;
bufferSize = halBufferSize;
}
_hidl_cb(retval, bufferSize);
return Void();
}
std::tuple<Result, sp<IStreamOut>> Device::openOutputStreamImpl(int32_t ioHandle,
const DeviceAddress& device,
const AudioConfig& config,
AudioOutputFlagBitfield flags,
AudioConfig* suggestedConfig) {
audio_config_t halConfig;
HidlUtils::audioConfigToHal(config, &halConfig);
audio_stream_out_t* halStream;
ALOGV(
"open_output_stream handle: %d devices: %x flags: %#x "
"srate: %d format %#x channels %x address %s",
ioHandle, static_cast<audio_devices_t>(device.device),
static_cast<audio_output_flags_t>(flags), halConfig.sample_rate, halConfig.format,
halConfig.channel_mask, deviceAddressToHal(device).c_str());
int status =
mDevice->open_output_stream(mDevice, ioHandle, static_cast<audio_devices_t>(device.device),
static_cast<audio_output_flags_t>(flags), &halConfig,
&halStream, deviceAddressToHal(device).c_str());
ALOGV("open_output_stream status %d stream %p", status, halStream);
sp<IStreamOut> streamOut;
if (status == OK) {
streamOut = new StreamOut(this, halStream);
}
HidlUtils::audioConfigFromHal(halConfig, suggestedConfig);
return {analyzeStatus("open_output_stream", status, {EINVAL} /*ignore*/), streamOut};
}
std::tuple<Result, sp<IStreamIn>> Device::openInputStreamImpl(
int32_t ioHandle, const DeviceAddress& device, const AudioConfig& config,
AudioInputFlagBitfield flags, AudioSource source, AudioConfig* suggestedConfig) {
audio_config_t halConfig;
HidlUtils::audioConfigToHal(config, &halConfig);
audio_stream_in_t* halStream;
ALOGV(
"open_input_stream handle: %d devices: %x flags: %#x "
"srate: %d format %#x channels %x address %s source %d",
ioHandle, static_cast<audio_devices_t>(device.device),
static_cast<audio_input_flags_t>(flags), halConfig.sample_rate, halConfig.format,
halConfig.channel_mask, deviceAddressToHal(device).c_str(),
static_cast<audio_source_t>(source));
int status = mDevice->open_input_stream(
mDevice, ioHandle, static_cast<audio_devices_t>(device.device), &halConfig, &halStream,
static_cast<audio_input_flags_t>(flags), deviceAddressToHal(device).c_str(),
static_cast<audio_source_t>(source));
ALOGV("open_input_stream status %d stream %p", status, halStream);
sp<IStreamIn> streamIn;
if (status == OK) {
streamIn = new StreamIn(this, halStream);
}
HidlUtils::audioConfigFromHal(halConfig, suggestedConfig);
return {analyzeStatus("open_input_stream", status, {EINVAL} /*ignore*/), streamIn};
}
#if MAJOR_VERSION == 2
Return<void> Device::openOutputStream(int32_t ioHandle, const DeviceAddress& device,
const AudioConfig& config, AudioOutputFlagBitfield flags,
openOutputStream_cb _hidl_cb) {
AudioConfig suggestedConfig;
auto [result, streamOut] =
openOutputStreamImpl(ioHandle, device, config, flags, &suggestedConfig);
_hidl_cb(result, streamOut, suggestedConfig);
return Void();
}
Return<void> Device::openInputStream(int32_t ioHandle, const DeviceAddress& device,
const AudioConfig& config, AudioInputFlagBitfield flags,
AudioSource source, openInputStream_cb _hidl_cb) {
AudioConfig suggestedConfig;
auto [result, streamIn] =
openInputStreamImpl(ioHandle, device, config, flags, source, &suggestedConfig);
_hidl_cb(result, streamIn, suggestedConfig);
return Void();
}
#elif MAJOR_VERSION >= 4
Return<void> Device::openOutputStream(int32_t ioHandle, const DeviceAddress& device,
const AudioConfig& config, AudioOutputFlagBitfield flags,
const SourceMetadata& sourceMetadata,
openOutputStream_cb _hidl_cb) {
AudioConfig suggestedConfig;
auto [result, streamOut] =
openOutputStreamImpl(ioHandle, device, config, flags, &suggestedConfig);
if (streamOut) {
streamOut->updateSourceMetadata(sourceMetadata);
}
_hidl_cb(result, streamOut, suggestedConfig);
return Void();
}
Return<void> Device::openInputStream(int32_t ioHandle, const DeviceAddress& device,
const AudioConfig& config, AudioInputFlagBitfield flags,
const SinkMetadata& sinkMetadata,
openInputStream_cb _hidl_cb) {
if (sinkMetadata.tracks.size() == 0) {
// This should never happen, the framework must not create as stream
// if there is no client
ALOGE("openInputStream called without tracks connected");
_hidl_cb(Result::INVALID_ARGUMENTS, nullptr, AudioConfig());
return Void();
}
// Pick the first one as the main.
AudioSource source = sinkMetadata.tracks[0].source;
AudioConfig suggestedConfig;
auto [result, streamIn] =
openInputStreamImpl(ioHandle, device, config, flags, source, &suggestedConfig);
if (streamIn) {
streamIn->updateSinkMetadata(sinkMetadata);
}
_hidl_cb(result, streamIn, suggestedConfig);
return Void();
}
#endif /* MAJOR_VERSION */
Return<bool> Device::supportsAudioPatches() {
return version() >= AUDIO_DEVICE_API_VERSION_3_0;
}
Return<void> Device::createAudioPatch(const hidl_vec<AudioPortConfig>& sources,
const hidl_vec<AudioPortConfig>& sinks,
createAudioPatch_cb _hidl_cb) {
Result retval(Result::NOT_SUPPORTED);
AudioPatchHandle patch = 0;
if (version() >= AUDIO_DEVICE_API_VERSION_3_0) {
std::unique_ptr<audio_port_config[]> halSources(HidlUtils::audioPortConfigsToHal(sources));
std::unique_ptr<audio_port_config[]> halSinks(HidlUtils::audioPortConfigsToHal(sinks));
audio_patch_handle_t halPatch = AUDIO_PATCH_HANDLE_NONE;
retval = analyzeStatus("create_audio_patch",
mDevice->create_audio_patch(mDevice, sources.size(), &halSources[0],
sinks.size(), &halSinks[0], &halPatch));
if (retval == Result::OK) {
patch = static_cast<AudioPatchHandle>(halPatch);
}
}
_hidl_cb(retval, patch);
return Void();
}
Return<Result> Device::releaseAudioPatch(int32_t patch) {
if (version() >= AUDIO_DEVICE_API_VERSION_3_0) {
return analyzeStatus(
"release_audio_patch",
mDevice->release_audio_patch(mDevice, static_cast<audio_patch_handle_t>(patch)));
}
return Result::NOT_SUPPORTED;
}
Return<void> Device::getAudioPort(const AudioPort& port, getAudioPort_cb _hidl_cb) {
audio_port halPort;
HidlUtils::audioPortToHal(port, &halPort);
Result retval = analyzeStatus("get_audio_port", mDevice->get_audio_port(mDevice, &halPort));
AudioPort resultPort = port;
if (retval == Result::OK) {
HidlUtils::audioPortFromHal(halPort, &resultPort);
}
_hidl_cb(retval, resultPort);
return Void();
}
Return<Result> Device::setAudioPortConfig(const AudioPortConfig& config) {
if (version() >= AUDIO_DEVICE_API_VERSION_3_0) {
struct audio_port_config halPortConfig;
HidlUtils::audioPortConfigToHal(config, &halPortConfig);
return analyzeStatus("set_audio_port_config",
mDevice->set_audio_port_config(mDevice, &halPortConfig));
}
return Result::NOT_SUPPORTED;
}
#if MAJOR_VERSION == 2
Return<AudioHwSync> Device::getHwAvSync() {
int halHwAvSync;
Result retval = getParam(AudioParameter::keyHwAvSync, &halHwAvSync);
return retval == Result::OK ? halHwAvSync : AUDIO_HW_SYNC_INVALID;
}
#elif MAJOR_VERSION >= 4
Return<void> Device::getHwAvSync(getHwAvSync_cb _hidl_cb) {
int halHwAvSync;
Result retval = getParam(AudioParameter::keyHwAvSync, &halHwAvSync);
_hidl_cb(retval, halHwAvSync);
return Void();
}
#endif
Return<Result> Device::setScreenState(bool turnedOn) {
return setParam(AudioParameter::keyScreenState, turnedOn);
}
#if MAJOR_VERSION == 2
Return<void> Device::getParameters(const hidl_vec<hidl_string>& keys, getParameters_cb _hidl_cb) {
getParametersImpl({}, keys, _hidl_cb);
return Void();
}
Return<Result> Device::setParameters(const hidl_vec<ParameterValue>& parameters) {
return setParametersImpl({} /* context */, parameters);
}
#elif MAJOR_VERSION >= 4
Return<void> Device::getParameters(const hidl_vec<ParameterValue>& context,
const hidl_vec<hidl_string>& keys, getParameters_cb _hidl_cb) {
getParametersImpl(context, keys, _hidl_cb);
return Void();
}
Return<Result> Device::setParameters(const hidl_vec<ParameterValue>& context,
const hidl_vec<ParameterValue>& parameters) {
return setParametersImpl(context, parameters);
}
#endif
#if MAJOR_VERSION == 2
Return<void> Device::debugDump(const hidl_handle& fd) {
return debug(fd, {});
}
#endif
Return<void> Device::debug(const hidl_handle& fd, const hidl_vec<hidl_string>& /* options */) {
if (fd.getNativeHandle() != nullptr && fd->numFds == 1) {
analyzeStatus("dump", mDevice->dump(mDevice, fd->data[0]));
}
return Void();
}
#if MAJOR_VERSION >= 4
Return<void> Device::getMicrophones(getMicrophones_cb _hidl_cb) {
Result retval = Result::NOT_SUPPORTED;
size_t actual_mics = AUDIO_MICROPHONE_MAX_COUNT;
audio_microphone_characteristic_t mic_array[AUDIO_MICROPHONE_MAX_COUNT];
hidl_vec<MicrophoneInfo> microphones;
if (mDevice->get_microphones != NULL &&
mDevice->get_microphones(mDevice, &mic_array[0], &actual_mics) == 0) {
microphones.resize(actual_mics);
for (size_t i = 0; i < actual_mics; ++i) {
halToMicrophoneCharacteristics(&microphones[i], mic_array[i]);
}
retval = Result::OK;
}
_hidl_cb(retval, microphones);
return Void();
}
Return<Result> Device::setConnectedState(const DeviceAddress& address, bool connected) {
auto key = connected ? AudioParameter::keyStreamConnect : AudioParameter::keyStreamDisconnect;
return setParam(key, address);
}
#endif
} // namespace implementation
} // namespace CPP_VERSION
} // namespace audio
} // namespace hardware
} // namespace android

View file

@ -0,0 +1,120 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_TAG "DevicesFactoryHAL"
#include "core/default/DevicesFactory.h"
#include "core/default/Device.h"
#include "core/default/PrimaryDevice.h"
#include <string.h>
#include <android/log.h>
namespace android {
namespace hardware {
namespace audio {
namespace CPP_VERSION {
namespace implementation {
#if MAJOR_VERSION == 2
Return<void> DevicesFactory::openDevice(IDevicesFactory::Device device, openDevice_cb _hidl_cb) {
switch (device) {
case IDevicesFactory::Device::PRIMARY:
return openDevice<PrimaryDevice>(AUDIO_HARDWARE_MODULE_ID_PRIMARY, _hidl_cb);
case IDevicesFactory::Device::A2DP:
return openDevice(AUDIO_HARDWARE_MODULE_ID_A2DP, _hidl_cb);
case IDevicesFactory::Device::USB:
return openDevice(AUDIO_HARDWARE_MODULE_ID_USB, _hidl_cb);
case IDevicesFactory::Device::R_SUBMIX:
return openDevice(AUDIO_HARDWARE_MODULE_ID_REMOTE_SUBMIX, _hidl_cb);
case IDevicesFactory::Device::STUB:
return openDevice(AUDIO_HARDWARE_MODULE_ID_STUB, _hidl_cb);
}
_hidl_cb(Result::INVALID_ARGUMENTS, nullptr);
return Void();
}
#elif MAJOR_VERSION >= 4
Return<void> DevicesFactory::openDevice(const hidl_string& moduleName, openDevice_cb _hidl_cb) {
if (moduleName == AUDIO_HARDWARE_MODULE_ID_PRIMARY) {
return openDevice<PrimaryDevice>(moduleName.c_str(), _hidl_cb);
}
return openDevice(moduleName.c_str(), _hidl_cb);
}
Return<void> DevicesFactory::openPrimaryDevice(openPrimaryDevice_cb _hidl_cb) {
return openDevice<PrimaryDevice>(AUDIO_HARDWARE_MODULE_ID_PRIMARY, _hidl_cb);
}
#endif
Return<void> DevicesFactory::openDevice(const char* moduleName, openDevice_cb _hidl_cb) {
return openDevice<implementation::Device>(moduleName, _hidl_cb);
}
template <class DeviceShim, class Callback>
Return<void> DevicesFactory::openDevice(const char* moduleName, Callback _hidl_cb) {
audio_hw_device_t* halDevice;
Result retval(Result::INVALID_ARGUMENTS);
sp<DeviceShim> result;
int halStatus = loadAudioInterface(moduleName, &halDevice);
if (halStatus == OK) {
result = new DeviceShim(halDevice);
retval = Result::OK;
} else if (halStatus == -EINVAL) {
retval = Result::NOT_INITIALIZED;
}
_hidl_cb(retval, result);
return Void();
}
// static
int DevicesFactory::loadAudioInterface(const char* if_name, audio_hw_device_t** dev) {
const hw_module_t* mod;
int rc;
rc = hw_get_module_by_class(AUDIO_HARDWARE_MODULE_ID, if_name, &mod);
if (rc) {
ALOGE("%s couldn't load audio hw module %s.%s (%s)", __func__, AUDIO_HARDWARE_MODULE_ID,
if_name, strerror(-rc));
goto out;
}
rc = audio_hw_device_open(mod, dev);
if (rc) {
ALOGE("%s couldn't open audio hw device in %s.%s (%s)", __func__, AUDIO_HARDWARE_MODULE_ID,
if_name, strerror(-rc));
goto out;
}
if ((*dev)->common.version < AUDIO_DEVICE_API_VERSION_MIN) {
ALOGE("%s wrong audio hw device version %04x", __func__, (*dev)->common.version);
rc = -EINVAL;
audio_hw_device_close(*dev);
goto out;
}
return OK;
out:
*dev = NULL;
return rc;
}
IDevicesFactory* HIDL_FETCH_IDevicesFactory(const char* name) {
return strcmp(name, "default") == 0 ? new DevicesFactory() : nullptr;
}
} // namespace implementation
} // namespace CPP_VERSION
} // namespace audio
} // namespace hardware
} // namespace android

View file

@ -0,0 +1,215 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "core/default/ParametersUtil.h"
#include "core/default/Conversions.h"
#include "core/default/Util.h"
#include <system/audio.h>
#include <tinyalsa/asoundlib.h>
namespace android {
namespace hardware {
namespace audio {
namespace CPP_VERSION {
namespace implementation {
constexpr int SLOT_POSITIONS_0[] = { 0, 1, 0, 1 };
constexpr int SLOT_POSITIONS_90[] = { 1, 1, 0, 0 };
constexpr int SLOT_POSITIONS_180[] = { 1, 0, 1, 0 };
constexpr int SLOT_POSITIONS_270[] = { 0, 0, 1, 1 };
void setMixerValueByName(mixer *mixer, const char *name, int value) {
const auto ctl = mixer_get_ctl_by_name(mixer, name);
if (ctl == nullptr) {
ALOGE("Failed to find mixer ctl for %s", name);
return;
}
if (mixer_ctl_set_value(ctl, 0, value) < 0) {
ALOGE("Failed to set ctl value %d for %s", value, name);
return;
}
}
void setSlotPositions(const int *values) {
const auto mixer = mixer_open(0);
if (mixer == nullptr) {
ALOGE("Failed to open mixer");
return;
}
setMixerValueByName(mixer, "FL ASPRX1 Slot Position", values[0]);
setMixerValueByName(mixer, "FR ASPRX1 Slot Position", values[1]);
setMixerValueByName(mixer, "RL ASPRX1 Slot Position", values[2]);
setMixerValueByName(mixer, "RR ASPRX1 Slot Position", values[3]);
mixer_close(mixer);
};
/** Converts a status_t in Result according to the rules of AudioParameter::get*
* Note: Static method and not private method to avoid leaking status_t dependency
*/
static Result getHalStatusToResult(status_t status) {
switch (status) {
case OK:
return Result::OK;
case BAD_VALUE: // Nothing was returned, probably because the HAL does
// not handle it
return Result::NOT_SUPPORTED;
case INVALID_OPERATION: // Conversion from string to the requested type
// failed
return Result::INVALID_ARGUMENTS;
default: // Should not happen
ALOGW("Unexpected status returned by getParam: %u", status);
return Result::INVALID_ARGUMENTS;
}
}
Result ParametersUtil::getParam(const char* name, bool* value) {
String8 halValue;
Result retval = getParam(name, &halValue);
*value = false;
if (retval == Result::OK) {
if (halValue.empty()) {
return Result::NOT_SUPPORTED;
}
*value = !(halValue == AudioParameter::valueOff);
}
return retval;
}
Result ParametersUtil::getParam(const char* name, int* value) {
const String8 halName(name);
AudioParameter keys;
keys.addKey(halName);
std::unique_ptr<AudioParameter> params = getParams(keys);
return getHalStatusToResult(params->getInt(halName, *value));
}
Result ParametersUtil::getParam(const char* name, String8* value, AudioParameter context) {
const String8 halName(name);
context.addKey(halName);
std::unique_ptr<AudioParameter> params = getParams(context);
return getHalStatusToResult(params->get(halName, *value));
}
void ParametersUtil::getParametersImpl(
const hidl_vec<ParameterValue>& context, const hidl_vec<hidl_string>& keys,
std::function<void(Result retval, const hidl_vec<ParameterValue>& parameters)> cb) {
AudioParameter halKeys;
for (auto& pair : context) {
halKeys.add(String8(pair.key.c_str()), String8(pair.value.c_str()));
}
for (size_t i = 0; i < keys.size(); ++i) {
halKeys.addKey(String8(keys[i].c_str()));
}
std::unique_ptr<AudioParameter> halValues = getParams(halKeys);
Result retval =
(keys.size() == 0 || halValues->size() != 0) ? Result::OK : Result::NOT_SUPPORTED;
hidl_vec<ParameterValue> result;
result.resize(halValues->size());
String8 halKey, halValue;
for (size_t i = 0; i < halValues->size(); ++i) {
status_t status = halValues->getAt(i, halKey, halValue);
if (status != OK) {
result.resize(0);
retval = getHalStatusToResult(status);
break;
}
result[i].key = halKey.string();
result[i].value = halValue.string();
}
cb(retval, result);
}
std::unique_ptr<AudioParameter> ParametersUtil::getParams(const AudioParameter& keys) {
String8 paramsAndValues;
char* halValues = halGetParameters(keys.keysToString().string());
if (halValues != NULL) {
paramsAndValues.setTo(halValues);
free(halValues);
} else {
paramsAndValues.clear();
}
return std::unique_ptr<AudioParameter>(new AudioParameter(paramsAndValues));
}
Result ParametersUtil::setParam(const char* name, const char* value) {
AudioParameter param;
param.add(String8(name), String8(value));
return setParams(param);
}
Result ParametersUtil::setParam(const char* name, bool value) {
AudioParameter param;
param.add(String8(name), String8(value ? AudioParameter::valueOn : AudioParameter::valueOff));
return setParams(param);
}
Result ParametersUtil::setParam(const char* name, int value) {
AudioParameter param;
param.addInt(String8(name), value);
return setParams(param);
}
Result ParametersUtil::setParam(const char* name, float value) {
AudioParameter param;
param.addFloat(String8(name), value);
return setParams(param);
}
Result ParametersUtil::setParametersImpl(const hidl_vec<ParameterValue>& context,
const hidl_vec<ParameterValue>& parameters) {
AudioParameter params;
for (auto& pair : context) {
params.add(String8(pair.key.c_str()), String8(pair.value.c_str()));
}
for (size_t i = 0; i < parameters.size(); ++i) {
if (parameters[i].key == "rotation") {
if (parameters[i].value == "0") {
setSlotPositions(SLOT_POSITIONS_0);
} else if (parameters[i].value == "90") {
setSlotPositions(SLOT_POSITIONS_90);
} else if (parameters[i].value == "180") {
setSlotPositions(SLOT_POSITIONS_180);
} else if (parameters[i].value == "270") {
setSlotPositions(SLOT_POSITIONS_270);
}
continue;
}
params.add(String8(parameters[i].key.c_str()), String8(parameters[i].value.c_str()));
}
return setParams(params);
}
Result ParametersUtil::setParam(const char* name, const DeviceAddress& address) {
AudioParameter params(String8(deviceAddressToHal(address).c_str()));
params.addInt(String8(name), int(address.device));
return setParams(params);
}
Result ParametersUtil::setParams(const AudioParameter& param) {
int halStatus = halSetParameters(param.toString().string());
return util::analyzeStatus(halStatus);
}
} // namespace implementation
} // namespace CPP_VERSION
} // namespace audio
} // namespace hardware
} // namespace android

View file

@ -0,0 +1,326 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_TAG "PrimaryDeviceHAL"
#include "core/default/PrimaryDevice.h"
#include "core/default/Util.h"
#if MAJOR_VERSION >= 4
#include <cmath>
#endif
namespace android {
namespace hardware {
namespace audio {
namespace CPP_VERSION {
namespace implementation {
PrimaryDevice::PrimaryDevice(audio_hw_device_t* device) : mDevice(new Device(device)) {}
PrimaryDevice::~PrimaryDevice() {}
// Methods from ::android::hardware::audio::CPP_VERSION::IDevice follow.
Return<Result> PrimaryDevice::initCheck() {
return mDevice->initCheck();
}
Return<Result> PrimaryDevice::setMasterVolume(float volume) {
return mDevice->setMasterVolume(volume);
}
Return<void> PrimaryDevice::getMasterVolume(getMasterVolume_cb _hidl_cb) {
return mDevice->getMasterVolume(_hidl_cb);
}
Return<Result> PrimaryDevice::setMicMute(bool mute) {
return mDevice->setMicMute(mute);
}
Return<void> PrimaryDevice::getMicMute(getMicMute_cb _hidl_cb) {
return mDevice->getMicMute(_hidl_cb);
}
Return<Result> PrimaryDevice::setMasterMute(bool mute) {
return mDevice->setMasterMute(mute);
}
Return<void> PrimaryDevice::getMasterMute(getMasterMute_cb _hidl_cb) {
return mDevice->getMasterMute(_hidl_cb);
}
Return<void> PrimaryDevice::getInputBufferSize(const AudioConfig& config,
getInputBufferSize_cb _hidl_cb) {
return mDevice->getInputBufferSize(config, _hidl_cb);
}
#if MAJOR_VERSION == 2
Return<void> PrimaryDevice::openOutputStream(int32_t ioHandle, const DeviceAddress& device,
const AudioConfig& config,
AudioOutputFlagBitfield flags,
openOutputStream_cb _hidl_cb) {
return mDevice->openOutputStream(ioHandle, device, config, flags, _hidl_cb);
}
Return<void> PrimaryDevice::openInputStream(int32_t ioHandle, const DeviceAddress& device,
const AudioConfig& config, AudioInputFlagBitfield flags,
AudioSource source, openInputStream_cb _hidl_cb) {
return mDevice->openInputStream(ioHandle, device, config, flags, source, _hidl_cb);
}
#elif MAJOR_VERSION >= 4
Return<void> PrimaryDevice::openOutputStream(int32_t ioHandle, const DeviceAddress& device,
const AudioConfig& config,
AudioOutputFlagBitfield flags,
const SourceMetadata& sourceMetadata,
openOutputStream_cb _hidl_cb) {
return mDevice->openOutputStream(ioHandle, device, config, flags, sourceMetadata, _hidl_cb);
}
Return<void> PrimaryDevice::openInputStream(int32_t ioHandle, const DeviceAddress& device,
const AudioConfig& config, AudioInputFlagBitfield flags,
const SinkMetadata& sinkMetadata,
openInputStream_cb _hidl_cb) {
return mDevice->openInputStream(ioHandle, device, config, flags, sinkMetadata, _hidl_cb);
}
#endif
Return<bool> PrimaryDevice::supportsAudioPatches() {
return mDevice->supportsAudioPatches();
}
Return<void> PrimaryDevice::createAudioPatch(const hidl_vec<AudioPortConfig>& sources,
const hidl_vec<AudioPortConfig>& sinks,
createAudioPatch_cb _hidl_cb) {
return mDevice->createAudioPatch(sources, sinks, _hidl_cb);
}
Return<Result> PrimaryDevice::releaseAudioPatch(int32_t patch) {
return mDevice->releaseAudioPatch(patch);
}
Return<void> PrimaryDevice::getAudioPort(const AudioPort& port, getAudioPort_cb _hidl_cb) {
return mDevice->getAudioPort(port, _hidl_cb);
}
Return<Result> PrimaryDevice::setAudioPortConfig(const AudioPortConfig& config) {
return mDevice->setAudioPortConfig(config);
}
Return<Result> PrimaryDevice::setScreenState(bool turnedOn) {
return mDevice->setScreenState(turnedOn);
}
#if MAJOR_VERSION == 2
Return<AudioHwSync> PrimaryDevice::getHwAvSync() {
return mDevice->getHwAvSync();
}
Return<void> PrimaryDevice::getParameters(const hidl_vec<hidl_string>& keys,
getParameters_cb _hidl_cb) {
return mDevice->getParameters(keys, _hidl_cb);
}
Return<Result> PrimaryDevice::setParameters(const hidl_vec<ParameterValue>& parameters) {
return mDevice->setParameters(parameters);
}
Return<void> PrimaryDevice::debugDump(const hidl_handle& fd) {
return mDevice->debugDump(fd);
}
#elif MAJOR_VERSION >= 4
Return<void> PrimaryDevice::getHwAvSync(getHwAvSync_cb _hidl_cb) {
return mDevice->getHwAvSync(_hidl_cb);
}
Return<void> PrimaryDevice::getParameters(const hidl_vec<ParameterValue>& context,
const hidl_vec<hidl_string>& keys,
getParameters_cb _hidl_cb) {
return mDevice->getParameters(context, keys, _hidl_cb);
}
Return<Result> PrimaryDevice::setParameters(const hidl_vec<ParameterValue>& context,
const hidl_vec<ParameterValue>& parameters) {
return mDevice->setParameters(context, parameters);
}
Return<void> PrimaryDevice::getMicrophones(getMicrophones_cb _hidl_cb) {
return mDevice->getMicrophones(_hidl_cb);
}
Return<Result> PrimaryDevice::setConnectedState(const DeviceAddress& address, bool connected) {
return mDevice->setConnectedState(address, connected);
}
#endif
// Methods from ::android::hardware::audio::CPP_VERSION::IPrimaryDevice follow.
Return<Result> PrimaryDevice::setVoiceVolume(float volume) {
if (!isGainNormalized(volume)) {
ALOGW("Can not set a voice volume (%f) outside [0,1]", volume);
return Result::INVALID_ARGUMENTS;
}
return mDevice->analyzeStatus("set_voice_volume",
mDevice->device()->set_voice_volume(mDevice->device(), volume));
}
Return<Result> PrimaryDevice::setMode(AudioMode mode) {
// On regular QCOM devices, these parameters are set by QtiTelephonyService,
// which basically listens to vendor.qti.hardware.radio.am callbacks.
// The hardcoded vsid value here is decimal VOICEMMODE1_VSID which one can find
// in {QC_AUDIO_HAL}/hal/voice_extn/voice_extn.c. The current code doesn't
// handle VOICEMMODE2_VSID, but since we don't have any MSIM variants it's totally fine.
// Audio param call_state 2 corresponds to CALL_ACTIVE and 1 to CALL_INACTIVE respectively,
// both of which can be found in {QC_AUDIO_HAL}/hal/voice.h.
mDevice->halSetParameters(mode == AudioMode::IN_CALL ? "call_state=2;vsid=297816064"
: "call_state=1;vsid=297816064");
// INVALID, CURRENT, CNT, MAX are reserved for internal use.
// TODO: remove the values from the HIDL interface
switch (mode) {
case AudioMode::NORMAL:
case AudioMode::RINGTONE:
case AudioMode::IN_CALL:
case AudioMode::IN_COMMUNICATION:
break; // Valid values
default:
return Result::INVALID_ARGUMENTS;
};
return mDevice->analyzeStatus(
"set_mode",
mDevice->device()->set_mode(mDevice->device(), static_cast<audio_mode_t>(mode)));
}
Return<void> PrimaryDevice::getBtScoNrecEnabled(getBtScoNrecEnabled_cb _hidl_cb) {
bool enabled;
Result retval = mDevice->getParam(AudioParameter::keyBtNrec, &enabled);
_hidl_cb(retval, enabled);
return Void();
}
Return<Result> PrimaryDevice::setBtScoNrecEnabled(bool enabled) {
return mDevice->setParam(AudioParameter::keyBtNrec, enabled);
}
Return<void> PrimaryDevice::getBtScoWidebandEnabled(getBtScoWidebandEnabled_cb _hidl_cb) {
bool enabled;
Result retval = mDevice->getParam(AUDIO_PARAMETER_KEY_BT_SCO_WB, &enabled);
_hidl_cb(retval, enabled);
return Void();
}
Return<Result> PrimaryDevice::setBtScoWidebandEnabled(bool enabled) {
return mDevice->setParam(AUDIO_PARAMETER_KEY_BT_SCO_WB, enabled);
}
static const char* convertTtyModeFromHIDL(IPrimaryDevice::TtyMode mode) {
switch (mode) {
case IPrimaryDevice::TtyMode::OFF:
return AUDIO_PARAMETER_VALUE_TTY_OFF;
case IPrimaryDevice::TtyMode::VCO:
return AUDIO_PARAMETER_VALUE_TTY_VCO;
case IPrimaryDevice::TtyMode::HCO:
return AUDIO_PARAMETER_VALUE_TTY_HCO;
case IPrimaryDevice::TtyMode::FULL:
return AUDIO_PARAMETER_VALUE_TTY_FULL;
default:
return nullptr;
}
}
static IPrimaryDevice::TtyMode convertTtyModeToHIDL(const char* halMode) {
if (strcmp(halMode, AUDIO_PARAMETER_VALUE_TTY_OFF) == 0)
return IPrimaryDevice::TtyMode::OFF;
else if (strcmp(halMode, AUDIO_PARAMETER_VALUE_TTY_VCO) == 0)
return IPrimaryDevice::TtyMode::VCO;
else if (strcmp(halMode, AUDIO_PARAMETER_VALUE_TTY_HCO) == 0)
return IPrimaryDevice::TtyMode::HCO;
else if (strcmp(halMode, AUDIO_PARAMETER_VALUE_TTY_FULL) == 0)
return IPrimaryDevice::TtyMode::FULL;
return IPrimaryDevice::TtyMode(-1);
}
Return<void> PrimaryDevice::getTtyMode(getTtyMode_cb _hidl_cb) {
String8 halMode;
Result retval = mDevice->getParam(AUDIO_PARAMETER_KEY_TTY_MODE, &halMode);
if (retval != Result::OK) {
_hidl_cb(retval, TtyMode::OFF);
return Void();
}
TtyMode mode = convertTtyModeToHIDL(halMode);
if (mode == TtyMode(-1)) {
ALOGE("HAL returned invalid TTY value: %s", halMode.c_str());
_hidl_cb(Result::INVALID_STATE, TtyMode::OFF);
return Void();
}
_hidl_cb(Result::OK, mode);
return Void();
}
Return<Result> PrimaryDevice::setTtyMode(IPrimaryDevice::TtyMode mode) {
const char* modeStr = convertTtyModeFromHIDL(mode);
if (modeStr == nullptr) {
ALOGW("Can not set an invalid TTY value: %d", mode);
return Result::INVALID_ARGUMENTS;
}
return mDevice->setParam(AUDIO_PARAMETER_KEY_TTY_MODE, modeStr);
}
Return<void> PrimaryDevice::getHacEnabled(getHacEnabled_cb _hidl_cb) {
bool enabled;
Result retval = mDevice->getParam(AUDIO_PARAMETER_KEY_HAC, &enabled);
_hidl_cb(retval, enabled);
return Void();
}
Return<Result> PrimaryDevice::setHacEnabled(bool enabled) {
return mDevice->setParam(AUDIO_PARAMETER_KEY_HAC, enabled);
}
#if MAJOR_VERSION >= 4
Return<Result> PrimaryDevice::setBtScoHeadsetDebugName(const hidl_string& name) {
return mDevice->setParam(AUDIO_PARAMETER_KEY_BT_SCO_HEADSET_NAME, name.c_str());
}
Return<void> PrimaryDevice::getBtHfpEnabled(getBtHfpEnabled_cb _hidl_cb) {
bool enabled;
Result retval = mDevice->getParam(AUDIO_PARAMETER_KEY_HFP_ENABLE, &enabled);
_hidl_cb(retval, enabled);
return Void();
}
Return<Result> PrimaryDevice::setBtHfpEnabled(bool enabled) {
return mDevice->setParam(AUDIO_PARAMETER_KEY_HFP_ENABLE, enabled);
}
Return<Result> PrimaryDevice::setBtHfpSampleRate(uint32_t sampleRateHz) {
return mDevice->setParam(AUDIO_PARAMETER_KEY_HFP_SET_SAMPLING_RATE, int(sampleRateHz));
}
Return<Result> PrimaryDevice::setBtHfpVolume(float volume) {
if (!isGainNormalized(volume)) {
ALOGW("Can not set BT HFP volume (%f) outside [0,1]", volume);
return Result::INVALID_ARGUMENTS;
}
// Map the normalized volume onto the range of [0, 15]
return mDevice->setParam(AUDIO_PARAMETER_KEY_HFP_VOLUME,
static_cast<int>(std::round(volume * 15)));
}
Return<Result> PrimaryDevice::updateRotation(IPrimaryDevice::Rotation rotation) {
// legacy API expects the rotation in degree
return mDevice->setParam(AUDIO_PARAMETER_KEY_ROTATION, int(rotation) * 90);
}
#endif
Return<void> PrimaryDevice::debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) {
return mDevice->debug(fd, options);
}
} // namespace implementation
} // namespace CPP_VERSION
} // namespace audio
} // namespace hardware
} // namespace android

View file

@ -0,0 +1,331 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_TAG "StreamHAL"
#include "core/default/Stream.h"
#include "common/all-versions/default/EffectMap.h"
#include "core/default/Conversions.h"
#include "core/default/Util.h"
#include <inttypes.h>
#include <android/log.h>
#include <hardware/audio.h>
#include <hardware/audio_effect.h>
#include <media/TypeConverter.h>
#include <utils/SortedVector.h>
#include <utils/Vector.h>
namespace android {
namespace hardware {
namespace audio {
namespace CPP_VERSION {
namespace implementation {
Stream::Stream(audio_stream_t* stream) : mStream(stream) {}
Stream::~Stream() {
mStream = nullptr;
}
// static
Result Stream::analyzeStatus(const char* funcName, int status) {
return util::analyzeStatus("stream", funcName, status);
}
// static
Result Stream::analyzeStatus(const char* funcName, int status,
const std::vector<int>& ignoreErrors) {
return util::analyzeStatus("stream", funcName, status, ignoreErrors);
}
char* Stream::halGetParameters(const char* keys) {
return mStream->get_parameters(mStream, keys);
}
int Stream::halSetParameters(const char* keysAndValues) {
return mStream->set_parameters(mStream, keysAndValues);
}
// Methods from ::android::hardware::audio::CPP_VERSION::IStream follow.
Return<uint64_t> Stream::getFrameSize() {
// Needs to be implemented by interface subclasses. But can't be declared as pure virtual,
// since interface subclasses implementation do not inherit from this class.
LOG_ALWAYS_FATAL("Stream::getFrameSize is pure abstract");
return uint64_t{};
}
Return<uint64_t> Stream::getFrameCount() {
int halFrameCount;
Result retval = getParam(AudioParameter::keyFrameCount, &halFrameCount);
return retval == Result::OK ? halFrameCount : 0;
}
Return<uint64_t> Stream::getBufferSize() {
return mStream->get_buffer_size(mStream);
}
Return<uint32_t> Stream::getSampleRate() {
return mStream->get_sample_rate(mStream);
}
#if MAJOR_VERSION == 2
Return<void> Stream::getSupportedSampleRates(getSupportedSampleRates_cb _hidl_cb) {
return getSupportedSampleRates(getFormat(), _hidl_cb);
}
Return<void> Stream::getSupportedChannelMasks(getSupportedChannelMasks_cb _hidl_cb) {
return getSupportedChannelMasks(getFormat(), _hidl_cb);
}
#endif
Return<void> Stream::getSupportedSampleRates(AudioFormat format,
getSupportedSampleRates_cb _hidl_cb) {
AudioParameter context;
context.addInt(String8(AUDIO_PARAMETER_STREAM_FORMAT), int(format));
String8 halListValue;
Result result =
getParam(AudioParameter::keyStreamSupportedSamplingRates, &halListValue, context);
hidl_vec<uint32_t> sampleRates;
SortedVector<uint32_t> halSampleRates;
if (result == Result::OK) {
halSampleRates =
samplingRatesFromString(halListValue.string(), AudioParameter::valueListSeparator);
sampleRates.setToExternal(halSampleRates.editArray(), halSampleRates.size());
// Legacy get_parameter does not return a status_t, thus can not advertise of failure.
// Note that this method must succeed (non empty list) if the format is supported.
if (sampleRates.size() == 0) {
result = Result::NOT_SUPPORTED;
}
}
#if MAJOR_VERSION == 2
_hidl_cb(sampleRates);
#elif MAJOR_VERSION >= 4
_hidl_cb(result, sampleRates);
#endif
return Void();
}
Return<void> Stream::getSupportedChannelMasks(AudioFormat format,
getSupportedChannelMasks_cb _hidl_cb) {
AudioParameter context;
context.addInt(String8(AUDIO_PARAMETER_STREAM_FORMAT), int(format));
String8 halListValue;
Result result = getParam(AudioParameter::keyStreamSupportedChannels, &halListValue, context);
hidl_vec<AudioChannelBitfield> channelMasks;
SortedVector<audio_channel_mask_t> halChannelMasks;
if (result == Result::OK) {
halChannelMasks =
channelMasksFromString(halListValue.string(), AudioParameter::valueListSeparator);
channelMasks.resize(halChannelMasks.size());
for (size_t i = 0; i < halChannelMasks.size(); ++i) {
channelMasks[i] = AudioChannelBitfield(halChannelMasks[i]);
}
// Legacy get_parameter does not return a status_t, thus can not advertise of failure.
// Note that this method must succeed (non empty list) if the format is supported.
if (channelMasks.size() == 0) {
result = Result::NOT_SUPPORTED;
}
}
#if MAJOR_VERSION == 2
_hidl_cb(channelMasks);
#elif MAJOR_VERSION >= 4
_hidl_cb(result, channelMasks);
#endif
return Void();
}
Return<Result> Stream::setSampleRate(uint32_t sampleRateHz) {
return setParam(AudioParameter::keySamplingRate, static_cast<int>(sampleRateHz));
}
Return<AudioChannelBitfield> Stream::getChannelMask() {
return AudioChannelBitfield(mStream->get_channels(mStream));
}
Return<Result> Stream::setChannelMask(AudioChannelBitfield mask) {
return setParam(AudioParameter::keyChannels, static_cast<int>(mask));
}
Return<AudioFormat> Stream::getFormat() {
return AudioFormat(mStream->get_format(mStream));
}
Return<void> Stream::getSupportedFormats(getSupportedFormats_cb _hidl_cb) {
String8 halListValue;
Result result = getParam(AudioParameter::keyStreamSupportedFormats, &halListValue);
hidl_vec<AudioFormat> formats;
Vector<audio_format_t> halFormats;
if (result == Result::OK) {
halFormats = formatsFromString(halListValue.string(), AudioParameter::valueListSeparator);
formats.resize(halFormats.size());
for (size_t i = 0; i < halFormats.size(); ++i) {
formats[i] = AudioFormat(halFormats[i]);
}
}
_hidl_cb(formats);
return Void();
}
Return<Result> Stream::setFormat(AudioFormat format) {
return setParam(AudioParameter::keyFormat, static_cast<int>(format));
}
Return<void> Stream::getAudioProperties(getAudioProperties_cb _hidl_cb) {
uint32_t halSampleRate = mStream->get_sample_rate(mStream);
audio_channel_mask_t halMask = mStream->get_channels(mStream);
audio_format_t halFormat = mStream->get_format(mStream);
_hidl_cb(halSampleRate, AudioChannelBitfield(halMask), AudioFormat(halFormat));
return Void();
}
Return<Result> Stream::addEffect(uint64_t effectId) {
effect_handle_t halEffect = EffectMap::getInstance().get(effectId);
if (halEffect != NULL) {
return analyzeStatus("add_audio_effect", mStream->add_audio_effect(mStream, halEffect));
} else {
ALOGW("Invalid effect ID passed from client: %" PRIu64, effectId);
return Result::INVALID_ARGUMENTS;
}
}
Return<Result> Stream::removeEffect(uint64_t effectId) {
effect_handle_t halEffect = EffectMap::getInstance().get(effectId);
if (halEffect != NULL) {
return analyzeStatus("remove_audio_effect",
mStream->remove_audio_effect(mStream, halEffect));
} else {
ALOGW("Invalid effect ID passed from client: %" PRIu64, effectId);
return Result::INVALID_ARGUMENTS;
}
}
Return<Result> Stream::standby() {
return analyzeStatus("standby", mStream->standby(mStream));
}
Return<Result> Stream::setHwAvSync(uint32_t hwAvSync) {
return setParam(AudioParameter::keyStreamHwAvSync, static_cast<int>(hwAvSync));
}
#if MAJOR_VERSION == 2
Return<AudioDevice> Stream::getDevice() {
int device = 0;
Result retval = getParam(AudioParameter::keyRouting, &device);
return retval == Result::OK ? static_cast<AudioDevice>(device) : AudioDevice::NONE;
}
Return<Result> Stream::setDevice(const DeviceAddress& address) {
return setParam(AudioParameter::keyRouting, address);
}
Return<void> Stream::getParameters(const hidl_vec<hidl_string>& keys, getParameters_cb _hidl_cb) {
getParametersImpl({} /* context */, keys, _hidl_cb);
return Void();
}
Return<Result> Stream::setParameters(const hidl_vec<ParameterValue>& parameters) {
return setParametersImpl({} /* context */, parameters);
}
Return<Result> Stream::setConnectedState(const DeviceAddress& address, bool connected) {
return setParam(
connected ? AudioParameter::keyStreamConnect : AudioParameter::keyStreamDisconnect,
address);
}
#elif MAJOR_VERSION >= 4
Return<void> Stream::getDevices(getDevices_cb _hidl_cb) {
int device = 0;
Result retval = getParam(AudioParameter::keyRouting, &device);
hidl_vec<DeviceAddress> devices;
if (retval == Result::OK) {
devices.resize(1);
devices[0].device = static_cast<AudioDevice>(device);
}
_hidl_cb(retval, devices);
return Void();
}
Return<Result> Stream::setDevices(const hidl_vec<DeviceAddress>& devices) {
// FIXME: can the legacy API set multiple device with address ?
if (devices.size() > 1) {
return Result::NOT_SUPPORTED;
}
DeviceAddress address;
if (devices.size() == 1) {
address = devices[0];
} else {
address.device = AudioDevice::NONE;
}
return setParam(AudioParameter::keyRouting, address);
}
Return<void> Stream::getParameters(const hidl_vec<ParameterValue>& context,
const hidl_vec<hidl_string>& keys, getParameters_cb _hidl_cb) {
getParametersImpl(context, keys, _hidl_cb);
return Void();
}
Return<Result> Stream::setParameters(const hidl_vec<ParameterValue>& context,
const hidl_vec<ParameterValue>& parameters) {
return setParametersImpl(context, parameters);
}
#endif
Return<Result> Stream::start() {
return Result::NOT_SUPPORTED;
}
Return<Result> Stream::stop() {
return Result::NOT_SUPPORTED;
}
Return<void> Stream::createMmapBuffer(int32_t minSizeFrames __unused,
createMmapBuffer_cb _hidl_cb) {
Result retval(Result::NOT_SUPPORTED);
MmapBufferInfo info;
_hidl_cb(retval, info);
return Void();
}
Return<void> Stream::getMmapPosition(getMmapPosition_cb _hidl_cb) {
Result retval(Result::NOT_SUPPORTED);
MmapPosition position;
_hidl_cb(retval, position);
return Void();
}
Return<Result> Stream::close() {
return Result::NOT_SUPPORTED;
}
Return<void> Stream::debug(const hidl_handle& fd, const hidl_vec<hidl_string>& /* options */) {
if (fd.getNativeHandle() != nullptr && fd->numFds == 1) {
analyzeStatus("dump", mStream->dump(mStream, fd->data[0]));
}
return Void();
}
#if MAJOR_VERSION == 2
Return<void> Stream::debugDump(const hidl_handle& fd) {
return debug(fd, {} /* options */);
}
#endif
} // namespace implementation
} // namespace CPP_VERSION
} // namespace audio
} // namespace hardware
} // namespace android

View file

@ -0,0 +1,534 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_TAG "StreamInHAL"
#include "core/default/StreamIn.h"
#include "core/default/Conversions.h"
#include "core/default/Util.h"
#include "common/all-versions/HidlSupport.h"
//#define LOG_NDEBUG 0
#define ATRACE_TAG ATRACE_TAG_AUDIO
#include <android/log.h>
#include <hardware/audio.h>
#include <utils/Trace.h>
#include <memory>
#include <cmath>
namespace android {
namespace hardware {
namespace audio {
namespace CPP_VERSION {
namespace implementation {
namespace {
class ReadThread : public Thread {
public:
// ReadThread's lifespan never exceeds StreamIn's lifespan.
ReadThread(std::atomic<bool>* stop, audio_stream_in_t* stream, StreamIn::CommandMQ* commandMQ,
StreamIn::DataMQ* dataMQ, StreamIn::StatusMQ* statusMQ, EventFlag* efGroup)
: Thread(false /*canCallJava*/),
mStop(stop),
mStream(stream),
mCommandMQ(commandMQ),
mDataMQ(dataMQ),
mStatusMQ(statusMQ),
mEfGroup(efGroup),
mBuffer(nullptr) {}
bool init() {
mBuffer.reset(new (std::nothrow) uint8_t[mDataMQ->getQuantumCount()]);
return mBuffer != nullptr;
}
virtual ~ReadThread() {}
private:
std::atomic<bool>* mStop;
audio_stream_in_t* mStream;
StreamIn::CommandMQ* mCommandMQ;
StreamIn::DataMQ* mDataMQ;
StreamIn::StatusMQ* mStatusMQ;
EventFlag* mEfGroup;
std::unique_ptr<uint8_t[]> mBuffer;
IStreamIn::ReadParameters mParameters;
IStreamIn::ReadStatus mStatus;
bool threadLoop() override;
void doGetCapturePosition();
void doRead();
};
void ReadThread::doRead() {
size_t availableToWrite = mDataMQ->availableToWrite();
size_t requestedToRead = mParameters.params.read;
if (requestedToRead > availableToWrite) {
ALOGW(
"truncating read data from %d to %d due to insufficient data queue "
"space",
(int32_t)requestedToRead, (int32_t)availableToWrite);
requestedToRead = availableToWrite;
}
ssize_t readResult = mStream->read(mStream, &mBuffer[0], requestedToRead);
mStatus.retval = Result::OK;
if (readResult >= 0) {
mStatus.reply.read = readResult;
if (!mDataMQ->write(&mBuffer[0], readResult)) {
ALOGW("data message queue write failed");
}
} else {
mStatus.retval = Stream::analyzeStatus("read", readResult);
}
}
void ReadThread::doGetCapturePosition() {
mStatus.retval = StreamIn::getCapturePositionImpl(
mStream, &mStatus.reply.capturePosition.frames, &mStatus.reply.capturePosition.time);
}
bool ReadThread::threadLoop() {
// This implementation doesn't return control back to the Thread until it
// decides to stop,
// as the Thread uses mutexes, and this can lead to priority inversion.
while (!std::atomic_load_explicit(mStop, std::memory_order_acquire)) {
uint32_t efState = 0;
mEfGroup->wait(static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL), &efState);
if (!(efState & static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL))) {
continue; // Nothing to do.
}
if (!mCommandMQ->read(&mParameters)) {
continue; // Nothing to do.
}
mStatus.replyTo = mParameters.command;
switch (mParameters.command) {
case IStreamIn::ReadCommand::READ:
doRead();
break;
case IStreamIn::ReadCommand::GET_CAPTURE_POSITION:
doGetCapturePosition();
break;
default:
ALOGE("Unknown read thread command code %d", mParameters.command);
mStatus.retval = Result::NOT_SUPPORTED;
break;
}
if (!mStatusMQ->write(&mStatus)) {
ALOGW("status message queue write failed");
}
mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY));
}
return false;
}
} // namespace
StreamIn::StreamIn(const sp<Device>& device, audio_stream_in_t* stream)
: mIsClosed(false),
mDevice(device),
mStream(stream),
mStreamCommon(new Stream(&stream->common)),
mStreamMmap(new StreamMmap<audio_stream_in_t>(stream)),
mEfGroup(nullptr),
mStopReadThread(false) {}
StreamIn::~StreamIn() {
ATRACE_CALL();
close();
if (mReadThread.get()) {
ATRACE_NAME("mReadThread->join");
status_t status = mReadThread->join();
ALOGE_IF(status, "read thread exit error: %s", strerror(-status));
}
if (mEfGroup) {
status_t status = EventFlag::deleteEventFlag(&mEfGroup);
ALOGE_IF(status, "read MQ event flag deletion error: %s", strerror(-status));
}
mDevice->closeInputStream(mStream);
mStream = nullptr;
}
// Methods from ::android::hardware::audio::CPP_VERSION::IStream follow.
Return<uint64_t> StreamIn::getFrameSize() {
return audio_stream_in_frame_size(mStream);
}
Return<uint64_t> StreamIn::getFrameCount() {
return mStreamCommon->getFrameCount();
}
Return<uint64_t> StreamIn::getBufferSize() {
return mStreamCommon->getBufferSize();
}
Return<uint32_t> StreamIn::getSampleRate() {
return mStreamCommon->getSampleRate();
}
#if MAJOR_VERSION == 2
Return<void> StreamIn::getSupportedChannelMasks(getSupportedChannelMasks_cb _hidl_cb) {
return mStreamCommon->getSupportedChannelMasks(_hidl_cb);
}
Return<void> StreamIn::getSupportedSampleRates(getSupportedSampleRates_cb _hidl_cb) {
return mStreamCommon->getSupportedSampleRates(_hidl_cb);
}
#endif
Return<void> StreamIn::getSupportedChannelMasks(AudioFormat format,
getSupportedChannelMasks_cb _hidl_cb) {
return mStreamCommon->getSupportedChannelMasks(format, _hidl_cb);
}
Return<void> StreamIn::getSupportedSampleRates(AudioFormat format,
getSupportedSampleRates_cb _hidl_cb) {
return mStreamCommon->getSupportedSampleRates(format, _hidl_cb);
}
Return<Result> StreamIn::setSampleRate(uint32_t sampleRateHz) {
return mStreamCommon->setSampleRate(sampleRateHz);
}
Return<AudioChannelBitfield> StreamIn::getChannelMask() {
return mStreamCommon->getChannelMask();
}
Return<Result> StreamIn::setChannelMask(AudioChannelBitfield mask) {
return mStreamCommon->setChannelMask(mask);
}
Return<AudioFormat> StreamIn::getFormat() {
return mStreamCommon->getFormat();
}
Return<void> StreamIn::getSupportedFormats(getSupportedFormats_cb _hidl_cb) {
return mStreamCommon->getSupportedFormats(_hidl_cb);
}
Return<Result> StreamIn::setFormat(AudioFormat format) {
return mStreamCommon->setFormat(format);
}
Return<void> StreamIn::getAudioProperties(getAudioProperties_cb _hidl_cb) {
return mStreamCommon->getAudioProperties(_hidl_cb);
}
Return<Result> StreamIn::addEffect(uint64_t effectId) {
return mStreamCommon->addEffect(effectId);
}
Return<Result> StreamIn::removeEffect(uint64_t effectId) {
return mStreamCommon->removeEffect(effectId);
}
Return<Result> StreamIn::standby() {
return mStreamCommon->standby();
}
Return<Result> StreamIn::setHwAvSync(uint32_t hwAvSync) {
return mStreamCommon->setHwAvSync(hwAvSync);
}
#if MAJOR_VERSION == 2
Return<Result> StreamIn::setConnectedState(const DeviceAddress& address, bool connected) {
return mStreamCommon->setConnectedState(address, connected);
}
Return<AudioDevice> StreamIn::getDevice() {
return mStreamCommon->getDevice();
}
Return<Result> StreamIn::setDevice(const DeviceAddress& address) {
return mStreamCommon->setDevice(address);
}
Return<void> StreamIn::getParameters(const hidl_vec<hidl_string>& keys, getParameters_cb _hidl_cb) {
return mStreamCommon->getParameters(keys, _hidl_cb);
}
Return<Result> StreamIn::setParameters(const hidl_vec<ParameterValue>& parameters) {
return mStreamCommon->setParameters(parameters);
}
Return<void> StreamIn::debugDump(const hidl_handle& fd) {
return mStreamCommon->debugDump(fd);
}
#elif MAJOR_VERSION >= 4
Return<void> StreamIn::getDevices(getDevices_cb _hidl_cb) {
return mStreamCommon->getDevices(_hidl_cb);
}
Return<Result> StreamIn::setDevices(const hidl_vec<DeviceAddress>& devices) {
return mStreamCommon->setDevices(devices);
}
Return<void> StreamIn::getParameters(const hidl_vec<ParameterValue>& context,
const hidl_vec<hidl_string>& keys, getParameters_cb _hidl_cb) {
return mStreamCommon->getParameters(context, keys, _hidl_cb);
}
Return<Result> StreamIn::setParameters(const hidl_vec<ParameterValue>& context,
const hidl_vec<ParameterValue>& parameters) {
return mStreamCommon->setParameters(context, parameters);
}
#endif
Return<Result> StreamIn::start() {
return mStreamMmap->start();
}
Return<Result> StreamIn::stop() {
return mStreamMmap->stop();
}
Return<void> StreamIn::createMmapBuffer(int32_t minSizeFrames, createMmapBuffer_cb _hidl_cb) {
return mStreamMmap->createMmapBuffer(minSizeFrames, audio_stream_in_frame_size(mStream),
_hidl_cb);
}
Return<void> StreamIn::getMmapPosition(getMmapPosition_cb _hidl_cb) {
return mStreamMmap->getMmapPosition(_hidl_cb);
}
Return<Result> StreamIn::close() {
if (mIsClosed) return Result::INVALID_STATE;
mIsClosed = true;
if (mReadThread.get()) {
mStopReadThread.store(true, std::memory_order_release);
}
if (mEfGroup) {
mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL));
}
return Result::OK;
}
// Methods from ::android::hardware::audio::CPP_VERSION::IStreamIn follow.
Return<void> StreamIn::getAudioSource(getAudioSource_cb _hidl_cb) {
int halSource;
Result retval = mStreamCommon->getParam(AudioParameter::keyInputSource, &halSource);
AudioSource source(AudioSource::DEFAULT);
if (retval == Result::OK) {
source = AudioSource(halSource);
}
_hidl_cb(retval, source);
return Void();
}
Return<Result> StreamIn::setGain(float gain) {
if (!isGainNormalized(gain)) {
ALOGW("Can not set a stream input gain (%f) outside [0,1]", gain);
return Result::INVALID_ARGUMENTS;
}
return Stream::analyzeStatus("set_gain", mStream->set_gain(mStream, gain));
}
Return<void> StreamIn::prepareForReading(uint32_t frameSize, uint32_t framesCount,
prepareForReading_cb _hidl_cb) {
status_t status;
ThreadInfo threadInfo = {0, 0};
// Wrap the _hidl_cb to return an error
auto sendError = [&threadInfo, &_hidl_cb](Result result) {
_hidl_cb(result, CommandMQ::Descriptor(), DataMQ::Descriptor(), StatusMQ::Descriptor(),
threadInfo);
};
// Create message queues.
if (mDataMQ) {
ALOGE("the client attempts to call prepareForReading twice");
sendError(Result::INVALID_STATE);
return Void();
}
std::unique_ptr<CommandMQ> tempCommandMQ(new CommandMQ(1));
// Check frameSize and framesCount
if (frameSize == 0 || framesCount == 0) {
ALOGE("Null frameSize (%u) or framesCount (%u)", frameSize, framesCount);
sendError(Result::INVALID_ARGUMENTS);
return Void();
}
if (frameSize > Stream::MAX_BUFFER_SIZE / framesCount) {
ALOGE("Buffer too big: %u*%u bytes > MAX_BUFFER_SIZE (%u)", frameSize, framesCount,
Stream::MAX_BUFFER_SIZE);
sendError(Result::INVALID_ARGUMENTS);
return Void();
}
std::unique_ptr<DataMQ> tempDataMQ(new DataMQ(frameSize * framesCount, true /* EventFlag */));
std::unique_ptr<StatusMQ> tempStatusMQ(new StatusMQ(1));
if (!tempCommandMQ->isValid() || !tempDataMQ->isValid() || !tempStatusMQ->isValid()) {
ALOGE_IF(!tempCommandMQ->isValid(), "command MQ is invalid");
ALOGE_IF(!tempDataMQ->isValid(), "data MQ is invalid");
ALOGE_IF(!tempStatusMQ->isValid(), "status MQ is invalid");
sendError(Result::INVALID_ARGUMENTS);
return Void();
}
EventFlag* tempRawEfGroup{};
status = EventFlag::createEventFlag(tempDataMQ->getEventFlagWord(), &tempRawEfGroup);
std::unique_ptr<EventFlag, void (*)(EventFlag*)> tempElfGroup(
tempRawEfGroup, [](auto* ef) { EventFlag::deleteEventFlag(&ef); });
if (status != OK || !tempElfGroup) {
ALOGE("failed creating event flag for data MQ: %s", strerror(-status));
sendError(Result::INVALID_ARGUMENTS);
return Void();
}
// Create and launch the thread.
auto tempReadThread =
std::make_unique<ReadThread>(&mStopReadThread, mStream, tempCommandMQ.get(),
tempDataMQ.get(), tempStatusMQ.get(), tempElfGroup.get());
if (!tempReadThread->init()) {
ALOGW("failed to start reader thread: %s", strerror(-status));
sendError(Result::INVALID_ARGUMENTS);
return Void();
}
status = tempReadThread->run("reader", PRIORITY_URGENT_AUDIO);
if (status != OK) {
ALOGW("failed to start reader thread: %s", strerror(-status));
sendError(Result::INVALID_ARGUMENTS);
return Void();
}
mCommandMQ = std::move(tempCommandMQ);
mDataMQ = std::move(tempDataMQ);
mStatusMQ = std::move(tempStatusMQ);
mReadThread = tempReadThread.release();
mEfGroup = tempElfGroup.release();
threadInfo.pid = getpid();
threadInfo.tid = mReadThread->getTid();
_hidl_cb(Result::OK, *mCommandMQ->getDesc(), *mDataMQ->getDesc(), *mStatusMQ->getDesc(),
threadInfo);
return Void();
}
Return<uint32_t> StreamIn::getInputFramesLost() {
return mStream->get_input_frames_lost(mStream);
}
// static
Result StreamIn::getCapturePositionImpl(audio_stream_in_t* stream, uint64_t* frames,
uint64_t* time) {
// HAL may have a stub function, always returning ENOSYS, don't
// spam the log in this case.
static const std::vector<int> ignoredErrors{ENOSYS};
Result retval(Result::NOT_SUPPORTED);
if (stream->get_capture_position == NULL) return retval;
int64_t halFrames, halTime;
retval = Stream::analyzeStatus("get_capture_position",
stream->get_capture_position(stream, &halFrames, &halTime),
ignoredErrors);
if (retval == Result::OK) {
*frames = halFrames;
*time = halTime;
}
return retval;
};
Return<void> StreamIn::getCapturePosition(getCapturePosition_cb _hidl_cb) {
uint64_t frames = 0, time = 0;
Result retval = getCapturePositionImpl(mStream, &frames, &time);
_hidl_cb(retval, frames, time);
return Void();
}
Return<void> StreamIn::debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) {
return mStreamCommon->debug(fd, options);
}
#if MAJOR_VERSION >= 4
Return<void> StreamIn::updateSinkMetadata(const SinkMetadata& sinkMetadata) {
if (mStream->update_sink_metadata == nullptr) {
return Void(); // not supported by the HAL
}
std::vector<record_track_metadata> halTracks;
halTracks.reserve(sinkMetadata.tracks.size());
for (auto& metadata : sinkMetadata.tracks) {
record_track_metadata halTrackMetadata = {
.source = static_cast<audio_source_t>(metadata.source), .gain = metadata.gain};
#if MAJOR_VERSION >= 5
if (metadata.destination.getDiscriminator() ==
RecordTrackMetadata::Destination::hidl_discriminator::device) {
halTrackMetadata.dest_device =
static_cast<audio_devices_t>(metadata.destination.device().device);
strncpy(halTrackMetadata.dest_device_address,
deviceAddressToHal(metadata.destination.device()).c_str(),
AUDIO_DEVICE_MAX_ADDRESS_LEN);
}
#endif
halTracks.push_back(halTrackMetadata);
}
const sink_metadata_t halMetadata = {
.track_count = halTracks.size(),
.tracks = halTracks.data(),
};
mStream->update_sink_metadata(mStream, &halMetadata);
return Void();
}
Return<void> StreamIn::getActiveMicrophones(getActiveMicrophones_cb _hidl_cb) {
Result retval = Result::NOT_SUPPORTED;
size_t actual_mics = AUDIO_MICROPHONE_MAX_COUNT;
audio_microphone_characteristic_t mic_array[AUDIO_MICROPHONE_MAX_COUNT];
hidl_vec<MicrophoneInfo> microphones;
if (mStream->get_active_microphones != NULL &&
mStream->get_active_microphones(mStream, &mic_array[0], &actual_mics) == 0) {
microphones.resize(actual_mics);
for (size_t i = 0; i < actual_mics; ++i) {
halToMicrophoneCharacteristics(&microphones[i], mic_array[i]);
}
retval = Result::OK;
}
_hidl_cb(retval, microphones);
return Void();
}
#endif
#if MAJOR_VERSION >= 5
Return<Result> StreamIn::setMicrophoneDirection(MicrophoneDirection direction) {
if (mStream->set_microphone_direction == nullptr) {
return Result::NOT_SUPPORTED;
}
if (!common::utils::isValidHidlEnum(direction)) {
ALOGE("%s: Invalid direction %d", __func__, direction);
return Result::INVALID_ARGUMENTS;
}
return Stream::analyzeStatus(
"set_microphone_direction",
mStream->set_microphone_direction(
mStream, static_cast<audio_microphone_direction_t>(direction)));
}
Return<Result> StreamIn::setMicrophoneFieldDimension(float zoom) {
if (mStream->set_microphone_field_dimension == nullptr) {
return Result::NOT_SUPPORTED;
}
if (std::isnan(zoom) || zoom < -1 || zoom > 1) {
ALOGE("%s: Invalid zoom %f", __func__, zoom);
return Result::INVALID_ARGUMENTS;
}
return Stream::analyzeStatus("set_microphone_field_dimension",
mStream->set_microphone_field_dimension(mStream, zoom));
}
#endif
} // namespace implementation
} // namespace CPP_VERSION
} // namespace audio
} // namespace hardware
} // namespace android

View file

@ -0,0 +1,578 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_TAG "StreamOutHAL"
#include "core/default/StreamOut.h"
#include "core/default/Util.h"
//#define LOG_NDEBUG 0
#define ATRACE_TAG ATRACE_TAG_AUDIO
#include <memory>
#include <android/log.h>
#include <hardware/audio.h>
#include <utils/Trace.h>
namespace android {
namespace hardware {
namespace audio {
namespace CPP_VERSION {
namespace implementation {
namespace {
class WriteThread : public Thread {
public:
// WriteThread's lifespan never exceeds StreamOut's lifespan.
WriteThread(std::atomic<bool>* stop, audio_stream_out_t* stream,
StreamOut::CommandMQ* commandMQ, StreamOut::DataMQ* dataMQ,
StreamOut::StatusMQ* statusMQ, EventFlag* efGroup)
: Thread(false /*canCallJava*/),
mStop(stop),
mStream(stream),
mCommandMQ(commandMQ),
mDataMQ(dataMQ),
mStatusMQ(statusMQ),
mEfGroup(efGroup),
mBuffer(nullptr) {}
bool init() {
mBuffer.reset(new (std::nothrow) uint8_t[mDataMQ->getQuantumCount()]);
return mBuffer != nullptr;
}
virtual ~WriteThread() {}
private:
std::atomic<bool>* mStop;
audio_stream_out_t* mStream;
StreamOut::CommandMQ* mCommandMQ;
StreamOut::DataMQ* mDataMQ;
StreamOut::StatusMQ* mStatusMQ;
EventFlag* mEfGroup;
std::unique_ptr<uint8_t[]> mBuffer;
IStreamOut::WriteStatus mStatus;
bool threadLoop() override;
void doGetLatency();
void doGetPresentationPosition();
void doWrite();
};
void WriteThread::doWrite() {
const size_t availToRead = mDataMQ->availableToRead();
mStatus.retval = Result::OK;
mStatus.reply.written = 0;
if (mDataMQ->read(&mBuffer[0], availToRead)) {
ssize_t writeResult = mStream->write(mStream, &mBuffer[0], availToRead);
if (writeResult >= 0) {
mStatus.reply.written = writeResult;
} else {
mStatus.retval = Stream::analyzeStatus("write", writeResult);
}
}
}
void WriteThread::doGetPresentationPosition() {
mStatus.retval =
StreamOut::getPresentationPositionImpl(mStream, &mStatus.reply.presentationPosition.frames,
&mStatus.reply.presentationPosition.timeStamp);
}
void WriteThread::doGetLatency() {
mStatus.retval = Result::OK;
mStatus.reply.latencyMs = mStream->get_latency(mStream);
}
bool WriteThread::threadLoop() {
// This implementation doesn't return control back to the Thread until it
// decides to stop,
// as the Thread uses mutexes, and this can lead to priority inversion.
while (!std::atomic_load_explicit(mStop, std::memory_order_acquire)) {
uint32_t efState = 0;
mEfGroup->wait(static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY), &efState);
if (!(efState & static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY))) {
continue; // Nothing to do.
}
if (!mCommandMQ->read(&mStatus.replyTo)) {
continue; // Nothing to do.
}
switch (mStatus.replyTo) {
case IStreamOut::WriteCommand::WRITE:
doWrite();
break;
case IStreamOut::WriteCommand::GET_PRESENTATION_POSITION:
doGetPresentationPosition();
break;
case IStreamOut::WriteCommand::GET_LATENCY:
doGetLatency();
break;
default:
ALOGE("Unknown write thread command code %d", mStatus.replyTo);
mStatus.retval = Result::NOT_SUPPORTED;
break;
}
if (!mStatusMQ->write(&mStatus)) {
ALOGE("status message queue write failed");
}
mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL));
}
return false;
}
} // namespace
StreamOut::StreamOut(const sp<Device>& device, audio_stream_out_t* stream)
: mIsClosed(false),
mDevice(device),
mStream(stream),
mStreamCommon(new Stream(&stream->common)),
mStreamMmap(new StreamMmap<audio_stream_out_t>(stream)),
mEfGroup(nullptr),
mStopWriteThread(false) {}
StreamOut::~StreamOut() {
ATRACE_CALL();
close();
if (mWriteThread.get()) {
ATRACE_NAME("mWriteThread->join");
status_t status = mWriteThread->join();
ALOGE_IF(status, "write thread exit error: %s", strerror(-status));
}
if (mEfGroup) {
status_t status = EventFlag::deleteEventFlag(&mEfGroup);
ALOGE_IF(status, "write MQ event flag deletion error: %s", strerror(-status));
}
mCallback.clear();
mDevice->closeOutputStream(mStream);
// Closing the output stream in the HAL waits for the callback to finish,
// and joins the callback thread. Thus is it guaranteed that the callback
// thread will not be accessing our object anymore.
mStream = nullptr;
}
// Methods from ::android::hardware::audio::CPP_VERSION::IStream follow.
Return<uint64_t> StreamOut::getFrameSize() {
return audio_stream_out_frame_size(mStream);
}
Return<uint64_t> StreamOut::getFrameCount() {
return mStreamCommon->getFrameCount();
}
Return<uint64_t> StreamOut::getBufferSize() {
return mStreamCommon->getBufferSize();
}
Return<uint32_t> StreamOut::getSampleRate() {
return mStreamCommon->getSampleRate();
}
#if MAJOR_VERSION == 2
Return<void> StreamOut::getSupportedChannelMasks(getSupportedChannelMasks_cb _hidl_cb) {
return mStreamCommon->getSupportedChannelMasks(_hidl_cb);
}
Return<void> StreamOut::getSupportedSampleRates(getSupportedSampleRates_cb _hidl_cb) {
return mStreamCommon->getSupportedSampleRates(_hidl_cb);
}
#endif
Return<void> StreamOut::getSupportedChannelMasks(AudioFormat format,
getSupportedChannelMasks_cb _hidl_cb) {
return mStreamCommon->getSupportedChannelMasks(format, _hidl_cb);
}
Return<void> StreamOut::getSupportedSampleRates(AudioFormat format,
getSupportedSampleRates_cb _hidl_cb) {
return mStreamCommon->getSupportedSampleRates(format, _hidl_cb);
}
Return<Result> StreamOut::setSampleRate(uint32_t sampleRateHz) {
return mStreamCommon->setSampleRate(sampleRateHz);
}
Return<AudioChannelBitfield> StreamOut::getChannelMask() {
return mStreamCommon->getChannelMask();
}
Return<Result> StreamOut::setChannelMask(AudioChannelBitfield mask) {
return mStreamCommon->setChannelMask(mask);
}
Return<AudioFormat> StreamOut::getFormat() {
return mStreamCommon->getFormat();
}
Return<void> StreamOut::getSupportedFormats(getSupportedFormats_cb _hidl_cb) {
return mStreamCommon->getSupportedFormats(_hidl_cb);
}
Return<Result> StreamOut::setFormat(AudioFormat format) {
return mStreamCommon->setFormat(format);
}
Return<void> StreamOut::getAudioProperties(getAudioProperties_cb _hidl_cb) {
return mStreamCommon->getAudioProperties(_hidl_cb);
}
Return<Result> StreamOut::addEffect(uint64_t effectId) {
return mStreamCommon->addEffect(effectId);
}
Return<Result> StreamOut::removeEffect(uint64_t effectId) {
return mStreamCommon->removeEffect(effectId);
}
Return<Result> StreamOut::standby() {
return mStreamCommon->standby();
}
Return<Result> StreamOut::setHwAvSync(uint32_t hwAvSync) {
return mStreamCommon->setHwAvSync(hwAvSync);
}
#if MAJOR_VERSION == 2
Return<Result> StreamOut::setConnectedState(const DeviceAddress& address, bool connected) {
return mStreamCommon->setConnectedState(address, connected);
}
Return<AudioDevice> StreamOut::getDevice() {
return mStreamCommon->getDevice();
}
Return<Result> StreamOut::setDevice(const DeviceAddress& address) {
return mStreamCommon->setDevice(address);
}
Return<void> StreamOut::getParameters(const hidl_vec<hidl_string>& keys,
getParameters_cb _hidl_cb) {
return mStreamCommon->getParameters(keys, _hidl_cb);
}
Return<Result> StreamOut::setParameters(const hidl_vec<ParameterValue>& parameters) {
return mStreamCommon->setParameters(parameters);
}
Return<void> StreamOut::debugDump(const hidl_handle& fd) {
return mStreamCommon->debugDump(fd);
}
#elif MAJOR_VERSION >= 4
Return<void> StreamOut::getDevices(getDevices_cb _hidl_cb) {
return mStreamCommon->getDevices(_hidl_cb);
}
Return<Result> StreamOut::setDevices(const hidl_vec<DeviceAddress>& devices) {
return mStreamCommon->setDevices(devices);
}
Return<void> StreamOut::getParameters(const hidl_vec<ParameterValue>& context,
const hidl_vec<hidl_string>& keys,
getParameters_cb _hidl_cb) {
return mStreamCommon->getParameters(context, keys, _hidl_cb);
}
Return<Result> StreamOut::setParameters(const hidl_vec<ParameterValue>& context,
const hidl_vec<ParameterValue>& parameters) {
return mStreamCommon->setParameters(context, parameters);
}
#endif
Return<Result> StreamOut::close() {
if (mIsClosed) return Result::INVALID_STATE;
mIsClosed = true;
if (mWriteThread.get()) {
mStopWriteThread.store(true, std::memory_order_release);
}
if (mEfGroup) {
mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY));
}
return Result::OK;
}
// Methods from ::android::hardware::audio::CPP_VERSION::IStreamOut follow.
Return<uint32_t> StreamOut::getLatency() {
return mStream->get_latency(mStream);
}
Return<Result> StreamOut::setVolume(float left, float right) {
if (mStream->set_volume == NULL) {
return Result::NOT_SUPPORTED;
}
if (!isGainNormalized(left)) {
ALOGW("Can not set a stream output volume {%f, %f} outside [0,1]", left, right);
return Result::INVALID_ARGUMENTS;
}
return Stream::analyzeStatus("set_volume", mStream->set_volume(mStream, left, right));
}
Return<void> StreamOut::prepareForWriting(uint32_t frameSize, uint32_t framesCount,
prepareForWriting_cb _hidl_cb) {
status_t status;
ThreadInfo threadInfo = {0, 0};
// Wrap the _hidl_cb to return an error
auto sendError = [&threadInfo, &_hidl_cb](Result result) {
_hidl_cb(result, CommandMQ::Descriptor(), DataMQ::Descriptor(), StatusMQ::Descriptor(),
threadInfo);
};
// Create message queues.
if (mDataMQ) {
ALOGE("the client attempts to call prepareForWriting twice");
sendError(Result::INVALID_STATE);
return Void();
}
std::unique_ptr<CommandMQ> tempCommandMQ(new CommandMQ(1));
// Check frameSize and framesCount
if (frameSize == 0 || framesCount == 0) {
ALOGE("Null frameSize (%u) or framesCount (%u)", frameSize, framesCount);
sendError(Result::INVALID_ARGUMENTS);
return Void();
}
if (frameSize > Stream::MAX_BUFFER_SIZE / framesCount) {
ALOGE("Buffer too big: %u*%u bytes > MAX_BUFFER_SIZE (%u)", frameSize, framesCount,
Stream::MAX_BUFFER_SIZE);
sendError(Result::INVALID_ARGUMENTS);
return Void();
}
std::unique_ptr<DataMQ> tempDataMQ(new DataMQ(frameSize * framesCount, true /* EventFlag */));
std::unique_ptr<StatusMQ> tempStatusMQ(new StatusMQ(1));
if (!tempCommandMQ->isValid() || !tempDataMQ->isValid() || !tempStatusMQ->isValid()) {
ALOGE_IF(!tempCommandMQ->isValid(), "command MQ is invalid");
ALOGE_IF(!tempDataMQ->isValid(), "data MQ is invalid");
ALOGE_IF(!tempStatusMQ->isValid(), "status MQ is invalid");
sendError(Result::INVALID_ARGUMENTS);
return Void();
}
EventFlag* tempRawEfGroup{};
status = EventFlag::createEventFlag(tempDataMQ->getEventFlagWord(), &tempRawEfGroup);
std::unique_ptr<EventFlag, void (*)(EventFlag*)> tempElfGroup(
tempRawEfGroup, [](auto* ef) { EventFlag::deleteEventFlag(&ef); });
if (status != OK || !tempElfGroup) {
ALOGE("failed creating event flag for data MQ: %s", strerror(-status));
sendError(Result::INVALID_ARGUMENTS);
return Void();
}
// Create and launch the thread.
auto tempWriteThread =
std::make_unique<WriteThread>(&mStopWriteThread, mStream, tempCommandMQ.get(),
tempDataMQ.get(), tempStatusMQ.get(), tempElfGroup.get());
if (!tempWriteThread->init()) {
ALOGW("failed to start writer thread: %s", strerror(-status));
sendError(Result::INVALID_ARGUMENTS);
return Void();
}
status = tempWriteThread->run("writer", PRIORITY_URGENT_AUDIO);
if (status != OK) {
ALOGW("failed to start writer thread: %s", strerror(-status));
sendError(Result::INVALID_ARGUMENTS);
return Void();
}
mCommandMQ = std::move(tempCommandMQ);
mDataMQ = std::move(tempDataMQ);
mStatusMQ = std::move(tempStatusMQ);
mWriteThread = tempWriteThread.release();
mEfGroup = tempElfGroup.release();
threadInfo.pid = getpid();
threadInfo.tid = mWriteThread->getTid();
_hidl_cb(Result::OK, *mCommandMQ->getDesc(), *mDataMQ->getDesc(), *mStatusMQ->getDesc(),
threadInfo);
return Void();
}
Return<void> StreamOut::getRenderPosition(getRenderPosition_cb _hidl_cb) {
uint32_t halDspFrames;
Result retval = Stream::analyzeStatus("get_render_position",
mStream->get_render_position(mStream, &halDspFrames));
_hidl_cb(retval, halDspFrames);
return Void();
}
Return<void> StreamOut::getNextWriteTimestamp(getNextWriteTimestamp_cb _hidl_cb) {
Result retval(Result::NOT_SUPPORTED);
int64_t timestampUs = 0;
if (mStream->get_next_write_timestamp != NULL) {
retval = Stream::analyzeStatus("get_next_write_timestamp",
mStream->get_next_write_timestamp(mStream, &timestampUs));
}
_hidl_cb(retval, timestampUs);
return Void();
}
Return<Result> StreamOut::setCallback(const sp<IStreamOutCallback>& callback) {
if (mStream->set_callback == NULL) return Result::NOT_SUPPORTED;
// Safe to pass 'this' because it is guaranteed that the callback thread
// is joined prior to exit from StreamOut's destructor.
int result = mStream->set_callback(mStream, StreamOut::asyncCallback, this);
if (result == 0) {
mCallback = callback;
}
return Stream::analyzeStatus("set_callback", result);
}
Return<Result> StreamOut::clearCallback() {
if (mStream->set_callback == NULL) return Result::NOT_SUPPORTED;
mCallback.clear();
return Result::OK;
}
// static
int StreamOut::asyncCallback(stream_callback_event_t event, void*, void* cookie) {
// It is guaranteed that the callback thread is joined prior
// to exiting from StreamOut's destructor. Must *not* use sp<StreamOut>
// here because it can make this code the last owner of StreamOut,
// and an attempt to run the destructor on the callback thread
// will cause a deadlock in the legacy HAL code.
StreamOut* self = reinterpret_cast<StreamOut*>(cookie);
// It's correct to hold an sp<> to callback because the reference
// in the StreamOut instance can be cleared in the meantime. There is
// no difference on which thread to run IStreamOutCallback's destructor.
sp<IStreamOutCallback> callback = self->mCallback;
if (callback.get() == nullptr) return 0;
ALOGV("asyncCallback() event %d", event);
switch (event) {
case STREAM_CBK_EVENT_WRITE_READY:
callback->onWriteReady();
break;
case STREAM_CBK_EVENT_DRAIN_READY:
callback->onDrainReady();
break;
case STREAM_CBK_EVENT_ERROR:
callback->onError();
break;
default:
ALOGW("asyncCallback() unknown event %d", event);
break;
}
return 0;
}
Return<void> StreamOut::supportsPauseAndResume(supportsPauseAndResume_cb _hidl_cb) {
_hidl_cb(mStream->pause != NULL, mStream->resume != NULL);
return Void();
}
Return<Result> StreamOut::pause() {
return mStream->pause != NULL ? Stream::analyzeStatus("pause", mStream->pause(mStream))
: Result::NOT_SUPPORTED;
}
Return<Result> StreamOut::resume() {
return mStream->resume != NULL ? Stream::analyzeStatus("resume", mStream->resume(mStream))
: Result::NOT_SUPPORTED;
}
Return<bool> StreamOut::supportsDrain() {
return mStream->drain != NULL;
}
Return<Result> StreamOut::drain(AudioDrain type) {
return mStream->drain != NULL
? Stream::analyzeStatus(
"drain", mStream->drain(mStream, static_cast<audio_drain_type_t>(type)))
: Result::NOT_SUPPORTED;
}
Return<Result> StreamOut::flush() {
return mStream->flush != NULL ? Stream::analyzeStatus("flush", mStream->flush(mStream))
: Result::NOT_SUPPORTED;
}
// static
Result StreamOut::getPresentationPositionImpl(audio_stream_out_t* stream, uint64_t* frames,
TimeSpec* timeStamp) {
// Don't logspam on EINVAL--it's normal for get_presentation_position
// to return it sometimes. EAGAIN may be returned by A2DP audio HAL
// implementation. ENODATA can also be reported while the writer is
// continuously querying it, but the stream has been stopped.
static const std::vector<int> ignoredErrors{EINVAL, EAGAIN, ENODATA};
Result retval(Result::NOT_SUPPORTED);
if (stream->get_presentation_position == NULL) return retval;
struct timespec halTimeStamp;
retval = Stream::analyzeStatus("get_presentation_position",
stream->get_presentation_position(stream, frames, &halTimeStamp),
ignoredErrors);
if (retval == Result::OK) {
timeStamp->tvSec = halTimeStamp.tv_sec;
timeStamp->tvNSec = halTimeStamp.tv_nsec;
}
return retval;
}
Return<void> StreamOut::getPresentationPosition(getPresentationPosition_cb _hidl_cb) {
uint64_t frames = 0;
TimeSpec timeStamp = {0, 0};
Result retval = getPresentationPositionImpl(mStream, &frames, &timeStamp);
_hidl_cb(retval, frames, timeStamp);
return Void();
}
Return<Result> StreamOut::start() {
return mStreamMmap->start();
}
Return<Result> StreamOut::stop() {
return mStreamMmap->stop();
}
Return<void> StreamOut::createMmapBuffer(int32_t minSizeFrames, createMmapBuffer_cb _hidl_cb) {
return mStreamMmap->createMmapBuffer(minSizeFrames, audio_stream_out_frame_size(mStream),
_hidl_cb);
}
Return<void> StreamOut::getMmapPosition(getMmapPosition_cb _hidl_cb) {
return mStreamMmap->getMmapPosition(_hidl_cb);
}
Return<void> StreamOut::debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) {
return mStreamCommon->debug(fd, options);
}
#if MAJOR_VERSION >= 4
Return<void> StreamOut::updateSourceMetadata(const SourceMetadata& sourceMetadata) {
if (mStream->update_source_metadata == nullptr) {
return Void(); // not supported by the HAL
}
std::vector<playback_track_metadata> halTracks;
halTracks.reserve(sourceMetadata.tracks.size());
for (auto& metadata : sourceMetadata.tracks) {
halTracks.push_back({
.usage = static_cast<audio_usage_t>(metadata.usage),
.content_type = static_cast<audio_content_type_t>(metadata.contentType),
.gain = metadata.gain,
});
}
const source_metadata_t halMetadata = {
.track_count = halTracks.size(),
.tracks = halTracks.data(),
};
mStream->update_source_metadata(mStream, &halMetadata);
return Void();
}
Return<Result> StreamOut::selectPresentation(int32_t /*presentationId*/, int32_t /*programId*/) {
return Result::NOT_SUPPORTED; // TODO: propagate to legacy
}
#endif
} // namespace implementation
} // namespace CPP_VERSION
} // namespace audio
} // namespace hardware
} // namespace android

View file

@ -0,0 +1,48 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_HARDWARE_AUDIO_CONVERSIONS_H_
#define ANDROID_HARDWARE_AUDIO_CONVERSIONS_H_
#include PATH(android/hardware/audio/FILE_VERSION/types.h)
#include <string>
#include <system/audio.h>
namespace android {
namespace hardware {
namespace audio {
namespace CPP_VERSION {
namespace implementation {
using namespace ::android::hardware::audio::common::CPP_VERSION;
using namespace ::android::hardware::audio::CPP_VERSION;
std::string deviceAddressToHal(const DeviceAddress& address);
#if MAJOR_VERSION >= 4
bool halToMicrophoneCharacteristics(MicrophoneInfo* pDst,
const struct audio_microphone_characteristic_t& src);
#endif
} // namespace implementation
} // namespace CPP_VERSION
} // namespace audio
} // namespace hardware
} // namespace android
#endif // ANDROID_HARDWARE_AUDIO_CONVERSIONS_H_

View file

@ -0,0 +1,146 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_HARDWARE_AUDIO_DEVICE_H
#define ANDROID_HARDWARE_AUDIO_DEVICE_H
#include PATH(android/hardware/audio/FILE_VERSION/IDevice.h)
#include "ParametersUtil.h"
#include <memory>
#include <hardware/audio.h>
#include <media/AudioParameter.h>
#include <hidl/Status.h>
#include <hidl/MQDescriptor.h>
#include <VersionUtils.h>
namespace android {
namespace hardware {
namespace audio {
namespace CPP_VERSION {
namespace implementation {
using ::android::sp;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::hardware::audio::common::CPP_VERSION::implementation::AudioInputFlagBitfield;
using ::android::hardware::audio::common::CPP_VERSION::implementation::AudioOutputFlagBitfield;
using namespace ::android::hardware::audio::common::CPP_VERSION;
using namespace ::android::hardware::audio::CPP_VERSION;
struct Device : public IDevice, public ParametersUtil {
explicit Device(audio_hw_device_t* device);
// Methods from ::android::hardware::audio::CPP_VERSION::IDevice follow.
Return<Result> initCheck() override;
Return<Result> setMasterVolume(float volume) override;
Return<void> getMasterVolume(getMasterVolume_cb _hidl_cb) override;
Return<Result> setMicMute(bool mute) override;
Return<void> getMicMute(getMicMute_cb _hidl_cb) override;
Return<Result> setMasterMute(bool mute) override;
Return<void> getMasterMute(getMasterMute_cb _hidl_cb) override;
Return<void> getInputBufferSize(const AudioConfig& config,
getInputBufferSize_cb _hidl_cb) override;
std::tuple<Result, sp<IStreamOut>> openOutputStreamImpl(int32_t ioHandle,
const DeviceAddress& device,
const AudioConfig& config,
AudioOutputFlagBitfield flags,
AudioConfig* suggestedConfig);
std::tuple<Result, sp<IStreamIn>> openInputStreamImpl(
int32_t ioHandle, const DeviceAddress& device, const AudioConfig& config,
AudioInputFlagBitfield flags, AudioSource source, AudioConfig* suggestedConfig);
#if MAJOR_VERSION == 2
Return<void> openOutputStream(int32_t ioHandle, const DeviceAddress& device,
const AudioConfig& config, AudioOutputFlagBitfield flags,
openOutputStream_cb _hidl_cb) override;
Return<void> openInputStream(int32_t ioHandle, const DeviceAddress& device,
const AudioConfig& config, AudioInputFlagBitfield flags,
AudioSource source, openInputStream_cb _hidl_cb) override;
#elif MAJOR_VERSION >= 4
Return<void> openOutputStream(int32_t ioHandle, const DeviceAddress& device,
const AudioConfig& config, AudioOutputFlagBitfield flags,
const SourceMetadata& sourceMetadata,
openOutputStream_cb _hidl_cb) override;
Return<void> openInputStream(int32_t ioHandle, const DeviceAddress& device,
const AudioConfig& config, AudioInputFlagBitfield flags,
const SinkMetadata& sinkMetadata,
openInputStream_cb _hidl_cb) override;
#endif
Return<bool> supportsAudioPatches() override;
Return<void> createAudioPatch(const hidl_vec<AudioPortConfig>& sources,
const hidl_vec<AudioPortConfig>& sinks,
createAudioPatch_cb _hidl_cb) override;
Return<Result> releaseAudioPatch(int32_t patch) override;
Return<void> getAudioPort(const AudioPort& port, getAudioPort_cb _hidl_cb) override;
Return<Result> setAudioPortConfig(const AudioPortConfig& config) override;
Return<Result> setScreenState(bool turnedOn) override;
#if MAJOR_VERSION == 2
Return<AudioHwSync> getHwAvSync() override;
Return<void> getParameters(const hidl_vec<hidl_string>& keys,
getParameters_cb _hidl_cb) override;
Return<Result> setParameters(const hidl_vec<ParameterValue>& parameters) override;
Return<void> debugDump(const hidl_handle& fd) override;
#elif MAJOR_VERSION >= 4
Return<void> getHwAvSync(getHwAvSync_cb _hidl_cb) override;
Return<void> getParameters(const hidl_vec<ParameterValue>& context,
const hidl_vec<hidl_string>& keys,
getParameters_cb _hidl_cb) override;
Return<Result> setParameters(const hidl_vec<ParameterValue>& context,
const hidl_vec<ParameterValue>& parameters) override;
Return<void> getMicrophones(getMicrophones_cb _hidl_cb) override;
Return<Result> setConnectedState(const DeviceAddress& address, bool connected) override;
#endif
Return<void> debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override;
// Utility methods for extending interfaces.
Result analyzeStatus(const char* funcName, int status,
const std::vector<int>& ignoreErrors = {});
void closeInputStream(audio_stream_in_t* stream);
void closeOutputStream(audio_stream_out_t* stream);
audio_hw_device_t* device() const { return mDevice; }
int halSetParameters(const char* keysAndValues) override;
private:
audio_hw_device_t* mDevice;
virtual ~Device();
// Methods from ParametersUtil.
char* halGetParameters(const char* keys) override;
uint32_t version() const { return mDevice->common.version; }
};
} // namespace implementation
} // namespace CPP_VERSION
} // namespace audio
} // namespace hardware
} // namespace android
#endif // ANDROID_HARDWARE_AUDIO_DEVICE_H

View file

@ -0,0 +1,64 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_HARDWARE_AUDIO_DEVICESFACTORY_H
#define ANDROID_HARDWARE_AUDIO_DEVICESFACTORY_H
#include PATH(android/hardware/audio/FILE_VERSION/IDevicesFactory.h)
#include <hardware/audio.h>
#include <hidl/Status.h>
#include <hidl/MQDescriptor.h>
namespace android {
namespace hardware {
namespace audio {
namespace CPP_VERSION {
namespace implementation {
using ::android::sp;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
using namespace ::android::hardware::audio::CPP_VERSION;
struct DevicesFactory : public IDevicesFactory {
#if MAJOR_VERSION == 2
Return<void> openDevice(IDevicesFactory::Device device, openDevice_cb _hidl_cb) override;
#elif MAJOR_VERSION >= 4
Return<void> openDevice(const hidl_string& device, openDevice_cb _hidl_cb) override;
Return<void> openPrimaryDevice(openPrimaryDevice_cb _hidl_cb) override;
#endif
private:
template <class DeviceShim, class Callback>
Return<void> openDevice(const char* moduleName, Callback _hidl_cb);
Return<void> openDevice(const char* moduleName, openDevice_cb _hidl_cb);
static int loadAudioInterface(const char* if_name, audio_hw_device_t** dev);
};
extern "C" IDevicesFactory* HIDL_FETCH_IDevicesFactory(const char* name);
} // namespace implementation
} // namespace CPP_VERSION
} // namespace audio
} // namespace hardware
} // namespace android
#endif // ANDROID_HARDWARE_AUDIO_DEVICESFACTORY_H

View file

@ -0,0 +1,70 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_HARDWARE_AUDIO_PARAMETERS_UTIL_H_
#define ANDROID_HARDWARE_AUDIO_PARAMETERS_UTIL_H_
#include PATH(android/hardware/audio/FILE_VERSION/types.h)
#include <functional>
#include <memory>
#include <hidl/HidlSupport.h>
#include <media/AudioParameter.h>
namespace android {
namespace hardware {
namespace audio {
namespace CPP_VERSION {
namespace implementation {
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
using namespace ::android::hardware::audio::common::CPP_VERSION;
using namespace ::android::hardware::audio::CPP_VERSION;
class ParametersUtil {
public:
Result setParam(const char* name, const char* value);
Result getParam(const char* name, bool* value);
Result getParam(const char* name, int* value);
Result getParam(const char* name, String8* value, AudioParameter context = {});
void getParametersImpl(
const hidl_vec<ParameterValue>& context, const hidl_vec<hidl_string>& keys,
std::function<void(Result retval, const hidl_vec<ParameterValue>& parameters)> cb);
std::unique_ptr<AudioParameter> getParams(const AudioParameter& keys);
Result setParam(const char* name, bool value);
Result setParam(const char* name, int value);
Result setParam(const char* name, float value);
Result setParametersImpl(const hidl_vec<ParameterValue>& context,
const hidl_vec<ParameterValue>& parameters);
Result setParams(const AudioParameter& param);
Result setParam(const char* name, const DeviceAddress& address);
protected:
virtual ~ParametersUtil() {}
virtual char* halGetParameters(const char* keys) = 0;
virtual int halSetParameters(const char* keysAndValues) = 0;
};
} // namespace implementation
} // namespace CPP_VERSION
} // namespace audio
} // namespace hardware
} // namespace android
#endif // ANDROID_HARDWARE_AUDIO_PARAMETERS_UTIL_H_

View file

@ -0,0 +1,135 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_HARDWARE_AUDIO_PRIMARYDEVICE_H
#define ANDROID_HARDWARE_AUDIO_PRIMARYDEVICE_H
#include PATH(android/hardware/audio/FILE_VERSION/IPrimaryDevice.h)
#include "Device.h"
#include <hidl/Status.h>
#include <hidl/MQDescriptor.h>
namespace android {
namespace hardware {
namespace audio {
namespace CPP_VERSION {
namespace implementation {
using ::android::sp;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
using namespace ::android::hardware::audio::common::CPP_VERSION;
using namespace ::android::hardware::audio::CPP_VERSION;
struct PrimaryDevice : public IPrimaryDevice {
explicit PrimaryDevice(audio_hw_device_t* device);
// Methods from ::android::hardware::audio::CPP_VERSION::IDevice follow.
Return<Result> initCheck() override;
Return<Result> setMasterVolume(float volume) override;
Return<void> getMasterVolume(getMasterVolume_cb _hidl_cb) override;
Return<Result> setMicMute(bool mute) override;
Return<void> getMicMute(getMicMute_cb _hidl_cb) override;
Return<Result> setMasterMute(bool mute) override;
Return<void> getMasterMute(getMasterMute_cb _hidl_cb) override;
Return<void> getInputBufferSize(const AudioConfig& config,
getInputBufferSize_cb _hidl_cb) override;
Return<void> openOutputStream(int32_t ioHandle, const DeviceAddress& device,
const AudioConfig& config, AudioOutputFlagBitfield flags,
#if MAJOR_VERSION >= 4
const SourceMetadata& sourceMetadata,
#endif
openOutputStream_cb _hidl_cb) override;
Return<void> openInputStream(int32_t ioHandle, const DeviceAddress& device,
const AudioConfig& config, AudioInputFlagBitfield flags,
AudioSource source, openInputStream_cb _hidl_cb);
#if MAJOR_VERSION >= 4
Return<void> openInputStream(int32_t ioHandle, const DeviceAddress& device,
const AudioConfig& config, AudioInputFlagBitfield flags,
const SinkMetadata& sinkMetadata,
openInputStream_cb _hidl_cb) override;
#endif
Return<bool> supportsAudioPatches() override;
Return<void> createAudioPatch(const hidl_vec<AudioPortConfig>& sources,
const hidl_vec<AudioPortConfig>& sinks,
createAudioPatch_cb _hidl_cb) override;
Return<Result> releaseAudioPatch(int32_t patch) override;
Return<void> getAudioPort(const AudioPort& port, getAudioPort_cb _hidl_cb) override;
Return<Result> setAudioPortConfig(const AudioPortConfig& config) override;
Return<Result> setScreenState(bool turnedOn) override;
#if MAJOR_VERSION == 2
Return<AudioHwSync> getHwAvSync() override;
Return<void> getParameters(const hidl_vec<hidl_string>& keys,
getParameters_cb _hidl_cb) override;
Return<Result> setParameters(const hidl_vec<ParameterValue>& parameters) override;
Return<void> debugDump(const hidl_handle& fd) override;
#elif MAJOR_VERSION >= 4
Return<void> getHwAvSync(getHwAvSync_cb _hidl_cb) override;
Return<void> getParameters(const hidl_vec<ParameterValue>& context,
const hidl_vec<hidl_string>& keys,
getParameters_cb _hidl_cb) override;
Return<Result> setParameters(const hidl_vec<ParameterValue>& context,
const hidl_vec<ParameterValue>& parameters) override;
Return<void> getMicrophones(getMicrophones_cb _hidl_cb) override;
Return<Result> setConnectedState(const DeviceAddress& address, bool connected) override;
#endif
Return<void> debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override;
// Methods from ::android::hardware::audio::CPP_VERSION::IPrimaryDevice follow.
Return<Result> setVoiceVolume(float volume) override;
Return<Result> setMode(AudioMode mode) override;
Return<void> getBtScoNrecEnabled(getBtScoNrecEnabled_cb _hidl_cb) override;
Return<Result> setBtScoNrecEnabled(bool enabled) override;
Return<void> getBtScoWidebandEnabled(getBtScoWidebandEnabled_cb _hidl_cb) override;
Return<Result> setBtScoWidebandEnabled(bool enabled) override;
Return<void> getTtyMode(getTtyMode_cb _hidl_cb) override;
Return<Result> setTtyMode(IPrimaryDevice::TtyMode mode) override;
Return<void> getHacEnabled(getHacEnabled_cb _hidl_cb) override;
Return<Result> setHacEnabled(bool enabled) override;
#if MAJOR_VERSION >= 4
Return<Result> setBtScoHeadsetDebugName(const hidl_string& name) override;
Return<void> getBtHfpEnabled(getBtHfpEnabled_cb _hidl_cb) override;
Return<Result> setBtHfpEnabled(bool enabled) override;
Return<Result> setBtHfpSampleRate(uint32_t sampleRateHz) override;
Return<Result> setBtHfpVolume(float volume) override;
Return<Result> updateRotation(IPrimaryDevice::Rotation rotation) override;
#endif
private:
sp<Device> mDevice;
virtual ~PrimaryDevice();
};
} // namespace implementation
} // namespace CPP_VERSION
} // namespace audio
} // namespace hardware
} // namespace android
#endif // ANDROID_HARDWARE_AUDIO_PRIMARYDEVICE_H

View file

@ -0,0 +1,218 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_HARDWARE_AUDIO_STREAM_H
#define ANDROID_HARDWARE_AUDIO_STREAM_H
#include PATH(android/hardware/audio/FILE_VERSION/IStream.h)
#include "ParametersUtil.h"
#include <vector>
#include <hardware/audio.h>
#include <hidl/Status.h>
#include <hidl/MQDescriptor.h>
#include <VersionUtils.h>
namespace android {
namespace hardware {
namespace audio {
namespace CPP_VERSION {
namespace implementation {
using ::android::sp;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::hardware::audio::common::CPP_VERSION::implementation::AudioChannelBitfield;
using namespace ::android::hardware::audio::common::CPP_VERSION;
using namespace ::android::hardware::audio::CPP_VERSION;
struct Stream : public IStream, public ParametersUtil {
explicit Stream(audio_stream_t* stream);
/** 1GiB is the maximum buffer size the HAL client is allowed to request.
* This value has been chosen to be under SIZE_MAX and still big enough
* for all audio use case.
* Keep private for 2.0, put in .hal in 2.1
*/
static constexpr uint32_t MAX_BUFFER_SIZE = 2 << 30 /* == 1GiB */;
// Methods from ::android::hardware::audio::CPP_VERSION::IStream follow.
Return<uint64_t> getFrameSize() override;
Return<uint64_t> getFrameCount() override;
Return<uint64_t> getBufferSize() override;
Return<uint32_t> getSampleRate() override;
#if MAJOR_VERSION == 2
Return<void> getSupportedSampleRates(getSupportedSampleRates_cb _hidl_cb) override;
Return<void> getSupportedChannelMasks(getSupportedChannelMasks_cb _hidl_cb) override;
#endif
Return<void> getSupportedSampleRates(AudioFormat format, getSupportedSampleRates_cb _hidl_cb);
Return<void> getSupportedChannelMasks(AudioFormat format, getSupportedChannelMasks_cb _hidl_cb);
Return<Result> setSampleRate(uint32_t sampleRateHz) override;
Return<AudioChannelBitfield> getChannelMask() override;
Return<Result> setChannelMask(AudioChannelBitfield mask) override;
Return<AudioFormat> getFormat() override;
Return<void> getSupportedFormats(getSupportedFormats_cb _hidl_cb) override;
Return<Result> setFormat(AudioFormat format) override;
Return<void> getAudioProperties(getAudioProperties_cb _hidl_cb) override;
Return<Result> addEffect(uint64_t effectId) override;
Return<Result> removeEffect(uint64_t effectId) override;
Return<Result> standby() override;
#if MAJOR_VERSION == 2
Return<AudioDevice> getDevice() override;
Return<Result> setDevice(const DeviceAddress& address) override;
Return<void> getParameters(const hidl_vec<hidl_string>& keys,
getParameters_cb _hidl_cb) override;
Return<Result> setParameters(const hidl_vec<ParameterValue>& parameters) override;
Return<Result> setConnectedState(const DeviceAddress& address, bool connected) override;
#elif MAJOR_VERSION >= 4
Return<void> getDevices(getDevices_cb _hidl_cb) override;
Return<Result> setDevices(const hidl_vec<DeviceAddress>& devices) override;
Return<void> getParameters(const hidl_vec<ParameterValue>& context,
const hidl_vec<hidl_string>& keys,
getParameters_cb _hidl_cb) override;
Return<Result> setParameters(const hidl_vec<ParameterValue>& context,
const hidl_vec<ParameterValue>& parameters) override;
#endif
Return<Result> setHwAvSync(uint32_t hwAvSync) override;
Return<Result> start() override;
Return<Result> stop() override;
Return<void> createMmapBuffer(int32_t minSizeFrames, createMmapBuffer_cb _hidl_cb) override;
Return<void> getMmapPosition(getMmapPosition_cb _hidl_cb) override;
Return<Result> close() override;
Return<void> debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override;
#if MAJOR_VERSION == 2
Return<void> debugDump(const hidl_handle& fd) override;
#endif
// Utility methods for extending interfaces.
static Result analyzeStatus(const char* funcName, int status);
static Result analyzeStatus(const char* funcName, int status,
const std::vector<int>& ignoreErrors);
private:
audio_stream_t* mStream;
virtual ~Stream();
// Methods from ParametersUtil.
char* halGetParameters(const char* keys) override;
int halSetParameters(const char* keysAndValues) override;
};
template <typename T>
struct StreamMmap : public RefBase {
explicit StreamMmap(T* stream) : mStream(stream) {}
Return<Result> start();
Return<Result> stop();
Return<void> createMmapBuffer(int32_t minSizeFrames, size_t frameSize,
IStream::createMmapBuffer_cb _hidl_cb);
Return<void> getMmapPosition(IStream::getMmapPosition_cb _hidl_cb);
private:
StreamMmap() {}
T* mStream;
};
template <typename T>
Return<Result> StreamMmap<T>::start() {
if (mStream->start == NULL) return Result::NOT_SUPPORTED;
int result = mStream->start(mStream);
return Stream::analyzeStatus("start", result);
}
template <typename T>
Return<Result> StreamMmap<T>::stop() {
if (mStream->stop == NULL) return Result::NOT_SUPPORTED;
int result = mStream->stop(mStream);
return Stream::analyzeStatus("stop", result);
}
template <typename T>
Return<void> StreamMmap<T>::createMmapBuffer(int32_t minSizeFrames, size_t frameSize,
IStream::createMmapBuffer_cb _hidl_cb) {
Result retval(Result::NOT_SUPPORTED);
MmapBufferInfo info;
native_handle_t* hidlHandle = nullptr;
if (mStream->create_mmap_buffer != NULL) {
struct audio_mmap_buffer_info halInfo;
retval = Stream::analyzeStatus(
"create_mmap_buffer", mStream->create_mmap_buffer(mStream, minSizeFrames, &halInfo));
if (retval == Result::OK) {
hidlHandle = native_handle_create(1, 0);
hidlHandle->data[0] = halInfo.shared_memory_fd;
// Negative buffer size frame is a legacy hack to indicate that the buffer
// is shareable to applications before the relevant flag was introduced
bool applicationShareable =
halInfo.flags & AUDIO_MMAP_APPLICATION_SHAREABLE || halInfo.buffer_size_frames < 0;
halInfo.buffer_size_frames = abs(halInfo.buffer_size_frames);
info.sharedMemory = // hidl_memory size must always be positive
hidl_memory("audio_buffer", hidlHandle, frameSize * halInfo.buffer_size_frames);
#if MAJOR_VERSION == 2
if (applicationShareable) {
halInfo.buffer_size_frames *= -1;
}
#else
info.flags =
halInfo.flags | (applicationShareable ? MmapBufferFlag::APPLICATION_SHAREABLE
: MmapBufferFlag::NONE);
#endif
info.bufferSizeFrames = halInfo.buffer_size_frames;
info.burstSizeFrames = halInfo.burst_size_frames;
}
}
_hidl_cb(retval, info);
if (hidlHandle != nullptr) {
native_handle_delete(hidlHandle);
}
return Void();
}
template <typename T>
Return<void> StreamMmap<T>::getMmapPosition(IStream::getMmapPosition_cb _hidl_cb) {
Result retval(Result::NOT_SUPPORTED);
MmapPosition position;
if (mStream->get_mmap_position != NULL) {
struct audio_mmap_position halPosition;
retval = Stream::analyzeStatus("get_mmap_position",
mStream->get_mmap_position(mStream, &halPosition));
if (retval == Result::OK) {
position.timeNanoseconds = halPosition.time_nanoseconds;
position.positionFrames = halPosition.position_frames;
}
}
_hidl_cb(retval, position);
return Void();
}
} // namespace implementation
} // namespace CPP_VERSION
} // namespace audio
} // namespace hardware
} // namespace android
#endif // ANDROID_HARDWARE_AUDIO_STREAM_H

View file

@ -0,0 +1,144 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_HARDWARE_AUDIO_STREAMIN_H
#define ANDROID_HARDWARE_AUDIO_STREAMIN_H
#include PATH(android/hardware/audio/FILE_VERSION/IStreamIn.h)
#include "Device.h"
#include "Stream.h"
#include <atomic>
#include <memory>
#include <fmq/EventFlag.h>
#include <fmq/MessageQueue.h>
#include <hidl/MQDescriptor.h>
#include <hidl/Status.h>
#include <utils/Thread.h>
namespace android {
namespace hardware {
namespace audio {
namespace CPP_VERSION {
namespace implementation {
using ::android::sp;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
using namespace ::android::hardware::audio::common::CPP_VERSION;
using namespace ::android::hardware::audio::CPP_VERSION;
struct StreamIn : public IStreamIn {
typedef MessageQueue<ReadParameters, kSynchronizedReadWrite> CommandMQ;
typedef MessageQueue<uint8_t, kSynchronizedReadWrite> DataMQ;
typedef MessageQueue<ReadStatus, kSynchronizedReadWrite> StatusMQ;
StreamIn(const sp<Device>& device, audio_stream_in_t* stream);
// Methods from ::android::hardware::audio::CPP_VERSION::IStream follow.
Return<uint64_t> getFrameSize() override;
Return<uint64_t> getFrameCount() override;
Return<uint64_t> getBufferSize() override;
Return<uint32_t> getSampleRate() override;
#if MAJOR_VERSION == 2
Return<void> getSupportedSampleRates(getSupportedSampleRates_cb _hidl_cb) override;
Return<void> getSupportedChannelMasks(getSupportedChannelMasks_cb _hidl_cb) override;
#endif
Return<void> getSupportedSampleRates(AudioFormat format, getSupportedSampleRates_cb _hidl_cb);
Return<void> getSupportedChannelMasks(AudioFormat format, getSupportedChannelMasks_cb _hidl_cb);
Return<Result> setSampleRate(uint32_t sampleRateHz) override;
Return<AudioChannelBitfield> getChannelMask() override;
Return<Result> setChannelMask(AudioChannelBitfield mask) override;
Return<AudioFormat> getFormat() override;
Return<void> getSupportedFormats(getSupportedFormats_cb _hidl_cb) override;
Return<Result> setFormat(AudioFormat format) override;
Return<void> getAudioProperties(getAudioProperties_cb _hidl_cb) override;
Return<Result> addEffect(uint64_t effectId) override;
Return<Result> removeEffect(uint64_t effectId) override;
Return<Result> standby() override;
#if MAJOR_VERSION == 2
Return<AudioDevice> getDevice() override;
Return<Result> setDevice(const DeviceAddress& address) override;
Return<void> getParameters(const hidl_vec<hidl_string>& keys,
getParameters_cb _hidl_cb) override;
Return<Result> setParameters(const hidl_vec<ParameterValue>& parameters) override;
Return<Result> setConnectedState(const DeviceAddress& address, bool connected) override;
#elif MAJOR_VERSION >= 4
Return<void> getDevices(getDevices_cb _hidl_cb) override;
Return<Result> setDevices(const hidl_vec<DeviceAddress>& devices) override;
Return<void> getParameters(const hidl_vec<ParameterValue>& context,
const hidl_vec<hidl_string>& keys,
getParameters_cb _hidl_cb) override;
Return<Result> setParameters(const hidl_vec<ParameterValue>& context,
const hidl_vec<ParameterValue>& parameters) override;
#endif
Return<Result> setHwAvSync(uint32_t hwAvSync) override;
Return<Result> close() override;
Return<void> debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override;
#if MAJOR_VERSION == 2
Return<void> debugDump(const hidl_handle& fd) override;
#endif
// Methods from ::android::hardware::audio::CPP_VERSION::IStreamIn follow.
Return<void> getAudioSource(getAudioSource_cb _hidl_cb) override;
Return<Result> setGain(float gain) override;
Return<void> prepareForReading(uint32_t frameSize, uint32_t framesCount,
prepareForReading_cb _hidl_cb) override;
Return<uint32_t> getInputFramesLost() override;
Return<void> getCapturePosition(getCapturePosition_cb _hidl_cb) override;
Return<Result> start() override;
Return<Result> stop() override;
Return<void> createMmapBuffer(int32_t minSizeFrames, createMmapBuffer_cb _hidl_cb) override;
Return<void> getMmapPosition(getMmapPosition_cb _hidl_cb) override;
#if MAJOR_VERSION >= 4
Return<void> updateSinkMetadata(const SinkMetadata& sinkMetadata) override;
Return<void> getActiveMicrophones(getActiveMicrophones_cb _hidl_cb) override;
#endif
#if MAJOR_VERSION >= 5
Return<Result> setMicrophoneDirection(MicrophoneDirection direction) override;
Return<Result> setMicrophoneFieldDimension(float zoom) override;
#endif
static Result getCapturePositionImpl(audio_stream_in_t* stream, uint64_t* frames,
uint64_t* time);
private:
bool mIsClosed;
const sp<Device> mDevice;
audio_stream_in_t* mStream;
const sp<Stream> mStreamCommon;
const sp<StreamMmap<audio_stream_in_t>> mStreamMmap;
std::unique_ptr<CommandMQ> mCommandMQ;
std::unique_ptr<DataMQ> mDataMQ;
std::unique_ptr<StatusMQ> mStatusMQ;
EventFlag* mEfGroup;
std::atomic<bool> mStopReadThread;
sp<Thread> mReadThread;
virtual ~StreamIn();
};
} // namespace implementation
} // namespace CPP_VERSION
} // namespace audio
} // namespace hardware
} // namespace android
#endif // ANDROID_HARDWARE_AUDIO_STREAMIN_H

View file

@ -0,0 +1,153 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_HARDWARE_AUDIO_STREAMOUT_H
#define ANDROID_HARDWARE_AUDIO_STREAMOUT_H
#include PATH(android/hardware/audio/FILE_VERSION/IStreamOut.h)
#include "Device.h"
#include "Stream.h"
#include <atomic>
#include <memory>
#include <fmq/EventFlag.h>
#include <fmq/MessageQueue.h>
#include <hidl/MQDescriptor.h>
#include <hidl/Status.h>
#include <utils/Thread.h>
namespace android {
namespace hardware {
namespace audio {
namespace CPP_VERSION {
namespace implementation {
using ::android::sp;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
using namespace ::android::hardware::audio::common::CPP_VERSION;
using namespace ::android::hardware::audio::CPP_VERSION;
struct StreamOut : public IStreamOut {
typedef MessageQueue<WriteCommand, kSynchronizedReadWrite> CommandMQ;
typedef MessageQueue<uint8_t, kSynchronizedReadWrite> DataMQ;
typedef MessageQueue<WriteStatus, kSynchronizedReadWrite> StatusMQ;
StreamOut(const sp<Device>& device, audio_stream_out_t* stream);
// Methods from ::android::hardware::audio::CPP_VERSION::IStream follow.
Return<uint64_t> getFrameSize() override;
Return<uint64_t> getFrameCount() override;
Return<uint64_t> getBufferSize() override;
Return<uint32_t> getSampleRate() override;
#if MAJOR_VERSION == 2
Return<void> getSupportedSampleRates(getSupportedSampleRates_cb _hidl_cb) override;
Return<void> getSupportedChannelMasks(getSupportedChannelMasks_cb _hidl_cb) override;
#endif
Return<void> getSupportedSampleRates(AudioFormat format, getSupportedSampleRates_cb _hidl_cb);
Return<void> getSupportedChannelMasks(AudioFormat format, getSupportedChannelMasks_cb _hidl_cb);
Return<Result> setSampleRate(uint32_t sampleRateHz) override;
Return<AudioChannelBitfield> getChannelMask() override;
Return<Result> setChannelMask(AudioChannelBitfield mask) override;
Return<AudioFormat> getFormat() override;
Return<void> getSupportedFormats(getSupportedFormats_cb _hidl_cb) override;
Return<Result> setFormat(AudioFormat format) override;
Return<void> getAudioProperties(getAudioProperties_cb _hidl_cb) override;
Return<Result> addEffect(uint64_t effectId) override;
Return<Result> removeEffect(uint64_t effectId) override;
Return<Result> standby() override;
#if MAJOR_VERSION == 2
Return<AudioDevice> getDevice() override;
Return<Result> setDevice(const DeviceAddress& address) override;
Return<void> getParameters(const hidl_vec<hidl_string>& keys,
getParameters_cb _hidl_cb) override;
Return<Result> setParameters(const hidl_vec<ParameterValue>& parameters) override;
Return<Result> setConnectedState(const DeviceAddress& address, bool connected) override;
#elif MAJOR_VERSION >= 4
Return<void> getDevices(getDevices_cb _hidl_cb) override;
Return<Result> setDevices(const hidl_vec<DeviceAddress>& devices) override;
Return<void> getParameters(const hidl_vec<ParameterValue>& context,
const hidl_vec<hidl_string>& keys,
getParameters_cb _hidl_cb) override;
Return<Result> setParameters(const hidl_vec<ParameterValue>& context,
const hidl_vec<ParameterValue>& parameters) override;
#endif
Return<Result> setHwAvSync(uint32_t hwAvSync) override;
Return<Result> close() override;
Return<void> debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override;
#if MAJOR_VERSION == 2
Return<void> debugDump(const hidl_handle& fd) override;
#endif
// Methods from ::android::hardware::audio::CPP_VERSION::IStreamOut follow.
Return<uint32_t> getLatency() override;
Return<Result> setVolume(float left, float right) override;
Return<void> prepareForWriting(uint32_t frameSize, uint32_t framesCount,
prepareForWriting_cb _hidl_cb) override;
Return<void> getRenderPosition(getRenderPosition_cb _hidl_cb) override;
Return<void> getNextWriteTimestamp(getNextWriteTimestamp_cb _hidl_cb) override;
Return<Result> setCallback(const sp<IStreamOutCallback>& callback) override;
Return<Result> clearCallback() override;
Return<void> supportsPauseAndResume(supportsPauseAndResume_cb _hidl_cb) override;
Return<Result> pause() override;
Return<Result> resume() override;
Return<bool> supportsDrain() override;
Return<Result> drain(AudioDrain type) override;
Return<Result> flush() override;
Return<void> getPresentationPosition(getPresentationPosition_cb _hidl_cb) override;
Return<Result> start() override;
Return<Result> stop() override;
Return<void> createMmapBuffer(int32_t minSizeFrames, createMmapBuffer_cb _hidl_cb) override;
Return<void> getMmapPosition(getMmapPosition_cb _hidl_cb) override;
#if MAJOR_VERSION >= 4
Return<void> updateSourceMetadata(const SourceMetadata& sourceMetadata) override;
Return<Result> selectPresentation(int32_t presentationId, int32_t programId) override;
#endif
static Result getPresentationPositionImpl(audio_stream_out_t* stream, uint64_t* frames,
TimeSpec* timeStamp);
private:
bool mIsClosed;
const sp<Device> mDevice;
audio_stream_out_t* mStream;
const sp<Stream> mStreamCommon;
const sp<StreamMmap<audio_stream_out_t>> mStreamMmap;
sp<IStreamOutCallback> mCallback;
std::unique_ptr<CommandMQ> mCommandMQ;
std::unique_ptr<DataMQ> mDataMQ;
std::unique_ptr<StatusMQ> mStatusMQ;
EventFlag* mEfGroup;
std::atomic<bool> mStopWriteThread;
sp<Thread> mWriteThread;
virtual ~StreamOut();
static int asyncCallback(stream_callback_event_t event, void* param, void* cookie);
};
} // namespace implementation
} // namespace CPP_VERSION
} // namespace audio
} // namespace hardware
} // namespace android
#endif // ANDROID_HARDWARE_AUDIO_STREAMOUT_H

View file

@ -0,0 +1,80 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_HARDWARE_AUDIO_UTIL_H
#define ANDROID_HARDWARE_AUDIO_UTIL_H
#include PATH(android/hardware/audio/FILE_VERSION/types.h)
#include <algorithm>
#include <vector>
#include <system/audio.h>
namespace android {
namespace hardware {
namespace audio {
namespace CPP_VERSION {
namespace implementation {
using namespace ::android::hardware::audio::common::CPP_VERSION;
using namespace ::android::hardware::audio::CPP_VERSION;
/** @return true if gain is between 0 and 1 included. */
constexpr bool isGainNormalized(float gain) {
return gain >= 0.0 && gain <= 1.0;
}
namespace util {
template <typename T>
inline bool element_in(T e, const std::vector<T>& v) {
return std::find(v.begin(), v.end(), e) != v.end();
}
static inline Result analyzeStatus(status_t status) {
switch (status) {
case 0:
return Result::OK;
case -EINVAL:
return Result::INVALID_ARGUMENTS;
case -ENODATA:
return Result::INVALID_STATE;
case -ENODEV:
return Result::NOT_INITIALIZED;
case -ENOSYS:
return Result::NOT_SUPPORTED;
default:
return Result::INVALID_STATE;
}
}
static inline Result analyzeStatus(const char* className, const char* funcName, status_t status,
const std::vector<int>& ignoreErrors = {}) {
if (status != 0 && !element_in(-status, ignoreErrors)) {
ALOGW("Error from HAL %s in function %s: %s", className, funcName, strerror(-status));
}
return analyzeStatus(status);
}
} // namespace util
} // namespace implementation
} // namespace CPP_VERSION
} // namespace audio
} // namespace hardware
} // namespace android
#endif // ANDROID_HARDWARE_AUDIO_UTIL_H

View file

@ -39,15 +39,6 @@ TARGET_BOOTANIMATION_HALF_RES := true
# Device characteristics
PRODUCT_CHARACTERISTICS := tablet
# Dalvik
PRODUCT_PROPERTY_OVERRIDES += \
dalvik.vm.heapstartsize=8m \
dalvik.vm.heapgrowthlimit=256m \
dalvik.vm.heapsize=512m \
dalvik.vm.heaptargetutilization=0.75 \
dalvik.vm.heapminfree=512k \
dalvik.vm.heapmaxfree=8m
# Permissions
PRODUCT_COPY_FILES += \
external/ant-wireless/antradio-library/com.dsi.ant.antradio_library.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/com.dsi.ant.antradio_library.xml \
@ -107,24 +98,26 @@ PRODUCT_PACKAGES += \
# Audio
PRODUCT_PACKAGES += \
android.hardware.audio@2.0-service \
android.hardware.audio@5.0-impl \
android.hardware.audio@5.0-impl.gts3l \
android.hardware.audio.effect@5.0-impl \
android.hardware.audio.service \
android.hardware.bluetooth.audio@2.0-impl:32 \
android.hardware.soundtrigger@2.1-impl:32 \
audio.a2dp.default \
android.hardware.bluetooth.audio@2.0-impl \
android.hardware.soundtrigger@2.1-impl \
audio.bluetooth.default \
audio.primary.msm8996 \
audio.r_submix.default \
audio.usb.default \
libaacwrapper \
libaudio-resampler \
cplay \
liba2dpoffload \
libaudioroute \
libcirrusspkrprot \
libhdmiedid \
libhfp \
libqcompostprocbundle \
libqcomvisualizer \
libqcomvoiceprocessing \
libvolumelistener \
tinymix
libsndmonitor \
libspkrprot \
libvolumelistener
PRODUCT_COPY_FILES += \
$(LOCAL_PATH)/configs/audio/audio_effects.xml:$(TARGET_COPY_OUT_VENDOR)/etc/audio_effects.xml \
@ -146,11 +139,9 @@ PRODUCT_COPY_FILES += \
# Camera
PRODUCT_PACKAGES += \
android.hardware.camera.provider@2.4-impl \
vendor.qti.hardware.camera.device@1.0 \
vendor.qti.hardware.camera.device@1.0_vendor
PRODUCT_PACKAGES += \
android.hardware.camera.provider@2.4-impl:32 \
android.hardware.camera.provider@2.4-service \
camera.msm8996 \
Snap
# Connectivity Engine support (CNE)
@ -175,8 +166,8 @@ PRODUCT_PACKAGES += \
libtinyxml
PRODUCT_COPY_FILES += \
$(LOCAL_PATH)/configs/display/hdr_tm_config.xml:$(TARGET_COPY_OUT_VENDOR)/etc/hdr_tm_config.xml \
$(LOCAL_PATH)/configs/display/qdcm_calib_data_ss_dsi_panel_ANA38401_AMS968HH01_QXGA.xml:$(TARGET_COPY_OUT_VENDOR)/etc/qdcm_calib_data_ss_dsi_panel_ANA38401_AMS968HH01_QXGA.xml
$(LOCAL_PATH)/configs/display/hdr_tm_config.xml:$(TARGET_COPY_OUT_VENDOR)/vendor/etc/hdr_tm_config.xml \
$(LOCAL_PATH)/configs/display/qdcm_calib_data_ss_dsi_panel_ANA38401_AMS968HH01_QXGA.xml:$(TARGET_COPY_OUT_VENDOR)/vendor/etc/qdcm_calib_data_ss_dsi_panel_ANA38401_AMS968HH01_QXGA.xml
# Doze mode
PRODUCT_PACKAGES += \

396
configs/manifest.xml → manifest.xml Executable file → Normal file
View file

@ -1,31 +1,4 @@
<!-- Copyright (c) 2017, 2018 The Linux Foundation. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of The Linux Foundation nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-->
<manifest version="1.0" type="device">
<manifest version="1.0" type="device" target-level="legacy">
<hal format="hidl">
<name>android.hardware.audio</name>
<transport>hwbinder</transport>
@ -53,15 +26,6 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<instance>default</instance>
</interface>
</hal>
<hal format="hidl">
<name>vendor.samsung.hardware.biometrics.fingerprint</name>
<transport>hwbinder</transport>
<version>2.1</version>
<interface>
<name>ISecBiometricsFingerprint</name>
<instance>default</instance>
</interface>
</hal>
<hal format="hidl">
<name>android.hardware.bluetooth</name>
<transport>hwbinder</transport>
@ -81,12 +45,21 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
</interface>
</hal>
<hal format="hidl">
<name>android.hardware.camera.provider</name>
<transport arch="32">passthrough</transport>
<version>2.4</version>
<name>android.hardware.broadcastradio</name>
<transport>hwbinder</transport>
<version>1.0</version>
<interface>
<name>ICameraProvider</name>
<instance>legacy/0</instance>
<name>IBroadcastRadioFactory</name>
<instance>default</instance>
</interface>
</hal>
<hal format="hidl">
<name>android.hardware.cas</name>
<transport>hwbinder</transport>
<version>1.0</version>
<interface>
<name>IMediaCasService</name>
<instance>default</instance>
</interface>
</hal>
<hal format="hidl">
@ -132,7 +105,6 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<name>IGnss</name>
<instance>default</instance>
</interface>
<fqname>@1.0::IGnss/default</fqname>
<fqname>@1.0::IGnss/gnss_vendor</fqname>
</hal>
<hal format="hidl">
@ -162,13 +134,14 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<instance>default</instance>
</interface>
</hal>
<hal format="hidl">
<hal format="hidl" override="true">
<name>android.hardware.health</name>
<transport>hwbinder</transport>
<version>2.0</version>
<interface>
<name>IHealth</name>
<instance>default</instance>
<instance>sehhealth</instance>
</interface>
</hal>
<hal format="hidl">
@ -214,34 +187,12 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<hal format="hidl">
<name>android.hardware.power</name>
<transport>hwbinder</transport>
<version>1.2</version>
<version>1.0</version>
<interface>
<name>IPower</name>
<instance>default</instance>
</interface>
</hal>
<hal format="hidl">
<name>android.hardware.radio</name>
<transport>hwbinder</transport>
<version>1.1</version>
<interface>
<name>IRadio</name>
<instance>slot1</instance>
</interface>
<interface>
<name>ISap</name>
<instance>slot1</instance>
</interface>
</hal>
<hal format="hidl">
<name>android.hardware.radio.deprecated</name>
<transport>hwbinder</transport>
<version>1.0</version>
<interface>
<name>IOemHook</name>
<instance>slot1</instance>
</interface>
</hal>
<hal format="hidl">
<name>android.hardware.renderscript</name>
<transport arch="32+64">passthrough</transport>
@ -270,20 +221,11 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
</interface>
</hal>
<hal format="hidl">
<name>android.hardware.tetheroffload.config</name>
<name>android.hardware.thermal</name>
<transport>hwbinder</transport>
<version>1.0</version>
<interface>
<name>IOffloadConfig</name>
<instance>default</instance>
</interface>
</hal>
<hal format="hidl">
<name>android.hardware.tetheroffload.control</name>
<transport>hwbinder</transport>
<version>1.0</version>
<interface>
<name>IOffloadControl</name>
<name>IThermal</name>
<instance>default</instance>
</interface>
</hal>
@ -296,19 +238,10 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<instance>default</instance>
</interface>
</hal>
<hal format="hidl">
<name>android.hardware.vibrator</name>
<transport>hwbinder</transport>
<version>1.0</version>
<interface>
<name>IVibrator</name>
<instance>default</instance>
</interface>
</hal>
<hal format="hidl">
<name>android.hardware.wifi</name>
<transport>hwbinder</transport>
<version>1.3</version>
<version>1.2</version>
<interface>
<name>IWifi</name>
<instance>default</instance>
@ -317,7 +250,7 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<hal format="hidl">
<name>android.hardware.wifi.hostapd</name>
<transport>hwbinder</transport>
<version>1.1</version>
<version>1.0</version>
<interface>
<name>IHostapd</name>
<instance>default</instance>
@ -326,7 +259,7 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<hal format="hidl">
<name>android.hardware.wifi.supplicant</name>
<transport>hwbinder</transport>
<version>1.2</version>
<version>1.1</version>
<interface>
<name>ISupplicant</name>
<instance>default</instance>
@ -342,22 +275,40 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
</interface>
</hal>
<hal format="hidl">
<name>com.qualcomm.qti.dpm.api</name>
<name>com.qualcomm.qti.bluetooth_audio</name>
<transport>hwbinder</transport>
<version>1.0</version>
<interface>
<name>IdpmQmi</name>
<instance>dpmQmiService</instance>
<name>IBluetoothAudio</name>
<instance>default</instance>
</interface>
</hal>
<hal format="hidl">
<hal format="hidl" override="true">
<name>com.qualcomm.qti.dpm.api</name>
<transport>hwbinder</transport>
</hal>
<hal format="hidl" override="true">
<name>com.qualcomm.qti.imscmservice</name>
<transport>hwbinder</transport>
</hal>
<hal format="hidl" override="true">
<name>com.qualcomm.qti.uceservice</name>
<transport>hwbinder</transport>
</hal>
<hal format="hidl">
<name>com.qualcomm.qti.wifidisplayhal</name>
<transport>hwbinder</transport>
<version>1.0</version>
<interface>
<name>IUceService</name>
<instance>com.qualcomm.qti.uceservice</instance>
<name>IDSManager</name>
<instance>wifidisplaydshal</instance>
</interface>
<interface>
<name>IHDCPSession</name>
<instance>wifidisplayhdcphal</instance>
</interface>
<fqname>@1.0::IDSManager/wifidisplaydshal</fqname>
<fqname>@1.0::IHDCPSession/wifidisplayhdcphal</fqname>
</hal>
<hal format="hidl">
<name>vendor.display.color</name>
@ -386,96 +337,31 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<instance>default</instance>
</interface>
</hal>
<!-- <hal format="hidl">
<hal format="hidl">
<name>vendor.lineage.livedisplay</name>
<transport arch="32+64">passthrough</transport>
<transport>hwbinder</transport>
<version>2.0</version>
<interface>
<name>IAdaptiveBacklight</name>
<instance>default</instance>
</interface>
<interface>
<name>IAutoContrast</name>
<instance>default</instance>
</interface>
<interface>
<name>IColorBalance</name>
<instance>default</instance>
</interface>
<interface>
<name>IColorEnhancement</name>
<instance>default</instance>
</interface>
<interface>
<name>IDisplayColorCalibration</name>
<instance>default</instance>
</interface>
<interface>
<name>IDisplayModes</name>
<instance>default</instance>
</interface>
<interface>
<name>IPictureAdjustment</name>
<instance>default</instance>
</interface>
<interface>
<name>IReadingEnhancement</name>
<instance>default</instance>
</interface>
<interface>
<name>ISunlightEnhancement</name>
<instance>default</instance>
</interface>
</hal> -->
<hal format="hidl">
<name>vendor.lineage.trust</name>
<transport>hwbinder</transport>
<version>1.0</version>
<interface>
<name>IUsbRestrict</name>
<instance>default</instance>
</interface>
</hal>
<hal format="hidl">
<name>vendor.lineage.touch</name>
<transport arch="32+64">passthrough</transport>
<version>1.0</version>
<interface>
<name>IGloveMode</name>
<instance>default</instance>
</interface>
<interface>
<name>IKeyDisabler</name>
<instance>default</instance>
</interface>
<interface>
<name>IStylusMode</name>
<instance>default</instance>
</interface>
<interface>
<name>ITouchscreenGesture</name>
<instance>default</instance>
</interface>
<hal format="hidl" override="true">
<name>vendor.qti.data.factory</name>
<transport>hwbinder</transport>
</hal>
<hal format="hidl">
<name>vendor.qti.gnss</name>
<transport>hwbinder</transport>
<version>1.2</version>
<version>1.0</version>
<interface>
<name>ILocHidlGnss</name>
<instance>gnss_vendor</instance>
</interface>
<fqname>@1.2::ILocHidlGnss/gnss_vendor</fqname>
</hal>
<hal format="hidl">
<name>vendor.qti.gnss</name>
<transport>hwbinder</transport>
<version>2.0</version>
<interface>
<name>ILocHidlGnss</name>
<instance>gnss_vendor</instance>
</interface>
<fqname>@2.0::ILocHidlGnss/gnss_vendor</fqname>
</hal>
<hal format="hidl">
<name>vendor.qti.hardware.alarm</name>
@ -486,21 +372,20 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<instance>default</instance>
</interface>
</hal>
<hal format="hidl">
<name>vendor.qti.hardware.cryptfshw</name>
<hal format="hidl" override="true">
<name>vendor.qti.hardware.data.connection</name>
<transport>hwbinder</transport>
<version>1.0</version>
<interface>
<name>ICryptfsHw</name>
<instance>default</instance>
</interface>
</hal>
<hal format="hidl">
<hal format="hidl" override="true">
<name>vendor.qti.hardware.data.latency</name>
<transport>hwbinder</transport>
</hal>
<hal format="hidl">
<name>vendor.qti.hardware.fm</name>
<transport>hwbinder</transport>
<version>1.0</version>
<interface>
<name>ILinkLatency</name>
<name>IFmHci</name>
<instance>default</instance>
</interface>
</hal>
@ -521,6 +406,7 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<name>IPerf</name>
<instance>default</instance>
</interface>
<fqname>@1.0::IPerf/default</fqname>
</hal>
<hal format="hidl">
<name>vendor.qti.hardware.qdutils_disp</name>
@ -532,91 +418,177 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
</interface>
</hal>
<hal format="hidl">
<name>vendor.qti.hardware.radio.am</name>
<name>vendor.qti.hardware.qteeconnector</name>
<transport>hwbinder</transport>
<version>1.0</version>
<interface>
<name>IQcRilAudio</name>
<instance>slot1</instance>
<instance>slot2</instance>
<name>IAppConnector</name>
<instance>default</instance>
</interface>
<interface>
<name>IGPAppConnector</name>
<instance>default</instance>
</interface>
</hal>
<hal format="hidl">
<name>vendor.qti.hardware.radio.atcmdfwd</name>
<name>vendor.qti.hardware.tui_comm</name>
<transport>hwbinder</transport>
<version>1.0</version>
<interface>
<name>IAtCmdFwd</name>
<instance>AtCmdFwdService</instance>
<name>ITuiComm</name>
<instance>default</instance>
</interface>
</hal>
<hal format="hidl">
<name>vendor.qti.hardware.radio.ims</name>
<name>vendor.qti.hardware.wifi.hostapd</name>
<transport>hwbinder</transport>
<version>1.0</version>
<interface>
<name>IImsRadio</name>
<instance>imsradio0</instance>
<instance>imsradio1</instance>
<name>IHostapdVendor</name>
<instance>default</instance>
</interface>
</hal>
<hal format="hidl">
<name>vendor.qti.hardware.radio.lpa</name>
<name>vendor.qti.hardware.wifi.supplicant</name>
<transport>hwbinder</transport>
<version>1.0</version>
<version>2.0</version>
<interface>
<name>IUimLpa</name>
<instance>UimLpa0</instance>
<name>ISupplicantVendor</name>
<instance>default</instance>
</interface>
</hal>
<hal format="hidl">
<name>vendor.qti.hardware.radio.qcrilhook</name>
<name>vendor.qti.hardware.wigig.netperftuner</name>
<transport>hwbinder</transport>
<version>1.0</version>
<interface>
<name>IQtiOemHook</name>
<instance>oemhook0</instance>
<instance>oemhook1</instance>
<name>INetPerfTuner</name>
<instance>default</instance>
</interface>
</hal>
<hal format="hidl">
<name>vendor.qti.hardware.radio.qtiradio</name>
<name>vendor.qti.hardware.wigig.supptunnel</name>
<transport>hwbinder</transport>
<version>1.0</version>
<interface>
<name>IQtiRadio</name>
<instance>slot1</instance>
<instance>slot2</instance>
<name>ISuppTunnelProvider</name>
<instance>default</instance>
</interface>
</hal>
<hal format="hidl" override="true">
<name>vendor.qti.ims.callinfo</name>
<transport>hwbinder</transport>
</hal>
<hal format="hidl" override="true">
<name>vendor.qti.imsrtpservice</name>
<transport>hwbinder</transport>
</hal>
<hal format="hidl">
<name>vendor.samsung.external.secure_storage</name>
<transport>hwbinder</transport>
<version>2.0</version>
<interface>
<name>ISecureStorage</name>
<instance>default</instance>
</interface>
</hal>
<hal format="hidl">
<name>vendor.qti.hardware.radio.uim</name>
<name>vendor.samsung.hardware.biometrics.fingerprint</name>
<transport>hwbinder</transport>
<version>1.0</version>
<version>2.1</version>
<interface>
<name>IUim</name>
<instance>Uim0</instance>
<instance>Uim1</instance>
<name>ISecBiometricsFingerprint</name>
<instance>default</instance>
</interface>
</hal>
<hal format="hidl">
<name>vendor.qti.hardware.radio.uim_remote_client</name>
<name>vendor.samsung.hardware.gnss</name>
<transport>hwbinder</transport>
<version>1.0</version>
<interface>
<name>IUimRemoteServiceClient</name>
<instance>uimRemoteClient0</instance>
<instance>uimRemoteClient1</instance>
<name>ISecGnss</name>
<instance>default</instance>
</interface>
</hal>
<hal format="hidl">
<name>vendor.qti.hardware.radio.uim_remote_server</name>
<name>vendor.samsung.hardware.health</name>
<transport>hwbinder</transport>
<version>2.0</version>
<interface>
<name>ISehHealth</name>
<instance>sehhealth</instance>
</interface>
</hal>
<hal format="hidl">
<name>vendor.samsung.hardware.miscpower</name>
<transport>hwbinder</transport>
<version>1.0</version>
<interface>
<name>IUimRemoteServiceServer</name>
<instance>uimRemoteServer0</instance>
<instance>uimRemoteServer1</instance>
<name>ISecMiscPower</name>
<instance>miscpower</instance>
</interface>
</hal>
<hal format="hidl">
<name>vendor.samsung.hardware.wifi</name>
<transport>hwbinder</transport>
<version>1.0</version>
<interface>
<name>IWifiExt</name>
<instance>default</instance>
</interface>
</hal>
<hal format="hidl">
<name>vendor.samsung.hardware.wifi.hostapd</name>
<transport>hwbinder</transport>
<version>1.0</version>
<interface>
<name>ISemHostapd</name>
<instance>default</instance>
</interface>
</hal>
<hal format="hidl">
<name>vendor.samsung.hardware.wifi.supplicant</name>
<transport>hwbinder</transport>
<version>1.0</version>
<interface>
<name>ISupplicantExt</name>
<instance>default</instance>
</interface>
</hal>
<hal format="hidl">
<name>vendor.samsung.security.proca</name>
<transport>hwbinder</transport>
<version>1.0</version>
<interface>
<name>IProcaDaemon</name>
<instance>default</instance>
</interface>
</hal>
<hal format="hidl">
<name>vendor.samsung.security.skpm</name>
<transport>hwbinder</transport>
<version>1.0</version>
<interface>
<name>ISkpm</name>
<instance>default</instance>
</interface>
</hal>
<hal format="hidl">
<name>vendor.samsung.security.vaultkeeper_server</name>
<transport>hwbinder</transport>
<version>1.0</version>
<interface>
<name>Ivaultkeeper_server</name>
<instance>default</instance>
</interface>
</hal>
<hal format="hidl">
<name>vendor.samsung.security.wvkprov_server</name>
<transport>hwbinder</transport>
<version>1.0</version>
<interface>
<name>Iwvkprov_server</name>
<instance>default</instance>
</interface>
</hal>
</manifest>