diff --git a/Android.mk b/Android.mk index 55c4d1f..2d364f9 100755 --- a/Android.mk +++ b/Android.mk @@ -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 \ No newline at end of file +endif diff --git a/BoardConfig.mk b/BoardConfig.mk index 43e2401..7669fde 100755 --- a/BoardConfig.mk +++ b/BoardConfig.mk @@ -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 diff --git a/configs/compatibility_matrix.xml b/compatibility_matrix.xml similarity index 54% rename from configs/compatibility_matrix.xml rename to compatibility_matrix.xml index e549136..24b2761 100644 --- a/configs/compatibility_matrix.xml +++ b/compatibility_matrix.xml @@ -1,30 +1,3 @@ - android.frameworks.schedulerservice @@ -82,5 +55,17 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. default - + + netutils-wrapper + + 1.0 + diff --git a/configs/audio/impl/Android.bp b/configs/audio/impl/Android.bp new file mode 100644 index 0000000..29558a2 --- /dev/null +++ b/configs/audio/impl/Android.bp @@ -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", + ] +} diff --git a/configs/audio/impl/Conversions.cpp b/configs/audio/impl/Conversions.cpp new file mode 100644 index 0000000..11872c0 --- /dev/null +++ b/configs/audio/impl/Conversions.cpp @@ -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 + +#include + +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(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 diff --git a/configs/audio/impl/Device.cpp b/configs/audio/impl/Device.cpp new file mode 100644 index 0000000..bec22df --- /dev/null +++ b/configs/audio/impl/Device.cpp @@ -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 +#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 +#include +#include + +#include + +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& 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 Device::initCheck() { + return analyzeStatus("init_check", mDevice->init_check(mDevice)); +} + +Return 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 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 Device::setMicMute(bool mute) { + return analyzeStatus("set_mic_mute", mDevice->set_mic_mute(mDevice, mute)); +} + +Return 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 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 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 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> 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(device.device), + static_cast(flags), halConfig.sample_rate, halConfig.format, + halConfig.channel_mask, deviceAddressToHal(device).c_str()); + int status = + mDevice->open_output_stream(mDevice, ioHandle, static_cast(device.device), + static_cast(flags), &halConfig, + &halStream, deviceAddressToHal(device).c_str()); + ALOGV("open_output_stream status %d stream %p", status, halStream); + sp streamOut; + if (status == OK) { + streamOut = new StreamOut(this, halStream); + } + HidlUtils::audioConfigFromHal(halConfig, suggestedConfig); + return {analyzeStatus("open_output_stream", status, {EINVAL} /*ignore*/), streamOut}; +} + +std::tuple> 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(device.device), + static_cast(flags), halConfig.sample_rate, halConfig.format, + halConfig.channel_mask, deviceAddressToHal(device).c_str(), + static_cast(source)); + int status = mDevice->open_input_stream( + mDevice, ioHandle, static_cast(device.device), &halConfig, &halStream, + static_cast(flags), deviceAddressToHal(device).c_str(), + static_cast(source)); + ALOGV("open_input_stream status %d stream %p", status, halStream); + sp 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 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 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 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 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 Device::supportsAudioPatches() { + return version() >= AUDIO_DEVICE_API_VERSION_3_0; +} + +Return Device::createAudioPatch(const hidl_vec& sources, + const hidl_vec& sinks, + createAudioPatch_cb _hidl_cb) { + Result retval(Result::NOT_SUPPORTED); + AudioPatchHandle patch = 0; + if (version() >= AUDIO_DEVICE_API_VERSION_3_0) { + std::unique_ptr halSources(HidlUtils::audioPortConfigsToHal(sources)); + std::unique_ptr 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(halPatch); + } + } + _hidl_cb(retval, patch); + return Void(); +} + +Return 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(patch))); + } + return Result::NOT_SUPPORTED; +} + +Return 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 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 Device::getHwAvSync() { + int halHwAvSync; + Result retval = getParam(AudioParameter::keyHwAvSync, &halHwAvSync); + return retval == Result::OK ? halHwAvSync : AUDIO_HW_SYNC_INVALID; +} +#elif MAJOR_VERSION >= 4 +Return Device::getHwAvSync(getHwAvSync_cb _hidl_cb) { + int halHwAvSync; + Result retval = getParam(AudioParameter::keyHwAvSync, &halHwAvSync); + _hidl_cb(retval, halHwAvSync); + return Void(); +} +#endif + +Return Device::setScreenState(bool turnedOn) { + return setParam(AudioParameter::keyScreenState, turnedOn); +} + +#if MAJOR_VERSION == 2 +Return Device::getParameters(const hidl_vec& keys, getParameters_cb _hidl_cb) { + getParametersImpl({}, keys, _hidl_cb); + return Void(); +} + +Return Device::setParameters(const hidl_vec& parameters) { + return setParametersImpl({} /* context */, parameters); +} +#elif MAJOR_VERSION >= 4 +Return Device::getParameters(const hidl_vec& context, + const hidl_vec& keys, getParameters_cb _hidl_cb) { + getParametersImpl(context, keys, _hidl_cb); + return Void(); +} +Return Device::setParameters(const hidl_vec& context, + const hidl_vec& parameters) { + return setParametersImpl(context, parameters); +} +#endif + +#if MAJOR_VERSION == 2 +Return Device::debugDump(const hidl_handle& fd) { + return debug(fd, {}); +} +#endif + +Return Device::debug(const hidl_handle& fd, const hidl_vec& /* options */) { + if (fd.getNativeHandle() != nullptr && fd->numFds == 1) { + analyzeStatus("dump", mDevice->dump(mDevice, fd->data[0])); + } + return Void(); +} + +#if MAJOR_VERSION >= 4 +Return 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 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(µphones[i], mic_array[i]); + } + retval = Result::OK; + } + _hidl_cb(retval, microphones); + return Void(); +} + +Return 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 diff --git a/configs/audio/impl/DevicesFactory.cpp b/configs/audio/impl/DevicesFactory.cpp new file mode 100644 index 0000000..729f18c --- /dev/null +++ b/configs/audio/impl/DevicesFactory.cpp @@ -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 + +#include + +namespace android { +namespace hardware { +namespace audio { +namespace CPP_VERSION { +namespace implementation { + +#if MAJOR_VERSION == 2 +Return DevicesFactory::openDevice(IDevicesFactory::Device device, openDevice_cb _hidl_cb) { + switch (device) { + case IDevicesFactory::Device::PRIMARY: + return openDevice(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 DevicesFactory::openDevice(const hidl_string& moduleName, openDevice_cb _hidl_cb) { + if (moduleName == AUDIO_HARDWARE_MODULE_ID_PRIMARY) { + return openDevice(moduleName.c_str(), _hidl_cb); + } + return openDevice(moduleName.c_str(), _hidl_cb); +} +Return DevicesFactory::openPrimaryDevice(openPrimaryDevice_cb _hidl_cb) { + return openDevice(AUDIO_HARDWARE_MODULE_ID_PRIMARY, _hidl_cb); +} +#endif + +Return DevicesFactory::openDevice(const char* moduleName, openDevice_cb _hidl_cb) { + return openDevice(moduleName, _hidl_cb); +} + +template +Return DevicesFactory::openDevice(const char* moduleName, Callback _hidl_cb) { + audio_hw_device_t* halDevice; + Result retval(Result::INVALID_ARGUMENTS); + sp 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 diff --git a/configs/audio/impl/ParametersUtil.cpp b/configs/audio/impl/ParametersUtil.cpp new file mode 100644 index 0000000..d49180b --- /dev/null +++ b/configs/audio/impl/ParametersUtil.cpp @@ -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 +#include + +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 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 params = getParams(context); + return getHalStatusToResult(params->get(halName, *value)); +} + +void ParametersUtil::getParametersImpl( + const hidl_vec& context, const hidl_vec& keys, + std::function& 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 halValues = getParams(halKeys); + Result retval = + (keys.size() == 0 || halValues->size() != 0) ? Result::OK : Result::NOT_SUPPORTED; + hidl_vec 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 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(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& context, + const hidl_vec& 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 diff --git a/configs/audio/impl/PrimaryDevice.cpp b/configs/audio/impl/PrimaryDevice.cpp new file mode 100644 index 0000000..b4fe200 --- /dev/null +++ b/configs/audio/impl/PrimaryDevice.cpp @@ -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 +#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 PrimaryDevice::initCheck() { + return mDevice->initCheck(); +} + +Return PrimaryDevice::setMasterVolume(float volume) { + return mDevice->setMasterVolume(volume); +} + +Return PrimaryDevice::getMasterVolume(getMasterVolume_cb _hidl_cb) { + return mDevice->getMasterVolume(_hidl_cb); +} + +Return PrimaryDevice::setMicMute(bool mute) { + return mDevice->setMicMute(mute); +} + +Return PrimaryDevice::getMicMute(getMicMute_cb _hidl_cb) { + return mDevice->getMicMute(_hidl_cb); +} + +Return PrimaryDevice::setMasterMute(bool mute) { + return mDevice->setMasterMute(mute); +} + +Return PrimaryDevice::getMasterMute(getMasterMute_cb _hidl_cb) { + return mDevice->getMasterMute(_hidl_cb); +} + +Return PrimaryDevice::getInputBufferSize(const AudioConfig& config, + getInputBufferSize_cb _hidl_cb) { + return mDevice->getInputBufferSize(config, _hidl_cb); +} + +#if MAJOR_VERSION == 2 +Return 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 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 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 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 PrimaryDevice::supportsAudioPatches() { + return mDevice->supportsAudioPatches(); +} + +Return PrimaryDevice::createAudioPatch(const hidl_vec& sources, + const hidl_vec& sinks, + createAudioPatch_cb _hidl_cb) { + return mDevice->createAudioPatch(sources, sinks, _hidl_cb); +} + +Return PrimaryDevice::releaseAudioPatch(int32_t patch) { + return mDevice->releaseAudioPatch(patch); +} + +Return PrimaryDevice::getAudioPort(const AudioPort& port, getAudioPort_cb _hidl_cb) { + return mDevice->getAudioPort(port, _hidl_cb); +} + +Return PrimaryDevice::setAudioPortConfig(const AudioPortConfig& config) { + return mDevice->setAudioPortConfig(config); +} + +Return PrimaryDevice::setScreenState(bool turnedOn) { + return mDevice->setScreenState(turnedOn); +} + +#if MAJOR_VERSION == 2 +Return PrimaryDevice::getHwAvSync() { + return mDevice->getHwAvSync(); +} + +Return PrimaryDevice::getParameters(const hidl_vec& keys, + getParameters_cb _hidl_cb) { + return mDevice->getParameters(keys, _hidl_cb); +} + +Return PrimaryDevice::setParameters(const hidl_vec& parameters) { + return mDevice->setParameters(parameters); +} + +Return PrimaryDevice::debugDump(const hidl_handle& fd) { + return mDevice->debugDump(fd); +} +#elif MAJOR_VERSION >= 4 +Return PrimaryDevice::getHwAvSync(getHwAvSync_cb _hidl_cb) { + return mDevice->getHwAvSync(_hidl_cb); +} +Return PrimaryDevice::getParameters(const hidl_vec& context, + const hidl_vec& keys, + getParameters_cb _hidl_cb) { + return mDevice->getParameters(context, keys, _hidl_cb); +} +Return PrimaryDevice::setParameters(const hidl_vec& context, + const hidl_vec& parameters) { + return mDevice->setParameters(context, parameters); +} +Return PrimaryDevice::getMicrophones(getMicrophones_cb _hidl_cb) { + return mDevice->getMicrophones(_hidl_cb); +} +Return PrimaryDevice::setConnectedState(const DeviceAddress& address, bool connected) { + return mDevice->setConnectedState(address, connected); +} +#endif + +// Methods from ::android::hardware::audio::CPP_VERSION::IPrimaryDevice follow. +Return 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 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(mode))); +} + +Return PrimaryDevice::getBtScoNrecEnabled(getBtScoNrecEnabled_cb _hidl_cb) { + bool enabled; + Result retval = mDevice->getParam(AudioParameter::keyBtNrec, &enabled); + _hidl_cb(retval, enabled); + return Void(); +} + +Return PrimaryDevice::setBtScoNrecEnabled(bool enabled) { + return mDevice->setParam(AudioParameter::keyBtNrec, enabled); +} + +Return 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 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 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 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 PrimaryDevice::getHacEnabled(getHacEnabled_cb _hidl_cb) { + bool enabled; + Result retval = mDevice->getParam(AUDIO_PARAMETER_KEY_HAC, &enabled); + _hidl_cb(retval, enabled); + return Void(); +} + +Return PrimaryDevice::setHacEnabled(bool enabled) { + return mDevice->setParam(AUDIO_PARAMETER_KEY_HAC, enabled); +} + +#if MAJOR_VERSION >= 4 +Return PrimaryDevice::setBtScoHeadsetDebugName(const hidl_string& name) { + return mDevice->setParam(AUDIO_PARAMETER_KEY_BT_SCO_HEADSET_NAME, name.c_str()); +} +Return 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 PrimaryDevice::setBtHfpEnabled(bool enabled) { + return mDevice->setParam(AUDIO_PARAMETER_KEY_HFP_ENABLE, enabled); +} +Return PrimaryDevice::setBtHfpSampleRate(uint32_t sampleRateHz) { + return mDevice->setParam(AUDIO_PARAMETER_KEY_HFP_SET_SAMPLING_RATE, int(sampleRateHz)); +} +Return 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(std::round(volume * 15))); +} +Return PrimaryDevice::updateRotation(IPrimaryDevice::Rotation rotation) { + // legacy API expects the rotation in degree + return mDevice->setParam(AUDIO_PARAMETER_KEY_ROTATION, int(rotation) * 90); +} +#endif + +Return PrimaryDevice::debug(const hidl_handle& fd, const hidl_vec& options) { + return mDevice->debug(fd, options); +} + +} // namespace implementation +} // namespace CPP_VERSION +} // namespace audio +} // namespace hardware +} // namespace android diff --git a/configs/audio/impl/Stream.cpp b/configs/audio/impl/Stream.cpp new file mode 100644 index 0000000..b995657 --- /dev/null +++ b/configs/audio/impl/Stream.cpp @@ -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 + +#include +#include +#include +#include +#include +#include + +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& 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 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 Stream::getFrameCount() { + int halFrameCount; + Result retval = getParam(AudioParameter::keyFrameCount, &halFrameCount); + return retval == Result::OK ? halFrameCount : 0; +} + +Return Stream::getBufferSize() { + return mStream->get_buffer_size(mStream); +} + +Return Stream::getSampleRate() { + return mStream->get_sample_rate(mStream); +} + +#if MAJOR_VERSION == 2 +Return Stream::getSupportedSampleRates(getSupportedSampleRates_cb _hidl_cb) { + return getSupportedSampleRates(getFormat(), _hidl_cb); +} +Return Stream::getSupportedChannelMasks(getSupportedChannelMasks_cb _hidl_cb) { + return getSupportedChannelMasks(getFormat(), _hidl_cb); +} +#endif + +Return 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 sampleRates; + SortedVector 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 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 channelMasks; + SortedVector 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 Stream::setSampleRate(uint32_t sampleRateHz) { + return setParam(AudioParameter::keySamplingRate, static_cast(sampleRateHz)); +} + +Return Stream::getChannelMask() { + return AudioChannelBitfield(mStream->get_channels(mStream)); +} + +Return Stream::setChannelMask(AudioChannelBitfield mask) { + return setParam(AudioParameter::keyChannels, static_cast(mask)); +} + +Return Stream::getFormat() { + return AudioFormat(mStream->get_format(mStream)); +} + +Return Stream::getSupportedFormats(getSupportedFormats_cb _hidl_cb) { + String8 halListValue; + Result result = getParam(AudioParameter::keyStreamSupportedFormats, &halListValue); + hidl_vec formats; + Vector 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 Stream::setFormat(AudioFormat format) { + return setParam(AudioParameter::keyFormat, static_cast(format)); +} + +Return 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 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 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 Stream::standby() { + return analyzeStatus("standby", mStream->standby(mStream)); +} + +Return Stream::setHwAvSync(uint32_t hwAvSync) { + return setParam(AudioParameter::keyStreamHwAvSync, static_cast(hwAvSync)); +} + +#if MAJOR_VERSION == 2 +Return Stream::getDevice() { + int device = 0; + Result retval = getParam(AudioParameter::keyRouting, &device); + return retval == Result::OK ? static_cast(device) : AudioDevice::NONE; +} + +Return Stream::setDevice(const DeviceAddress& address) { + return setParam(AudioParameter::keyRouting, address); +} + +Return Stream::getParameters(const hidl_vec& keys, getParameters_cb _hidl_cb) { + getParametersImpl({} /* context */, keys, _hidl_cb); + return Void(); +} + +Return Stream::setParameters(const hidl_vec& parameters) { + return setParametersImpl({} /* context */, parameters); +} + +Return Stream::setConnectedState(const DeviceAddress& address, bool connected) { + return setParam( + connected ? AudioParameter::keyStreamConnect : AudioParameter::keyStreamDisconnect, + address); +} +#elif MAJOR_VERSION >= 4 +Return Stream::getDevices(getDevices_cb _hidl_cb) { + int device = 0; + Result retval = getParam(AudioParameter::keyRouting, &device); + hidl_vec devices; + if (retval == Result::OK) { + devices.resize(1); + devices[0].device = static_cast(device); + } + _hidl_cb(retval, devices); + return Void(); +} + +Return Stream::setDevices(const hidl_vec& 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 Stream::getParameters(const hidl_vec& context, + const hidl_vec& keys, getParameters_cb _hidl_cb) { + getParametersImpl(context, keys, _hidl_cb); + return Void(); +} + +Return Stream::setParameters(const hidl_vec& context, + const hidl_vec& parameters) { + return setParametersImpl(context, parameters); +} +#endif + +Return Stream::start() { + return Result::NOT_SUPPORTED; +} + +Return Stream::stop() { + return Result::NOT_SUPPORTED; +} + +Return Stream::createMmapBuffer(int32_t minSizeFrames __unused, + createMmapBuffer_cb _hidl_cb) { + Result retval(Result::NOT_SUPPORTED); + MmapBufferInfo info; + _hidl_cb(retval, info); + return Void(); +} + +Return Stream::getMmapPosition(getMmapPosition_cb _hidl_cb) { + Result retval(Result::NOT_SUPPORTED); + MmapPosition position; + _hidl_cb(retval, position); + return Void(); +} + +Return Stream::close() { + return Result::NOT_SUPPORTED; +} + +Return Stream::debug(const hidl_handle& fd, const hidl_vec& /* options */) { + if (fd.getNativeHandle() != nullptr && fd->numFds == 1) { + analyzeStatus("dump", mStream->dump(mStream, fd->data[0])); + } + return Void(); +} + +#if MAJOR_VERSION == 2 +Return Stream::debugDump(const hidl_handle& fd) { + return debug(fd, {} /* options */); +} +#endif + +} // namespace implementation +} // namespace CPP_VERSION +} // namespace audio +} // namespace hardware +} // namespace android diff --git a/configs/audio/impl/StreamIn.cpp b/configs/audio/impl/StreamIn.cpp new file mode 100644 index 0000000..d316f83 --- /dev/null +++ b/configs/audio/impl/StreamIn.cpp @@ -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 +#include +#include +#include +#include + +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* 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* mStop; + audio_stream_in_t* mStream; + StreamIn::CommandMQ* mCommandMQ; + StreamIn::DataMQ* mDataMQ; + StreamIn::StatusMQ* mStatusMQ; + EventFlag* mEfGroup; + std::unique_ptr 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(MessageQueueFlagBits::NOT_FULL), &efState); + if (!(efState & static_cast(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(MessageQueueFlagBits::NOT_EMPTY)); + } + + return false; +} + +} // namespace + +StreamIn::StreamIn(const sp& device, audio_stream_in_t* stream) + : mIsClosed(false), + mDevice(device), + mStream(stream), + mStreamCommon(new Stream(&stream->common)), + mStreamMmap(new StreamMmap(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 StreamIn::getFrameSize() { + return audio_stream_in_frame_size(mStream); +} + +Return StreamIn::getFrameCount() { + return mStreamCommon->getFrameCount(); +} + +Return StreamIn::getBufferSize() { + return mStreamCommon->getBufferSize(); +} + +Return StreamIn::getSampleRate() { + return mStreamCommon->getSampleRate(); +} + +#if MAJOR_VERSION == 2 +Return StreamIn::getSupportedChannelMasks(getSupportedChannelMasks_cb _hidl_cb) { + return mStreamCommon->getSupportedChannelMasks(_hidl_cb); +} +Return StreamIn::getSupportedSampleRates(getSupportedSampleRates_cb _hidl_cb) { + return mStreamCommon->getSupportedSampleRates(_hidl_cb); +} +#endif + +Return StreamIn::getSupportedChannelMasks(AudioFormat format, + getSupportedChannelMasks_cb _hidl_cb) { + return mStreamCommon->getSupportedChannelMasks(format, _hidl_cb); +} +Return StreamIn::getSupportedSampleRates(AudioFormat format, + getSupportedSampleRates_cb _hidl_cb) { + return mStreamCommon->getSupportedSampleRates(format, _hidl_cb); +} + +Return StreamIn::setSampleRate(uint32_t sampleRateHz) { + return mStreamCommon->setSampleRate(sampleRateHz); +} + +Return StreamIn::getChannelMask() { + return mStreamCommon->getChannelMask(); +} + +Return StreamIn::setChannelMask(AudioChannelBitfield mask) { + return mStreamCommon->setChannelMask(mask); +} + +Return StreamIn::getFormat() { + return mStreamCommon->getFormat(); +} + +Return StreamIn::getSupportedFormats(getSupportedFormats_cb _hidl_cb) { + return mStreamCommon->getSupportedFormats(_hidl_cb); +} + +Return StreamIn::setFormat(AudioFormat format) { + return mStreamCommon->setFormat(format); +} + +Return StreamIn::getAudioProperties(getAudioProperties_cb _hidl_cb) { + return mStreamCommon->getAudioProperties(_hidl_cb); +} + +Return StreamIn::addEffect(uint64_t effectId) { + return mStreamCommon->addEffect(effectId); +} + +Return StreamIn::removeEffect(uint64_t effectId) { + return mStreamCommon->removeEffect(effectId); +} + +Return StreamIn::standby() { + return mStreamCommon->standby(); +} + +Return StreamIn::setHwAvSync(uint32_t hwAvSync) { + return mStreamCommon->setHwAvSync(hwAvSync); +} + +#if MAJOR_VERSION == 2 +Return StreamIn::setConnectedState(const DeviceAddress& address, bool connected) { + return mStreamCommon->setConnectedState(address, connected); +} + +Return StreamIn::getDevice() { + return mStreamCommon->getDevice(); +} + +Return StreamIn::setDevice(const DeviceAddress& address) { + return mStreamCommon->setDevice(address); +} + +Return StreamIn::getParameters(const hidl_vec& keys, getParameters_cb _hidl_cb) { + return mStreamCommon->getParameters(keys, _hidl_cb); +} + +Return StreamIn::setParameters(const hidl_vec& parameters) { + return mStreamCommon->setParameters(parameters); +} + +Return StreamIn::debugDump(const hidl_handle& fd) { + return mStreamCommon->debugDump(fd); +} +#elif MAJOR_VERSION >= 4 +Return StreamIn::getDevices(getDevices_cb _hidl_cb) { + return mStreamCommon->getDevices(_hidl_cb); +} + +Return StreamIn::setDevices(const hidl_vec& devices) { + return mStreamCommon->setDevices(devices); +} +Return StreamIn::getParameters(const hidl_vec& context, + const hidl_vec& keys, getParameters_cb _hidl_cb) { + return mStreamCommon->getParameters(context, keys, _hidl_cb); +} + +Return StreamIn::setParameters(const hidl_vec& context, + const hidl_vec& parameters) { + return mStreamCommon->setParameters(context, parameters); +} +#endif + +Return StreamIn::start() { + return mStreamMmap->start(); +} + +Return StreamIn::stop() { + return mStreamMmap->stop(); +} + +Return StreamIn::createMmapBuffer(int32_t minSizeFrames, createMmapBuffer_cb _hidl_cb) { + return mStreamMmap->createMmapBuffer(minSizeFrames, audio_stream_in_frame_size(mStream), + _hidl_cb); +} + +Return StreamIn::getMmapPosition(getMmapPosition_cb _hidl_cb) { + return mStreamMmap->getMmapPosition(_hidl_cb); +} + +Return 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(MessageQueueFlagBits::NOT_FULL)); + } + return Result::OK; +} + +// Methods from ::android::hardware::audio::CPP_VERSION::IStreamIn follow. +Return 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 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 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 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 tempDataMQ(new DataMQ(frameSize * framesCount, true /* EventFlag */)); + + std::unique_ptr 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 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(&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 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 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 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 StreamIn::debug(const hidl_handle& fd, const hidl_vec& options) { + return mStreamCommon->debug(fd, options); +} + +#if MAJOR_VERSION >= 4 +Return StreamIn::updateSinkMetadata(const SinkMetadata& sinkMetadata) { + if (mStream->update_sink_metadata == nullptr) { + return Void(); // not supported by the HAL + } + std::vector halTracks; + halTracks.reserve(sinkMetadata.tracks.size()); + for (auto& metadata : sinkMetadata.tracks) { + record_track_metadata halTrackMetadata = { + .source = static_cast(metadata.source), .gain = metadata.gain}; +#if MAJOR_VERSION >= 5 + if (metadata.destination.getDiscriminator() == + RecordTrackMetadata::Destination::hidl_discriminator::device) { + halTrackMetadata.dest_device = + static_cast(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 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 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(µphones[i], mic_array[i]); + } + retval = Result::OK; + } + + _hidl_cb(retval, microphones); + return Void(); +} +#endif + +#if MAJOR_VERSION >= 5 +Return 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(direction))); +} + +Return 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 diff --git a/configs/audio/impl/StreamOut.cpp b/configs/audio/impl/StreamOut.cpp new file mode 100644 index 0000000..82cc408 --- /dev/null +++ b/configs/audio/impl/StreamOut.cpp @@ -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 + +#include +#include +#include + +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* 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* mStop; + audio_stream_out_t* mStream; + StreamOut::CommandMQ* mCommandMQ; + StreamOut::DataMQ* mDataMQ; + StreamOut::StatusMQ* mStatusMQ; + EventFlag* mEfGroup; + std::unique_ptr 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(MessageQueueFlagBits::NOT_EMPTY), &efState); + if (!(efState & static_cast(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(MessageQueueFlagBits::NOT_FULL)); + } + + return false; +} + +} // namespace + +StreamOut::StreamOut(const sp& device, audio_stream_out_t* stream) + : mIsClosed(false), + mDevice(device), + mStream(stream), + mStreamCommon(new Stream(&stream->common)), + mStreamMmap(new StreamMmap(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 StreamOut::getFrameSize() { + return audio_stream_out_frame_size(mStream); +} + +Return StreamOut::getFrameCount() { + return mStreamCommon->getFrameCount(); +} + +Return StreamOut::getBufferSize() { + return mStreamCommon->getBufferSize(); +} + +Return StreamOut::getSampleRate() { + return mStreamCommon->getSampleRate(); +} + +#if MAJOR_VERSION == 2 +Return StreamOut::getSupportedChannelMasks(getSupportedChannelMasks_cb _hidl_cb) { + return mStreamCommon->getSupportedChannelMasks(_hidl_cb); +} +Return StreamOut::getSupportedSampleRates(getSupportedSampleRates_cb _hidl_cb) { + return mStreamCommon->getSupportedSampleRates(_hidl_cb); +} +#endif + +Return StreamOut::getSupportedChannelMasks(AudioFormat format, + getSupportedChannelMasks_cb _hidl_cb) { + return mStreamCommon->getSupportedChannelMasks(format, _hidl_cb); +} +Return StreamOut::getSupportedSampleRates(AudioFormat format, + getSupportedSampleRates_cb _hidl_cb) { + return mStreamCommon->getSupportedSampleRates(format, _hidl_cb); +} + +Return StreamOut::setSampleRate(uint32_t sampleRateHz) { + return mStreamCommon->setSampleRate(sampleRateHz); +} + +Return StreamOut::getChannelMask() { + return mStreamCommon->getChannelMask(); +} + +Return StreamOut::setChannelMask(AudioChannelBitfield mask) { + return mStreamCommon->setChannelMask(mask); +} + +Return StreamOut::getFormat() { + return mStreamCommon->getFormat(); +} + +Return StreamOut::getSupportedFormats(getSupportedFormats_cb _hidl_cb) { + return mStreamCommon->getSupportedFormats(_hidl_cb); +} + +Return StreamOut::setFormat(AudioFormat format) { + return mStreamCommon->setFormat(format); +} + +Return StreamOut::getAudioProperties(getAudioProperties_cb _hidl_cb) { + return mStreamCommon->getAudioProperties(_hidl_cb); +} + +Return StreamOut::addEffect(uint64_t effectId) { + return mStreamCommon->addEffect(effectId); +} + +Return StreamOut::removeEffect(uint64_t effectId) { + return mStreamCommon->removeEffect(effectId); +} + +Return StreamOut::standby() { + return mStreamCommon->standby(); +} + +Return StreamOut::setHwAvSync(uint32_t hwAvSync) { + return mStreamCommon->setHwAvSync(hwAvSync); +} + +#if MAJOR_VERSION == 2 +Return StreamOut::setConnectedState(const DeviceAddress& address, bool connected) { + return mStreamCommon->setConnectedState(address, connected); +} + +Return StreamOut::getDevice() { + return mStreamCommon->getDevice(); +} + +Return StreamOut::setDevice(const DeviceAddress& address) { + return mStreamCommon->setDevice(address); +} + +Return StreamOut::getParameters(const hidl_vec& keys, + getParameters_cb _hidl_cb) { + return mStreamCommon->getParameters(keys, _hidl_cb); +} + +Return StreamOut::setParameters(const hidl_vec& parameters) { + return mStreamCommon->setParameters(parameters); +} + +Return StreamOut::debugDump(const hidl_handle& fd) { + return mStreamCommon->debugDump(fd); +} +#elif MAJOR_VERSION >= 4 +Return StreamOut::getDevices(getDevices_cb _hidl_cb) { + return mStreamCommon->getDevices(_hidl_cb); +} + +Return StreamOut::setDevices(const hidl_vec& devices) { + return mStreamCommon->setDevices(devices); +} +Return StreamOut::getParameters(const hidl_vec& context, + const hidl_vec& keys, + getParameters_cb _hidl_cb) { + return mStreamCommon->getParameters(context, keys, _hidl_cb); +} + +Return StreamOut::setParameters(const hidl_vec& context, + const hidl_vec& parameters) { + return mStreamCommon->setParameters(context, parameters); +} +#endif + +Return 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(MessageQueueFlagBits::NOT_EMPTY)); + } + return Result::OK; +} + +// Methods from ::android::hardware::audio::CPP_VERSION::IStreamOut follow. +Return StreamOut::getLatency() { + return mStream->get_latency(mStream); +} + +Return 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 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 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 tempDataMQ(new DataMQ(frameSize * framesCount, true /* EventFlag */)); + + std::unique_ptr 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 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(&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 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 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, ×tampUs)); + } + _hidl_cb(retval, timestampUs); + return Void(); +} + +Return StreamOut::setCallback(const sp& 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 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 + // 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(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 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 StreamOut::supportsPauseAndResume(supportsPauseAndResume_cb _hidl_cb) { + _hidl_cb(mStream->pause != NULL, mStream->resume != NULL); + return Void(); +} + +Return StreamOut::pause() { + return mStream->pause != NULL ? Stream::analyzeStatus("pause", mStream->pause(mStream)) + : Result::NOT_SUPPORTED; +} + +Return StreamOut::resume() { + return mStream->resume != NULL ? Stream::analyzeStatus("resume", mStream->resume(mStream)) + : Result::NOT_SUPPORTED; +} + +Return StreamOut::supportsDrain() { + return mStream->drain != NULL; +} + +Return StreamOut::drain(AudioDrain type) { + return mStream->drain != NULL + ? Stream::analyzeStatus( + "drain", mStream->drain(mStream, static_cast(type))) + : Result::NOT_SUPPORTED; +} + +Return 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 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 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 StreamOut::start() { + return mStreamMmap->start(); +} + +Return StreamOut::stop() { + return mStreamMmap->stop(); +} + +Return StreamOut::createMmapBuffer(int32_t minSizeFrames, createMmapBuffer_cb _hidl_cb) { + return mStreamMmap->createMmapBuffer(minSizeFrames, audio_stream_out_frame_size(mStream), + _hidl_cb); +} + +Return StreamOut::getMmapPosition(getMmapPosition_cb _hidl_cb) { + return mStreamMmap->getMmapPosition(_hidl_cb); +} + +Return StreamOut::debug(const hidl_handle& fd, const hidl_vec& options) { + return mStreamCommon->debug(fd, options); +} + +#if MAJOR_VERSION >= 4 +Return StreamOut::updateSourceMetadata(const SourceMetadata& sourceMetadata) { + if (mStream->update_source_metadata == nullptr) { + return Void(); // not supported by the HAL + } + std::vector halTracks; + halTracks.reserve(sourceMetadata.tracks.size()); + for (auto& metadata : sourceMetadata.tracks) { + halTracks.push_back({ + .usage = static_cast(metadata.usage), + .content_type = static_cast(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 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 diff --git a/configs/audio/impl/include/core/default/Conversions.h b/configs/audio/impl/include/core/default/Conversions.h new file mode 100644 index 0000000..cb7914f --- /dev/null +++ b/configs/audio/impl/include/core/default/Conversions.h @@ -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 + +#include + +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_ diff --git a/configs/audio/impl/include/core/default/Device.h b/configs/audio/impl/include/core/default/Device.h new file mode 100644 index 0000000..66d86f5 --- /dev/null +++ b/configs/audio/impl/include/core/default/Device.h @@ -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 + +#include +#include + +#include + +#include + +#include + +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 initCheck() override; + Return setMasterVolume(float volume) override; + Return getMasterVolume(getMasterVolume_cb _hidl_cb) override; + Return setMicMute(bool mute) override; + Return getMicMute(getMicMute_cb _hidl_cb) override; + Return setMasterMute(bool mute) override; + Return getMasterMute(getMasterMute_cb _hidl_cb) override; + Return getInputBufferSize(const AudioConfig& config, + getInputBufferSize_cb _hidl_cb) override; + + std::tuple> openOutputStreamImpl(int32_t ioHandle, + const DeviceAddress& device, + const AudioConfig& config, + AudioOutputFlagBitfield flags, + AudioConfig* suggestedConfig); + std::tuple> openInputStreamImpl( + int32_t ioHandle, const DeviceAddress& device, const AudioConfig& config, + AudioInputFlagBitfield flags, AudioSource source, AudioConfig* suggestedConfig); +#if MAJOR_VERSION == 2 + Return openOutputStream(int32_t ioHandle, const DeviceAddress& device, + const AudioConfig& config, AudioOutputFlagBitfield flags, + openOutputStream_cb _hidl_cb) override; + Return openInputStream(int32_t ioHandle, const DeviceAddress& device, + const AudioConfig& config, AudioInputFlagBitfield flags, + AudioSource source, openInputStream_cb _hidl_cb) override; +#elif MAJOR_VERSION >= 4 + Return openOutputStream(int32_t ioHandle, const DeviceAddress& device, + const AudioConfig& config, AudioOutputFlagBitfield flags, + const SourceMetadata& sourceMetadata, + openOutputStream_cb _hidl_cb) override; + Return openInputStream(int32_t ioHandle, const DeviceAddress& device, + const AudioConfig& config, AudioInputFlagBitfield flags, + const SinkMetadata& sinkMetadata, + openInputStream_cb _hidl_cb) override; +#endif + + Return supportsAudioPatches() override; + Return createAudioPatch(const hidl_vec& sources, + const hidl_vec& sinks, + createAudioPatch_cb _hidl_cb) override; + Return releaseAudioPatch(int32_t patch) override; + Return getAudioPort(const AudioPort& port, getAudioPort_cb _hidl_cb) override; + Return setAudioPortConfig(const AudioPortConfig& config) override; + + Return setScreenState(bool turnedOn) override; + +#if MAJOR_VERSION == 2 + Return getHwAvSync() override; + Return getParameters(const hidl_vec& keys, + getParameters_cb _hidl_cb) override; + Return setParameters(const hidl_vec& parameters) override; + Return debugDump(const hidl_handle& fd) override; +#elif MAJOR_VERSION >= 4 + Return getHwAvSync(getHwAvSync_cb _hidl_cb) override; + Return getParameters(const hidl_vec& context, + const hidl_vec& keys, + getParameters_cb _hidl_cb) override; + Return setParameters(const hidl_vec& context, + const hidl_vec& parameters) override; + Return getMicrophones(getMicrophones_cb _hidl_cb) override; + Return setConnectedState(const DeviceAddress& address, bool connected) override; +#endif + + Return debug(const hidl_handle& fd, const hidl_vec& options) override; + + // Utility methods for extending interfaces. + Result analyzeStatus(const char* funcName, int status, + const std::vector& 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 diff --git a/configs/audio/impl/include/core/default/DevicesFactory.h b/configs/audio/impl/include/core/default/DevicesFactory.h new file mode 100644 index 0000000..9f93a38 --- /dev/null +++ b/configs/audio/impl/include/core/default/DevicesFactory.h @@ -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 + +#include + +#include +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 openDevice(IDevicesFactory::Device device, openDevice_cb _hidl_cb) override; +#elif MAJOR_VERSION >= 4 + Return openDevice(const hidl_string& device, openDevice_cb _hidl_cb) override; + Return openPrimaryDevice(openPrimaryDevice_cb _hidl_cb) override; +#endif + + private: + template + Return openDevice(const char* moduleName, Callback _hidl_cb); + Return 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 diff --git a/configs/audio/impl/include/core/default/ParametersUtil.h b/configs/audio/impl/include/core/default/ParametersUtil.h new file mode 100644 index 0000000..45d9b21 --- /dev/null +++ b/configs/audio/impl/include/core/default/ParametersUtil.h @@ -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 +#include + +#include +#include + +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& context, const hidl_vec& keys, + std::function& parameters)> cb); + std::unique_ptr 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& context, + const hidl_vec& 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_ diff --git a/configs/audio/impl/include/core/default/PrimaryDevice.h b/configs/audio/impl/include/core/default/PrimaryDevice.h new file mode 100644 index 0000000..9d69cb0 --- /dev/null +++ b/configs/audio/impl/include/core/default/PrimaryDevice.h @@ -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 + +#include + +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 initCheck() override; + Return setMasterVolume(float volume) override; + Return getMasterVolume(getMasterVolume_cb _hidl_cb) override; + Return setMicMute(bool mute) override; + Return getMicMute(getMicMute_cb _hidl_cb) override; + Return setMasterMute(bool mute) override; + Return getMasterMute(getMasterMute_cb _hidl_cb) override; + Return getInputBufferSize(const AudioConfig& config, + getInputBufferSize_cb _hidl_cb) override; + + Return 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 openInputStream(int32_t ioHandle, const DeviceAddress& device, + const AudioConfig& config, AudioInputFlagBitfield flags, + AudioSource source, openInputStream_cb _hidl_cb); +#if MAJOR_VERSION >= 4 + Return openInputStream(int32_t ioHandle, const DeviceAddress& device, + const AudioConfig& config, AudioInputFlagBitfield flags, + const SinkMetadata& sinkMetadata, + openInputStream_cb _hidl_cb) override; +#endif + + Return supportsAudioPatches() override; + Return createAudioPatch(const hidl_vec& sources, + const hidl_vec& sinks, + createAudioPatch_cb _hidl_cb) override; + Return releaseAudioPatch(int32_t patch) override; + Return getAudioPort(const AudioPort& port, getAudioPort_cb _hidl_cb) override; + Return setAudioPortConfig(const AudioPortConfig& config) override; + + Return setScreenState(bool turnedOn) override; + +#if MAJOR_VERSION == 2 + Return getHwAvSync() override; + Return getParameters(const hidl_vec& keys, + getParameters_cb _hidl_cb) override; + Return setParameters(const hidl_vec& parameters) override; + Return debugDump(const hidl_handle& fd) override; +#elif MAJOR_VERSION >= 4 + Return getHwAvSync(getHwAvSync_cb _hidl_cb) override; + Return getParameters(const hidl_vec& context, + const hidl_vec& keys, + getParameters_cb _hidl_cb) override; + Return setParameters(const hidl_vec& context, + const hidl_vec& parameters) override; + Return getMicrophones(getMicrophones_cb _hidl_cb) override; + Return setConnectedState(const DeviceAddress& address, bool connected) override; +#endif + + Return debug(const hidl_handle& fd, const hidl_vec& options) override; + + // Methods from ::android::hardware::audio::CPP_VERSION::IPrimaryDevice follow. + Return setVoiceVolume(float volume) override; + Return setMode(AudioMode mode) override; + Return getBtScoNrecEnabled(getBtScoNrecEnabled_cb _hidl_cb) override; + Return setBtScoNrecEnabled(bool enabled) override; + Return getBtScoWidebandEnabled(getBtScoWidebandEnabled_cb _hidl_cb) override; + Return setBtScoWidebandEnabled(bool enabled) override; + Return getTtyMode(getTtyMode_cb _hidl_cb) override; + Return setTtyMode(IPrimaryDevice::TtyMode mode) override; + Return getHacEnabled(getHacEnabled_cb _hidl_cb) override; + Return setHacEnabled(bool enabled) override; + +#if MAJOR_VERSION >= 4 + Return setBtScoHeadsetDebugName(const hidl_string& name) override; + Return getBtHfpEnabled(getBtHfpEnabled_cb _hidl_cb) override; + Return setBtHfpEnabled(bool enabled) override; + Return setBtHfpSampleRate(uint32_t sampleRateHz) override; + Return setBtHfpVolume(float volume) override; + Return updateRotation(IPrimaryDevice::Rotation rotation) override; +#endif + + private: + sp mDevice; + + virtual ~PrimaryDevice(); +}; + +} // namespace implementation +} // namespace CPP_VERSION +} // namespace audio +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_AUDIO_PRIMARYDEVICE_H diff --git a/configs/audio/impl/include/core/default/Stream.h b/configs/audio/impl/include/core/default/Stream.h new file mode 100644 index 0000000..91df0c7 --- /dev/null +++ b/configs/audio/impl/include/core/default/Stream.h @@ -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 + +#include +#include + +#include + +#include + +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 getFrameSize() override; + Return getFrameCount() override; + Return getBufferSize() override; + Return getSampleRate() override; +#if MAJOR_VERSION == 2 + Return getSupportedSampleRates(getSupportedSampleRates_cb _hidl_cb) override; + Return getSupportedChannelMasks(getSupportedChannelMasks_cb _hidl_cb) override; +#endif + Return getSupportedSampleRates(AudioFormat format, getSupportedSampleRates_cb _hidl_cb); + Return getSupportedChannelMasks(AudioFormat format, getSupportedChannelMasks_cb _hidl_cb); + Return setSampleRate(uint32_t sampleRateHz) override; + Return getChannelMask() override; + Return setChannelMask(AudioChannelBitfield mask) override; + Return getFormat() override; + Return getSupportedFormats(getSupportedFormats_cb _hidl_cb) override; + Return setFormat(AudioFormat format) override; + Return getAudioProperties(getAudioProperties_cb _hidl_cb) override; + Return addEffect(uint64_t effectId) override; + Return removeEffect(uint64_t effectId) override; + Return standby() override; +#if MAJOR_VERSION == 2 + Return getDevice() override; + Return setDevice(const DeviceAddress& address) override; + Return getParameters(const hidl_vec& keys, + getParameters_cb _hidl_cb) override; + Return setParameters(const hidl_vec& parameters) override; + Return setConnectedState(const DeviceAddress& address, bool connected) override; +#elif MAJOR_VERSION >= 4 + Return getDevices(getDevices_cb _hidl_cb) override; + Return setDevices(const hidl_vec& devices) override; + Return getParameters(const hidl_vec& context, + const hidl_vec& keys, + getParameters_cb _hidl_cb) override; + Return setParameters(const hidl_vec& context, + const hidl_vec& parameters) override; +#endif + Return setHwAvSync(uint32_t hwAvSync) override; + Return start() override; + Return stop() override; + Return createMmapBuffer(int32_t minSizeFrames, createMmapBuffer_cb _hidl_cb) override; + Return getMmapPosition(getMmapPosition_cb _hidl_cb) override; + Return close() override; + + Return debug(const hidl_handle& fd, const hidl_vec& options) override; +#if MAJOR_VERSION == 2 + Return 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& ignoreErrors); + + private: + audio_stream_t* mStream; + + virtual ~Stream(); + + // Methods from ParametersUtil. + char* halGetParameters(const char* keys) override; + int halSetParameters(const char* keysAndValues) override; +}; + +template +struct StreamMmap : public RefBase { + explicit StreamMmap(T* stream) : mStream(stream) {} + + Return start(); + Return stop(); + Return createMmapBuffer(int32_t minSizeFrames, size_t frameSize, + IStream::createMmapBuffer_cb _hidl_cb); + Return getMmapPosition(IStream::getMmapPosition_cb _hidl_cb); + + private: + StreamMmap() {} + + T* mStream; +}; + +template +Return StreamMmap::start() { + if (mStream->start == NULL) return Result::NOT_SUPPORTED; + int result = mStream->start(mStream); + return Stream::analyzeStatus("start", result); +} + +template +Return StreamMmap::stop() { + if (mStream->stop == NULL) return Result::NOT_SUPPORTED; + int result = mStream->stop(mStream); + return Stream::analyzeStatus("stop", result); +} + +template +Return StreamMmap::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 +Return StreamMmap::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 diff --git a/configs/audio/impl/include/core/default/StreamIn.h b/configs/audio/impl/include/core/default/StreamIn.h new file mode 100644 index 0000000..6209b8f --- /dev/null +++ b/configs/audio/impl/include/core/default/StreamIn.h @@ -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 +#include + +#include +#include +#include +#include +#include + +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 CommandMQ; + typedef MessageQueue DataMQ; + typedef MessageQueue StatusMQ; + + StreamIn(const sp& device, audio_stream_in_t* stream); + + // Methods from ::android::hardware::audio::CPP_VERSION::IStream follow. + Return getFrameSize() override; + Return getFrameCount() override; + Return getBufferSize() override; + Return getSampleRate() override; +#if MAJOR_VERSION == 2 + Return getSupportedSampleRates(getSupportedSampleRates_cb _hidl_cb) override; + Return getSupportedChannelMasks(getSupportedChannelMasks_cb _hidl_cb) override; +#endif + Return getSupportedSampleRates(AudioFormat format, getSupportedSampleRates_cb _hidl_cb); + Return getSupportedChannelMasks(AudioFormat format, getSupportedChannelMasks_cb _hidl_cb); + Return setSampleRate(uint32_t sampleRateHz) override; + Return getChannelMask() override; + Return setChannelMask(AudioChannelBitfield mask) override; + Return getFormat() override; + Return getSupportedFormats(getSupportedFormats_cb _hidl_cb) override; + Return setFormat(AudioFormat format) override; + Return getAudioProperties(getAudioProperties_cb _hidl_cb) override; + Return addEffect(uint64_t effectId) override; + Return removeEffect(uint64_t effectId) override; + Return standby() override; +#if MAJOR_VERSION == 2 + Return getDevice() override; + Return setDevice(const DeviceAddress& address) override; + Return getParameters(const hidl_vec& keys, + getParameters_cb _hidl_cb) override; + Return setParameters(const hidl_vec& parameters) override; + Return setConnectedState(const DeviceAddress& address, bool connected) override; +#elif MAJOR_VERSION >= 4 + Return getDevices(getDevices_cb _hidl_cb) override; + Return setDevices(const hidl_vec& devices) override; + Return getParameters(const hidl_vec& context, + const hidl_vec& keys, + getParameters_cb _hidl_cb) override; + Return setParameters(const hidl_vec& context, + const hidl_vec& parameters) override; +#endif + Return setHwAvSync(uint32_t hwAvSync) override; + Return close() override; + + Return debug(const hidl_handle& fd, const hidl_vec& options) override; +#if MAJOR_VERSION == 2 + Return debugDump(const hidl_handle& fd) override; +#endif + + // Methods from ::android::hardware::audio::CPP_VERSION::IStreamIn follow. + Return getAudioSource(getAudioSource_cb _hidl_cb) override; + Return setGain(float gain) override; + Return prepareForReading(uint32_t frameSize, uint32_t framesCount, + prepareForReading_cb _hidl_cb) override; + Return getInputFramesLost() override; + Return getCapturePosition(getCapturePosition_cb _hidl_cb) override; + Return start() override; + Return stop() override; + Return createMmapBuffer(int32_t minSizeFrames, createMmapBuffer_cb _hidl_cb) override; + Return getMmapPosition(getMmapPosition_cb _hidl_cb) override; +#if MAJOR_VERSION >= 4 + Return updateSinkMetadata(const SinkMetadata& sinkMetadata) override; + Return getActiveMicrophones(getActiveMicrophones_cb _hidl_cb) override; +#endif +#if MAJOR_VERSION >= 5 + Return setMicrophoneDirection(MicrophoneDirection direction) override; + Return setMicrophoneFieldDimension(float zoom) override; +#endif + static Result getCapturePositionImpl(audio_stream_in_t* stream, uint64_t* frames, + uint64_t* time); + + private: + bool mIsClosed; + const sp mDevice; + audio_stream_in_t* mStream; + const sp mStreamCommon; + const sp> mStreamMmap; + std::unique_ptr mCommandMQ; + std::unique_ptr mDataMQ; + std::unique_ptr mStatusMQ; + EventFlag* mEfGroup; + std::atomic mStopReadThread; + sp mReadThread; + + virtual ~StreamIn(); +}; + +} // namespace implementation +} // namespace CPP_VERSION +} // namespace audio +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_AUDIO_STREAMIN_H diff --git a/configs/audio/impl/include/core/default/StreamOut.h b/configs/audio/impl/include/core/default/StreamOut.h new file mode 100644 index 0000000..b098005 --- /dev/null +++ b/configs/audio/impl/include/core/default/StreamOut.h @@ -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 +#include + +#include +#include +#include +#include +#include + +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 CommandMQ; + typedef MessageQueue DataMQ; + typedef MessageQueue StatusMQ; + + StreamOut(const sp& device, audio_stream_out_t* stream); + + // Methods from ::android::hardware::audio::CPP_VERSION::IStream follow. + Return getFrameSize() override; + Return getFrameCount() override; + Return getBufferSize() override; + Return getSampleRate() override; +#if MAJOR_VERSION == 2 + Return getSupportedSampleRates(getSupportedSampleRates_cb _hidl_cb) override; + Return getSupportedChannelMasks(getSupportedChannelMasks_cb _hidl_cb) override; +#endif + Return getSupportedSampleRates(AudioFormat format, getSupportedSampleRates_cb _hidl_cb); + Return getSupportedChannelMasks(AudioFormat format, getSupportedChannelMasks_cb _hidl_cb); + Return setSampleRate(uint32_t sampleRateHz) override; + Return getChannelMask() override; + Return setChannelMask(AudioChannelBitfield mask) override; + Return getFormat() override; + Return getSupportedFormats(getSupportedFormats_cb _hidl_cb) override; + Return setFormat(AudioFormat format) override; + Return getAudioProperties(getAudioProperties_cb _hidl_cb) override; + Return addEffect(uint64_t effectId) override; + Return removeEffect(uint64_t effectId) override; + Return standby() override; +#if MAJOR_VERSION == 2 + Return getDevice() override; + Return setDevice(const DeviceAddress& address) override; + Return getParameters(const hidl_vec& keys, + getParameters_cb _hidl_cb) override; + Return setParameters(const hidl_vec& parameters) override; + Return setConnectedState(const DeviceAddress& address, bool connected) override; +#elif MAJOR_VERSION >= 4 + Return getDevices(getDevices_cb _hidl_cb) override; + Return setDevices(const hidl_vec& devices) override; + Return getParameters(const hidl_vec& context, + const hidl_vec& keys, + getParameters_cb _hidl_cb) override; + Return setParameters(const hidl_vec& context, + const hidl_vec& parameters) override; +#endif + Return setHwAvSync(uint32_t hwAvSync) override; + Return close() override; + + Return debug(const hidl_handle& fd, const hidl_vec& options) override; +#if MAJOR_VERSION == 2 + Return debugDump(const hidl_handle& fd) override; +#endif + + // Methods from ::android::hardware::audio::CPP_VERSION::IStreamOut follow. + Return getLatency() override; + Return setVolume(float left, float right) override; + Return prepareForWriting(uint32_t frameSize, uint32_t framesCount, + prepareForWriting_cb _hidl_cb) override; + Return getRenderPosition(getRenderPosition_cb _hidl_cb) override; + Return getNextWriteTimestamp(getNextWriteTimestamp_cb _hidl_cb) override; + Return setCallback(const sp& callback) override; + Return clearCallback() override; + Return supportsPauseAndResume(supportsPauseAndResume_cb _hidl_cb) override; + Return pause() override; + Return resume() override; + Return supportsDrain() override; + Return drain(AudioDrain type) override; + Return flush() override; + Return getPresentationPosition(getPresentationPosition_cb _hidl_cb) override; + Return start() override; + Return stop() override; + Return createMmapBuffer(int32_t minSizeFrames, createMmapBuffer_cb _hidl_cb) override; + Return getMmapPosition(getMmapPosition_cb _hidl_cb) override; +#if MAJOR_VERSION >= 4 + Return updateSourceMetadata(const SourceMetadata& sourceMetadata) override; + Return 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 mDevice; + audio_stream_out_t* mStream; + const sp mStreamCommon; + const sp> mStreamMmap; + sp mCallback; + std::unique_ptr mCommandMQ; + std::unique_ptr mDataMQ; + std::unique_ptr mStatusMQ; + EventFlag* mEfGroup; + std::atomic mStopWriteThread; + sp 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 diff --git a/configs/audio/impl/include/core/default/Util.h b/configs/audio/impl/include/core/default/Util.h new file mode 100644 index 0000000..78ae03e --- /dev/null +++ b/configs/audio/impl/include/core/default/Util.h @@ -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 +#include + +#include + +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 +inline bool element_in(T e, const std::vector& 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& 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 diff --git a/device.mk b/device.mk index 6960b60..1f56d3c 100755 --- a/device.mk +++ b/device.mk @@ -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 += \ diff --git a/configs/framework_manifest.xml b/framework_manifest.xml similarity index 100% rename from configs/framework_manifest.xml rename to framework_manifest.xml diff --git a/configs/manifest.xml b/manifest.xml old mode 100755 new mode 100644 similarity index 71% rename from configs/manifest.xml rename to manifest.xml index f4d866a..437db2b --- a/configs/manifest.xml +++ b/manifest.xml @@ -1,31 +1,4 @@ - - + android.hardware.audio hwbinder @@ -53,15 +26,6 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. default - - vendor.samsung.hardware.biometrics.fingerprint - hwbinder - 2.1 - - ISecBiometricsFingerprint - default - - android.hardware.bluetooth hwbinder @@ -81,12 +45,21 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - android.hardware.camera.provider - passthrough - 2.4 + android.hardware.broadcastradio + hwbinder + 1.0 - ICameraProvider - legacy/0 + IBroadcastRadioFactory + default + + + + android.hardware.cas + hwbinder + 1.0 + + IMediaCasService + default @@ -132,7 +105,6 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. IGnss default - @1.0::IGnss/default @1.0::IGnss/gnss_vendor @@ -162,13 +134,14 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. default - + android.hardware.health hwbinder 2.0 IHealth default + sehhealth @@ -214,34 +187,12 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. android.hardware.power hwbinder - 1.2 + 1.0 IPower default - - android.hardware.radio - hwbinder - 1.1 - - IRadio - slot1 - - - ISap - slot1 - - - - android.hardware.radio.deprecated - hwbinder - 1.0 - - IOemHook - slot1 - - android.hardware.renderscript passthrough @@ -270,20 +221,11 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - android.hardware.tetheroffload.config + android.hardware.thermal hwbinder 1.0 - IOffloadConfig - default - - - - android.hardware.tetheroffload.control - hwbinder - 1.0 - - IOffloadControl + IThermal default @@ -296,19 +238,10 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. default - - android.hardware.vibrator - hwbinder - 1.0 - - IVibrator - default - - android.hardware.wifi hwbinder - 1.3 + 1.2 IWifi default @@ -317,7 +250,7 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. android.hardware.wifi.hostapd hwbinder - 1.1 + 1.0 IHostapd default @@ -326,7 +259,7 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. android.hardware.wifi.supplicant hwbinder - 1.2 + 1.1 ISupplicant default @@ -342,22 +275,40 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - com.qualcomm.qti.dpm.api + com.qualcomm.qti.bluetooth_audio hwbinder 1.0 - IdpmQmi - dpmQmiService + IBluetoothAudio + default - + + com.qualcomm.qti.dpm.api + hwbinder + + + com.qualcomm.qti.imscmservice + hwbinder + + com.qualcomm.qti.uceservice hwbinder + + + com.qualcomm.qti.wifidisplayhal + hwbinder 1.0 - IUceService - com.qualcomm.qti.uceservice + IDSManager + wifidisplaydshal + + IHDCPSession + wifidisplayhdcphal + + @1.0::IDSManager/wifidisplaydshal + @1.0::IHDCPSession/wifidisplayhdcphal vendor.display.color @@ -386,96 +337,31 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. default - - - vendor.lineage.trust - hwbinder - 1.0 - - IUsbRestrict - default - - - vendor.lineage.touch - passthrough - 1.0 - - IGloveMode - default - - - IKeyDisabler - default - - - IStylusMode - default - - - ITouchscreenGesture - default - + + vendor.qti.data.factory + hwbinder vendor.qti.gnss hwbinder - 1.2 + 1.0 ILocHidlGnss gnss_vendor - @1.2::ILocHidlGnss/gnss_vendor - - - vendor.qti.gnss - hwbinder - 2.0 - - ILocHidlGnss - gnss_vendor - - @2.0::ILocHidlGnss/gnss_vendor vendor.qti.hardware.alarm @@ -486,21 +372,20 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. default - - vendor.qti.hardware.cryptfshw + + vendor.qti.hardware.data.connection hwbinder - 1.0 - - ICryptfsHw - default - - + vendor.qti.hardware.data.latency hwbinder + + + vendor.qti.hardware.fm + hwbinder 1.0 - ILinkLatency + IFmHci default @@ -521,6 +406,7 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. IPerf default + @1.0::IPerf/default vendor.qti.hardware.qdutils_disp @@ -532,91 +418,177 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - vendor.qti.hardware.radio.am + vendor.qti.hardware.qteeconnector hwbinder 1.0 - IQcRilAudio - slot1 - slot2 + IAppConnector + default + + + IGPAppConnector + default - vendor.qti.hardware.radio.atcmdfwd + vendor.qti.hardware.tui_comm hwbinder 1.0 - IAtCmdFwd - AtCmdFwdService + ITuiComm + default - vendor.qti.hardware.radio.ims + vendor.qti.hardware.wifi.hostapd hwbinder 1.0 - IImsRadio - imsradio0 - imsradio1 + IHostapdVendor + default - vendor.qti.hardware.radio.lpa + vendor.qti.hardware.wifi.supplicant hwbinder - 1.0 + 2.0 - IUimLpa - UimLpa0 + ISupplicantVendor + default - vendor.qti.hardware.radio.qcrilhook + vendor.qti.hardware.wigig.netperftuner hwbinder 1.0 - IQtiOemHook - oemhook0 - oemhook1 + INetPerfTuner + default - vendor.qti.hardware.radio.qtiradio + vendor.qti.hardware.wigig.supptunnel hwbinder 1.0 - IQtiRadio - slot1 - slot2 + ISuppTunnelProvider + default + + + + vendor.qti.ims.callinfo + hwbinder + + + vendor.qti.imsrtpservice + hwbinder + + + vendor.samsung.external.secure_storage + hwbinder + 2.0 + + ISecureStorage + default - vendor.qti.hardware.radio.uim + vendor.samsung.hardware.biometrics.fingerprint hwbinder - 1.0 + 2.1 - IUim - Uim0 - Uim1 + ISecBiometricsFingerprint + default - vendor.qti.hardware.radio.uim_remote_client + vendor.samsung.hardware.gnss hwbinder 1.0 - IUimRemoteServiceClient - uimRemoteClient0 - uimRemoteClient1 + ISecGnss + default - vendor.qti.hardware.radio.uim_remote_server + vendor.samsung.hardware.health + hwbinder + 2.0 + + ISehHealth + sehhealth + + + + vendor.samsung.hardware.miscpower hwbinder 1.0 - IUimRemoteServiceServer - uimRemoteServer0 - uimRemoteServer1 + ISecMiscPower + miscpower + + + + vendor.samsung.hardware.wifi + hwbinder + 1.0 + + IWifiExt + default + + + + vendor.samsung.hardware.wifi.hostapd + hwbinder + 1.0 + + ISemHostapd + default + + + + vendor.samsung.hardware.wifi.supplicant + hwbinder + 1.0 + + ISupplicantExt + default + + + + vendor.samsung.security.proca + hwbinder + 1.0 + + IProcaDaemon + default + + + + vendor.samsung.security.skpm + hwbinder + 1.0 + + ISkpm + default + + + + vendor.samsung.security.vaultkeeper_server + hwbinder + 1.0 + + Ivaultkeeper_server + default + + + + vendor.samsung.security.wvkprov_server + hwbinder + 1.0 + + Iwvkprov_server + default