replace common qcom sources with samsung ones

This commit is contained in:
SaschaNes
2025-08-12 22:13:00 +02:00
parent ba24dcded9
commit 6f7753de11
5682 changed files with 2450203 additions and 103634 deletions

View File

@@ -0,0 +1,2 @@
AUDIO_OS_ROOT := $(call my-dir)
include $(call all-subdir-makefiles)

View File

@@ -0,0 +1,35 @@
MM_AUDIO := libaudiohal
MM_AUDIO += audiosphere
MM_AUDIO += audiosphere.xml
MM_AUDIO += libbinauralrenderer_wrapper.qti
MM_AUDIO += libhoaeffects_csim
MM_AUDIO += libhoaeffects.qti
MM_AUDIO += liblistenjni.qti
MM_AUDIO += liblistensoundmodel2.qti
MM_AUDIO += libvr_amb_engine
MM_AUDIO += libvraudio_client.qti
MM_AUDIO += libvraudio
MM_AUDIO += libvr_object_engine
MM_AUDIO += libvr_sam_wrapper
MM_AUDIO += libaudio-resampler
MM_AUDIO += libaudioprocessing
MM_AUDIO += libaudiopolicymanagerdefault
MM_AUDIO += libaudiopolicyenginedefault
MM_AUDIO += mixerops_objdump
MM_AUDIO += test-mixer
MM_AUDIO += test-resampler
MM_AUDIO += mixerops_benchmark
MM_AUDIO += resampler_tests
# AIDL AHAL VENDOR EXTENSION
MM_AUDIO += libaudiohalvendorextn
PRODUCT_SYSTEM_EXT_PROPERTIES += \
ro.audio.ihaladaptervendorextension_enabled=true
MM_AUDIO_DBG := MhaPlayerDemoApp
MM_AUDIO_DBG += MhaRecorderDemoApp
PRODUCT_PACKAGES += $(MM_AUDIO)
PRODUCT_PACKAGES_DEBUG += $(MM_AUDIO_DBG)

View File

@@ -0,0 +1,127 @@
#BOARD_USES_GENERIC_AUDIO := true
#
#AUDIO_FEATURE_FLAGS
BOARD_USES_ALSA_AUDIO := true
TARGET_USES_AOSP_FOR_AUDIO := false
AUDIO_FEATURE_QSSI_COMPLIANCE := true
ifneq ($(TARGET_USES_AOSP_FOR_AUDIO), true)
ifeq ($(TARGET_FWK_SUPPORTS_FULL_VALUEADDS),true)
USE_CUSTOM_AUDIO_POLICY := 1
else
USE_CUSTOM_AUDIO_POLICY := 0
endif
AUDIO_FEATURE_ENABLED_COMPRESS_VOIP := false
AUDIO_FEATURE_ENABLED_EXTN_FORMATS := true
AUDIO_FEATURE_ENABLED_EXTN_FLAC_DECODER := true
AUDIO_FEATURE_ENABLED_EXTN_RESAMPLER := true
AUDIO_FEATURE_ENABLED_FM_POWER_OPT := true
AUDIO_FEATURE_ENABLED_HDMI_SPK := true
AUDIO_FEATURE_ENABLED_PCM_OFFLOAD := true
AUDIO_FEATURE_ENABLED_PCM_OFFLOAD_24 := true
AUDIO_FEATURE_ENABLED_FLAC_OFFLOAD := true
AUDIO_FEATURE_ENABLED_VORBIS_OFFLOAD := true
AUDIO_FEATURE_ENABLED_WMA_OFFLOAD := true
AUDIO_FEATURE_ENABLED_ALAC_OFFLOAD := true
AUDIO_FEATURE_ENABLED_APE_OFFLOAD := true
AUDIO_FEATURE_ENABLED_AAC_ADTS_OFFLOAD := true
AUDIO_FEATURE_ENABLED_PROXY_DEVICE := true
AUDIO_FEATURE_ENABLED_AUDIOSPHERE := true
AUDIO_FEATURE_ENABLED_3D_AUDIO := true
AUDIO_FEATURE_ENABLED_AHAL_EXT := false
DOLBY_ENABLE := false
endif
USE_XML_AUDIO_POLICY_CONF := 1
BOARD_SUPPORTS_SOUND_TRIGGER := true
#AUDIO_FEATURE_ENABLED_KEEP_ALIVE := true
AUDIO_FEATURE_ENABLED_DS2_DOLBY_DAP := false
TARGET_USES_QCOM_MM_AUDIO := true
AUDIO_FEATURE_ENABLED_SVA_MULTI_STAGE := true
##AUDIO_FEATURE_FLAGS
ifneq ($(strip $(TARGET_USES_RRO)), true)
#Audio Specific device overlays
DEVICE_PACKAGE_OVERLAYS += hardware/qcom/audio/configs/common/overlay
endif
ifneq ($(GENERIC_ODM_IMAGE),true)
# Reduce client buffer size for fast audio output tracks
PRODUCT_PRODUCT_PROPERTIES += \
af.fast_track_multiplier=1
#Enable offload audio video playback by default
PRODUCT_PRODUCT_PROPERTIES += \
audio.offload.video=true
#Enable music through deep buffer
PRODUCT_PRODUCT_PROPERTIES += \
audio.deep_buffer.media=true
#audio becoming noisy intent broadcast delay
PRODUCT_PRODUCT_PROPERTIES += \
audio.sys.noisy.broadcast.delay=500
#audio device switch mute latency factor for draining unmuted data
PRODUCT_PRODUCT_PROPERTIES += \
audio.sys.mute.latency.factor=2
#audio device switch mute latency to absorb routing activities
PRODUCT_PRODUCT_PROPERTIES += \
audio.sys.routing.latency=0
#offload minimum duration set to 30sec
PRODUCT_PRODUCT_PROPERTIES += \
audio.offload.min.duration.secs=30
#offload pausetime out duration to 3 secs to inline with other outputs
PRODUCT_PRODUCT_PROPERTIES += \
audio.sys.offload.pstimeout.secs=3
#Set AudioFlinger client heap size
PRODUCT_PRODUCT_PROPERTIES += \
ro.af.client_heap_size_kbyte=7168
#enable deep buffer
PRODUCT_PRODUCT_PROPERTIES += \
media.stagefright.audio.deep=false
endif
#guard for non generic_odm_image
# Enable AAudio MMAP/NOIRQ data path.
# 2 is AAUDIO_POLICY_AUTO so it will try MMAP then fallback to Legacy path.
PRODUCT_PRODUCT_PROPERTIES += aaudio.mmap_policy=2
# Allow EXCLUSIVE then fall back to SHARED.
PRODUCT_PRODUCT_PROPERTIES += aaudio.mmap_exclusive_policy=2
PRODUCT_PRODUCT_PROPERTIES += aaudio.hw_burst_min_usec=2000
# for HIDL related packages
PRODUCT_PACKAGES += \
android.hardware.audio@4.0 \
android.hardware.audio.common@4.0 \
android.hardware.audio.common@4.0-util \
android.hardware.audio.effect@4.0
# enable audio hidl hal 5.0
PRODUCT_PACKAGES += \
android.hardware.audio@5.0 \
android.hardware.audio.common@5.0 \
android.hardware.audio.common@5.0-util \
android.hardware.audio.effect@5.0 \
#enable audio hidl hal 6.0
PRODUCT_PACKAGES += \
android.hardware.audio@6.0 \
android.hardware.audio.common@6.0 \
android.hardware.audio.common@6.0-util \
android.hardware.audio.effect@6.0
PRODUCT_PACKAGES_ENG += \
VoicePrintTest \
VoicePrintDemo
PRODUCT_PACKAGES_DEBUG += \
AudioSettings
PRODUCT_PACKAGES += libnbaio

View File

@@ -0,0 +1,56 @@
aidl_interface {
name: "qti-audio-types-aidl",
stability: "vintf",
owner: "qcom",
system_ext_specific: true,
vendor_available: true,
local_include_dir: "aidl",
srcs: [
"aidl/qti/audio/core/VString.aidl",
],
backend: {
cpp: {
enabled: false,
},
java: {
enabled: false,
},
},
versions_with_info: [
{
version: "1",
imports: [],
},
],
frozen: true,
}
cc_library {
name: "libaudiohalvendorextn",
system_ext_specific: true,
srcs: ["HalAdapterVendorExtension.cpp"],
export_include_dirs: [
"include",
],
header_libs: [
"libsystem_headers",
],
shared_libs: [
"av-audio-types-aidl-V1-ndk",
"libbinder_ndk",
"libbase",
"qti-audio-types-aidl-V1-ndk",
],
cflags: [
"-Wall",
"-Wextra",
"-Werror",
"-Wthread-safety",
"-DBACKEND_NDK",
],
}

View File

@@ -0,0 +1,224 @@
/*
* Copyright (c) 2023-2024 Qualcomm Innovation Center, Inc. All rights reserved.
* SPDX-License-Identifier: BSD-3-Clause-Clear
*/
#define LOG_TAG "QHAVExt"
#include <aidl/qti/audio/core/VString.h>
#include <android-base/logging.h>
#include <android/binder_ibinder_platform.h>
#include <android/binder_manager.h>
#include <android/binder_process.h>
#include <qti-audio-core/HalAdapterVendorExtension.h>
#include <system/thread_defs.h>
#include <numeric>
// no headers below these
namespace qti::audio::core {
/* sfsfc;dvfrg=1;yupp => {sfsfc,dvfrg=1,yupp} */
auto getVectorFromString =
[](const std::string& keyString) -> std::vector<std::string> {
const auto keyLength = keyString.length();
if (keyString.length() == 0) {
return {};
}
std::vector<std::string> result;
size_t i = 0;
const std::string delimiter{";"};
size_t foundPos = 0;
while ((foundPos = keyString.find(delimiter, i)) != std::string::npos) {
std::cout << "foundPos: " << foundPos << std::endl;
std::string key = keyString.substr(i, foundPos - i);
key.empty() ? (void)0 : (void)result.push_back(key);
i = foundPos + 1;
}
if (i != keyLength) {
std::string key = keyString.substr(i, keyLength);
result.push_back(key);
}
return result;
};
/* {sfsfc=???,one=1,yupp=okay} => {{sfsfc,???},{one,1},{yupp,okay}} */
auto getPairsFromVector = [](const std::vector<std::string>& keyValues) {
std::vector<std::pair<std::string, std::string>> keyValuePairs;
for (const auto& keyValue : keyValues) {
const std::string delimiter{"="};
auto foundPos = keyValue.find(delimiter, 0);
if (foundPos == std::string::npos) {
keyValuePairs.push_back({keyValue, ""});
continue;
}
std::string key = keyValue.substr(0, foundPos);
std::string value = keyValue.substr(foundPos + 1, keyValue.size());
keyValuePairs.push_back({key, value});
}
return keyValuePairs;
};
::aidl::android::hardware::audio::core::VendorParameter
getVendorParameterAsVString(const std::string& key, const std::string& value) {
::aidl::android::hardware::audio::core::VendorParameter param;
::aidl::qti::audio::core::VString parcel;
param.id = key;
parcel.value = value;
if (param.ext.setParcelable(parcel) != android::OK) {
LOG(ERROR) << __func__ << ": failed to set parcel for "
<< parcel.descriptor;
}
return std::move(param);
}
std::optional<std::string> getStringForVendorParameterAsVString(
const ::aidl::android::hardware::audio::core::VendorParameter& param) {
std::optional<::aidl::qti::audio::core::VString> parcel;
param.ext.getParcelable(&parcel);
if (!parcel.has_value()) {
LOG(ERROR) << __func__
<< " unable to get parcelable for key:" << param.id;
return std::nullopt;
}
return param.id + "=" + parcel.value().value;
}
::ndk::ScopedAStatus HalAdapterVendorExtension::parseVendorParameterIds(
::aidl::android::media::audio::IHalAdapterVendorExtension::ParameterScope
in_scope,
const std::string& in_rawKeys, std::vector<std::string>* _aidl_return) {
*_aidl_return = getVectorFromString(in_rawKeys);
LOG(VERBOSE) << __func__
<< ": scope:" << ::aidl::android::media::audio::toString(in_scope)
<< ", raw keys:" << in_rawKeys << " ==> VendorParameter Ids:"
<< std::accumulate(_aidl_return->cbegin(), _aidl_return->cend(),
std::string(""), [](auto prev, auto ele) {
return std::move(prev) + " " + ele;
});
return ndk::ScopedAStatus::ok();
}
::ndk::ScopedAStatus HalAdapterVendorExtension::parseVendorParameters(
::aidl::android::media::audio::IHalAdapterVendorExtension::ParameterScope
in_scope,
const std::string& in_rawKeysAndValues,
std::vector<::aidl::android::hardware::audio::core::VendorParameter>*
out_syncParameters,
std::vector<::aidl::android::hardware::audio::core::VendorParameter>*
out_asyncParameters) {
const auto& keyValues = getVectorFromString(in_rawKeysAndValues);
const auto& keyValuesPairs = getPairsFromVector(keyValues);
std::vector<::aidl::android::hardware::audio::core::VendorParameter> result;
for (const auto& [key, value] : keyValuesPairs) {
result.push_back(getVendorParameterAsVString(key, value));
}
*out_syncParameters = result;
*out_asyncParameters = {};
LOG(VERBOSE)
<< __func__
<< ": scope:" << ::aidl::android::media::audio::toString(in_scope)
<< ", raw keyandvalues:" << in_rawKeysAndValues
<< ", VendorParameters Ids size:" << out_syncParameters->size()
<< " ==> "
<< std::accumulate(
out_syncParameters->cbegin(), out_syncParameters->cend(),
std::string(""), [](auto prev, auto ele) {
std::optional<::aidl::qti::audio::core::VString> parcel;
ele.ext.getParcelable(&parcel);
return std::move(prev) + " {" + ele.id + "," +
(parcel ? parcel.value().value : " not parcelled ") +
"}";
});
return ndk::ScopedAStatus::ok();
}
::ndk::ScopedAStatus
HalAdapterVendorExtension::parseBluetoothA2dpReconfigureOffload(
const std::string& in_rawValue,
std::vector<::aidl::android::hardware::audio::core::VendorParameter>*
_aidl_return) {
LOG(ERROR) << __func__ << "not implemented";
return ndk::ScopedAStatus::ok();
}
::ndk::ScopedAStatus
HalAdapterVendorExtension::parseBluetoothLeReconfigureOffload(
const std::string& in_rawValue,
std::vector<::aidl::android::hardware::audio::core::VendorParameter>*
_aidl_return) {
LOG(ERROR) << __func__ << "not implemented";
return ndk::ScopedAStatus::ok();
}
::ndk::ScopedAStatus HalAdapterVendorExtension::processVendorParameters(
::aidl::android::media::audio::IHalAdapterVendorExtension::ParameterScope
in_scope,
const std::vector<::aidl::android::hardware::audio::core::VendorParameter>&
in_parameters,
std::string* _aidl_return) {
std::string keyValuesString{""};
for (const auto& param : in_parameters) {
const auto& out = getStringForVendorParameterAsVString(param);
if (!out.has_value()) {
continue;
}
if (keyValuesString == "") {
keyValuesString = out.value();
} else {
keyValuesString.append(";").append(out.value());
}
}
*_aidl_return = keyValuesString;
LOG(VERBOSE) << __func__
<< ": scope:" << ::aidl::android::media::audio::toString(in_scope)
<< ", parameters size: " << in_parameters.size()
<< ", VendorParameters Ids:"
<< std::accumulate(in_parameters.cbegin(), in_parameters.cend(),
std::string(""),
[](auto prev, auto ele) {
return std::move(prev) + " " + ele.id;
})
<< " ==> raw key and values: " << *_aidl_return;
return ndk::ScopedAStatus::ok();
}
} // namespace qti::audio::core
/**
* in case, if someone want to dlopen this library and
* register this as AIDL service.
*
* Also, as per the interface expectation,
* one needs to set the system property
* 'ro.audio.ihaladaptervendorextension_enabled' to be true
*
**/
static std::shared_ptr<::qti::audio::core::HalAdapterVendorExtension>
gHalAdapterVendorExtension;
extern "C" __attribute__((visibility("default"))) void registerInterface() {
gHalAdapterVendorExtension = ndk::SharedRefBase::make<
::qti::audio::core::HalAdapterVendorExtension>();
const auto kServiceName =
std::string(gHalAdapterVendorExtension->descriptor)
.append("/")
.append("default");
AIBinder_setMinSchedulerPolicy(gHalAdapterVendorExtension->asBinder().get(),
SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
binder_exception_t status = AServiceManager_addService(
gHalAdapterVendorExtension->asBinder().get(), kServiceName.c_str());
if (status != EX_NONE) {
LOG(ERROR) << __func__ << " failed to register " << kServiceName
<< " ret:" << status;
}
}

View File

@@ -0,0 +1,18 @@
/*
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
* SPDX-License-Identifier: BSD-3-Clause-Clear
*/
package qti.audio.core;
/**
* This is a simple wrapper around an 'string', putting it in a parcelable, so it
* can be used as an 'inout' parameter, be made '@nullable', etc.
*
* {@hide}
*/
@JavaDerive(equals=true, toString=true)
@VintfStability
parcelable VString {
@utf8InCpp String value;
}

View File

@@ -0,0 +1 @@
97fa0e47495973748d210f63c7acdc748fbea3ac

View File

@@ -0,0 +1,28 @@
/*
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
* SPDX-License-Identifier: BSD-3-Clause-Clear
*/
///////////////////////////////////////////////////////////////////////////////
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
///////////////////////////////////////////////////////////////////////////////
// This file is a snapshot of an AIDL file. Do not edit it manually. There are
// two cases:
// 1). this is a frozen version file - do not edit this in any case.
// 2). this is a 'current' file. If you make a backwards compatible change to
// the interface (from the latest frozen version), the build system will
// prompt you to update this file with `m <name>-update-api`.
//
// You must not make a backward incompatible change to any AIDL file built
// with the aidl_interface module type with versions property set. The module
// type is used to build AIDL files in a way that they can be used across
// independently updatable components of the system. If a device is shipped
// with such a backward incompatible change, it has a high risk of breaking
// later when a module using the interface is updated, e.g., Mainline modules.
package qti.audio.core;
/* @hide */
@JavaDerive(equals=true, toString=true) @VintfStability
parcelable VString {
@utf8InCpp String value;
}

View File

@@ -0,0 +1,28 @@
/*
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
* SPDX-License-Identifier: BSD-3-Clause-Clear
*/
///////////////////////////////////////////////////////////////////////////////
// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
///////////////////////////////////////////////////////////////////////////////
// This file is a snapshot of an AIDL file. Do not edit it manually. There are
// two cases:
// 1). this is a frozen version file - do not edit this in any case.
// 2). this is a 'current' file. If you make a backwards compatible change to
// the interface (from the latest frozen version), the build system will
// prompt you to update this file with `m <name>-update-api`.
//
// You must not make a backward incompatible change to any AIDL file built
// with the aidl_interface module type with versions property set. The module
// type is used to build AIDL files in a way that they can be used across
// independently updatable components of the system. If a device is shipped
// with such a backward incompatible change, it has a high risk of breaking
// later when a module using the interface is updated, e.g., Mainline modules.
package qti.audio.core;
/* @hide */
@JavaDerive(equals=true, toString=true) @VintfStability
parcelable VString {
@utf8InCpp String value;
}

View File

@@ -0,0 +1,47 @@
/*
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
* SPDX-License-Identifier: BSD-3-Clause-Clear
*/
#pragma once
#include <aidl/android/media/audio/BnHalAdapterVendorExtension.h>
namespace qti::audio::core {
/**
* This is responsible for validating the parameters like key, key length validation
**/
class HalAdapterVendorExtension
: public ::aidl::android::media::audio::BnHalAdapterVendorExtension {
public:
::ndk::ScopedAStatus parseVendorParameterIds(
::aidl::android::media::audio::IHalAdapterVendorExtension::
ParameterScope in_scope,
const std::string& in_rawKeys,
std::vector<std::string>* _aidl_return) override;
::ndk::ScopedAStatus parseVendorParameters(
::aidl::android::media::audio::IHalAdapterVendorExtension::
ParameterScope in_scope,
const std::string& in_rawKeysAndValues,
std::vector<::aidl::android::hardware::audio::core::VendorParameter>*
out_syncParameters,
std::vector<::aidl::android::hardware::audio::core::VendorParameter>*
out_asyncParameters) override;
::ndk::ScopedAStatus parseBluetoothA2dpReconfigureOffload(
const std::string& in_rawValue,
std::vector<::aidl::android::hardware::audio::core::VendorParameter>*
_aidl_return) override;
::ndk::ScopedAStatus parseBluetoothLeReconfigureOffload(
const std::string& in_rawValue,
std::vector<::aidl::android::hardware::audio::core::VendorParameter>*
_aidl_return) override;
::ndk::ScopedAStatus processVendorParameters(
::aidl::android::media::audio::IHalAdapterVendorExtension::
ParameterScope in_scope,
const std::vector<
::aidl::android::hardware::audio::core::VendorParameter>&
in_parameters,
std::string* _aidl_return) override;
};
} // namespace qti::audio::core

View File

@@ -0,0 +1,372 @@
/*
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Changes from Qualcomm Innovation Center are provided under the following license:
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted (subject to the limitations in the
* disclaimer below) provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Qualcomm Innovation Center, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
* GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
* HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
//#define LOG_NDEBUG 0
#define LOG_TAG "APMConfigHelper"
#include "APMConfigHelper.h"
#include <cutils/properties.h>
#include <log/log.h>
#include <stdlib.h>
namespace android {
void APMConfigHelper::dump(String8 *dst) const
{
// apmconfig struct dump
dst->appendFormat("\nAudioPolicyManagerCustom Dump: %p\n", this);
dst->appendFormat("audio_offload_video: %d \n", mConfigs.audio_offload_video);
dst->appendFormat("audio_offload_disable: %d \n", mConfigs.audio_offload_disable);
dst->appendFormat("audio_deepbuffer_media: %d \n", mConfigs.audio_deepbuffer_media);
dst->appendFormat("audio_av_streaming_offload_enable: %d \n", mConfigs.audio_av_streaming_offload_enable);
dst->appendFormat("audio_offload_track_enable: %d \n", mConfigs.audio_offload_track_enable);
dst->appendFormat("audio_offload_multiple_enabled: %d \n", mConfigs.audio_offload_multiple_enabled);
dst->appendFormat("voice_dsd_playback_conc_disabled: %d \n", mConfigs.voice_dsd_playback_conc_disabled);
dst->appendFormat("audio_sva_conc_enabled: %d \n", mConfigs.audio_sva_conc_enabled);
dst->appendFormat("audio_va_concurrency_enabled: %d \n", mConfigs.audio_va_concurrency_enabled);
dst->appendFormat("audio_rec_playback_conc_disabled: %d \n", mConfigs.audio_rec_playback_conc_disabled);
dst->appendFormat("voice_path_for_pcm_voip: %d \n", mConfigs.voice_path_for_pcm_voip);
dst->appendFormat("voice_playback_conc_disabled: %d \n", mConfigs.voice_playback_conc_disabled);
dst->appendFormat("voice_record_conc_disabled: %d \n", mConfigs.voice_record_conc_disabled);
dst->appendFormat("voice_voip_conc_disabled: %d \n", mConfigs.voice_voip_conc_disabled);
dst->appendFormat("audio_offload_min_duration_secs: %u \n", mConfigs.audio_offload_min_duration_secs);
dst->appendFormat("voice_conc_fallbackpath: %s \n", mConfigs.voice_conc_fallbackpath.c_str());
dst->appendFormat("audio_extn_hdmi_spk_enabled: %d \n", mConfigs.audio_extn_hdmi_spk_enabled);
dst->appendFormat("audio_extn_formats_enabled: %d \n", mConfigs.audio_extn_formats_enabled);
dst->appendFormat("audio_extn_afe_proxy_enabled: %d \n", mConfigs.audio_extn_afe_proxy_enabled);
dst->appendFormat("compress_voip_enabled: %d \n", mConfigs.compress_voip_enabled);
dst->appendFormat("fm_power_opt: %d \n", mConfigs.fm_power_opt);
dst->appendFormat("voice_concurrency: %d \n", mConfigs.voice_concurrency);
dst->appendFormat("record_play_concurrency: %d \n", mConfigs.record_play_concurrency);
dst->appendFormat("use_xml_audio_policy_conf: %d \n", mConfigs.use_xml_audio_policy_conf);
}
void APMConfigHelper::retrieveConfigs()
{
// apmconfig struct dump
ALOGV("apmconfigs retrieved from %s", isRemote? "remote" : "local");
ALOGV("audio_offload_video: %d", mConfigs.audio_offload_video);
ALOGV("audio_offload_disable: %d", mConfigs.audio_offload_disable);
ALOGV("audio_deepbuffer_media: %d", mConfigs.audio_deepbuffer_media);
ALOGV("audio_av_streaming_offload_enable: %d", mConfigs.audio_av_streaming_offload_enable);
ALOGV("audio_offload_track_enable: %d", mConfigs.audio_offload_track_enable);
ALOGV("audio_offload_multiple_enabled: %d", mConfigs.audio_offload_multiple_enabled);
ALOGV("voice_dsd_playback_conc_disabled: %d", mConfigs.voice_dsd_playback_conc_disabled);
ALOGV("audio_sva_conc_enabled: %d", mConfigs.audio_sva_conc_enabled);
ALOGV("audio_va_concurrency_enabled: %d", mConfigs.audio_va_concurrency_enabled);
ALOGV("audio_rec_playback_conc_disabled: %d", mConfigs.audio_rec_playback_conc_disabled);
ALOGV("voice_path_for_pcm_voip: %d", mConfigs.voice_path_for_pcm_voip);
ALOGV("voice_playback_conc_disabled: %d", mConfigs.voice_playback_conc_disabled);
ALOGV("voice_record_conc_disabled: %d", mConfigs.voice_record_conc_disabled);
ALOGV("voice_voip_conc_disabled: %d", mConfigs.voice_voip_conc_disabled);
ALOGV("audio_offload_min_duration_secs: %u", mConfigs.audio_offload_min_duration_secs);
ALOGV("voice_conc_fallbackpath: %s", mConfigs.voice_conc_fallbackpath.c_str());
ALOGV("audio_extn_hdmi_spk_enabled: %d", mConfigs.audio_extn_hdmi_spk_enabled);
ALOGV("audio_extn_formats_enabled: %d", mConfigs.audio_extn_formats_enabled);
ALOGV("audio_extn_afe_proxy_enabled: %d", mConfigs.audio_extn_afe_proxy_enabled);
ALOGV("compress_voip_enabled: %d", mConfigs.compress_voip_enabled);
ALOGV("fm_power_opt: %d", mConfigs.fm_power_opt);
ALOGV("voice_concurrency: %d", mConfigs.voice_concurrency);
ALOGV("record_play_concurrency: %d", mConfigs.record_play_concurrency);
ALOGV("use_xml_audio_policy_conf: %d", mConfigs.use_xml_audio_policy_conf);
return;
}
APMConfigHelper::APMConfigHelper()
: isRemote(false)
{
uint32_t audio_offload_min_duration_secs = 0;
char voice_conc_fallbackpath[PROPERTY_VALUE_MAX] = "\0";
audio_offload_min_duration_secs =
(uint32_t)property_get_int32("audio.offload.min.duration.secs", 0);
property_get("vendor.voice.conc.fallbackpath", voice_conc_fallbackpath, NULL);
mConfigs = {
(bool) property_get_bool("audio.offload.video", true),
(bool) property_get_bool("audio.offload.disable", false),
(bool) property_get_bool("audio.deep_buffer.media", true),
(bool) property_get_bool("vendor.audio.av.streaming.offload.enable", false),
(bool) property_get_bool("vendor.audio.offload.track.enable", true),
(bool) property_get_bool("vendor.audio.offload.multiple.enabled", false),
(bool) property_get_bool("vendor.voice.dsd.playback.conc.disabled", true),
(bool) property_get_bool("persist.vendor.audio.sva.conc.enabled", false),
(bool) property_get_bool("persist.vendor.audio.va_concurrency_enabled", false),
(bool) property_get_bool("vendor.audio.rec.playback.conc.disabled", false),
(bool) property_get_bool("vendor.voice.path.for.pcm.voip", true),
(bool) property_get_bool("vendor.voice.playback.conc.disabled", false),
(bool) property_get_bool("vendor.voice.record.conc.disabled", false),
(bool) property_get_bool("vendor.voice.voip.conc.disabled", false),
audio_offload_min_duration_secs,
voice_conc_fallbackpath,
#ifdef AUDIO_EXTN_HDMI_SPK_ENABLED
true,
#else
false,
#endif
#ifdef AUDIO_EXTN_FORMATS_ENABLED
true,
#else
false,
#endif
#ifdef AUDIO_EXTN_AFE_PROXY_ENABLED
true,
#else
false,
#endif
#ifdef COMPRESS_VOIP_ENABLED
true,
#else
false,
#endif
#ifdef FM_POWER_OPT
true,
#else
false,
#endif
#ifdef VOICE_CONCURRENCY
true,
#else
false,
#endif
#ifdef RECORD_PLAY_CONCURRENCY
true,
#else
false,
#endif
#ifdef USE_XML_AUDIO_POLICY_CONF
true,
#else
false,
#endif
};
}
bool APMConfigHelper::isAudioOffloadVideoEnabled()
{
ALOGV("isAudioOffloadVideoEnabled enter");
retrieveConfigs();
return mConfigs.audio_offload_video;
}
bool APMConfigHelper::isAudioOffloadDisabled()
{
ALOGV("isAudioOffloadDisabled enter");
retrieveConfigs();
return mConfigs.audio_offload_disable;
}
bool APMConfigHelper::isAudioDeepbufferMediaEnabled()
{
ALOGV("isAudioDeepbufferMediaEnabled enter");
retrieveConfigs();
return mConfigs.audio_deepbuffer_media;
}
bool APMConfigHelper::isAVStreamingOffloadEnabled()
{
ALOGV("isAVStreamingOffloadEnabled enter");
retrieveConfigs();
return mConfigs.audio_av_streaming_offload_enable;
}
bool APMConfigHelper::isAudioTrackOffloadEnabled()
{
ALOGV("isAudioTrackOffloadEnabled enter");
retrieveConfigs();
return mConfigs.audio_offload_track_enable;
}
bool APMConfigHelper::isAudioMultipleOffloadEnable()
{
ALOGV("isAudioMultipleOffloadEnable enter");
retrieveConfigs();
return mConfigs.audio_offload_multiple_enabled;
}
bool APMConfigHelper::isVoiceDSDConcDisabled()
{
ALOGV("isVoiceDSDConcDisabled enter");
retrieveConfigs();
return mConfigs.voice_dsd_playback_conc_disabled;
}
bool APMConfigHelper::isSVAConcEnabled()
{
ALOGV("isSVAConcEnabled enter");
retrieveConfigs();
return mConfigs.audio_sva_conc_enabled;
}
bool APMConfigHelper::isVAConcEnabled()
{
ALOGV("isVAConcEnabled enter");
retrieveConfigs();
return mConfigs.audio_va_concurrency_enabled;
}
bool APMConfigHelper::isRecPlayConcDisabled()
{
ALOGV("isRecPlayConcDisabled enter");
retrieveConfigs();
return mConfigs.audio_rec_playback_conc_disabled;
}
bool APMConfigHelper::useVoicePathForPCMVOIP()
{
ALOGV("useVoicePathForPCMVOIP enter");
retrieveConfigs();
return mConfigs.voice_path_for_pcm_voip;
}
bool APMConfigHelper::isVoicePlayConcDisabled()
{
ALOGV("isVoicePlayConcDisabled enter");
retrieveConfigs();
return mConfigs.voice_playback_conc_disabled;
}
bool APMConfigHelper::isVoiceRecConcDisabled()
{
ALOGV("isVoiceRecConcDisabled enter");
retrieveConfigs();
return mConfigs.voice_record_conc_disabled;
}
bool APMConfigHelper::isVoiceVOIPConcDisabled()
{
ALOGV("isVoiceVOIPConcDisabled enter");
retrieveConfigs();
return mConfigs.voice_voip_conc_disabled;
}
uint32_t APMConfigHelper::getAudioOffloadMinDuration()
{
ALOGV("getAudioOffloadMinDuration enter");
retrieveConfigs();
return mConfigs.audio_offload_min_duration_secs;
}
string APMConfigHelper::getVoiceConcFallbackPath()
{
ALOGV("getVoiceConcFallbackPath enter");
retrieveConfigs();
return mConfigs.voice_conc_fallbackpath;
}
bool APMConfigHelper::isHDMISpkEnabled()
{
ALOGV("isHDMISpkEnabled enter");
retrieveConfigs();
return mConfigs.audio_extn_hdmi_spk_enabled;
}
bool APMConfigHelper::isExtnFormatsEnabled()
{
ALOGV("isExtnFormatsEnabled enter");
retrieveConfigs();
return mConfigs.audio_extn_formats_enabled;
}
bool APMConfigHelper::isAFEProxyEnabled()
{
ALOGV("isAFEProxyEnabled enter");
retrieveConfigs();
return mConfigs.audio_extn_afe_proxy_enabled;
}
bool APMConfigHelper::isCompressVOIPEnabled()
{
ALOGV("isCompressVOIPEnabled enter");
retrieveConfigs();
return mConfigs.compress_voip_enabled;
}
bool APMConfigHelper::isFMPowerOptEnabled()
{
ALOGV("isFMPowerOptEnabled enter");
retrieveConfigs();
return mConfigs.fm_power_opt;
}
bool APMConfigHelper::isVoiceConcEnabled()
{
ALOGV("isVoiceConcEnabled enter");
retrieveConfigs();
return mConfigs.voice_concurrency;
}
bool APMConfigHelper::isRecPlayConcEnabled()
{
ALOGV("isRecPlayConcEnabled enter");
retrieveConfigs();
return mConfigs.record_play_concurrency;
}
bool APMConfigHelper::useXMLAudioPolicyConf()
{
ALOGV("useXMLAudioPolicyConf enter");
retrieveConfigs();
return mConfigs.use_xml_audio_policy_conf;
}
}

View File

@@ -0,0 +1,147 @@
/*
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Changes from Qualcomm Innovation Center are provided under the following license:
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted (subject to the limitations in the
* disclaimer below) provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Qualcomm Innovation Center, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
* GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
* HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _APM_CONFIG_HELPER_H_
#define _APM_CONFIG_HELPER_H_
#include <string>
#include <utils/String8.h>
#include <media/stagefright/foundation/ABase.h>
#include <utils/RefBase.h>
namespace android {
using namespace std;
struct ApmValues {
bool audio_offload_video;
bool audio_offload_disable;
bool audio_deepbuffer_media;
bool audio_av_streaming_offload_enable;
bool audio_offload_track_enable;
bool audio_offload_multiple_enabled;
bool voice_dsd_playback_conc_disabled;
bool audio_sva_conc_enabled;
bool audio_va_concurrency_enabled;
bool audio_rec_playback_conc_disabled;
bool voice_path_for_pcm_voip;
bool voice_playback_conc_disabled;
bool voice_record_conc_disabled;
bool voice_voip_conc_disabled;
uint32_t audio_offload_min_duration_secs;
string voice_conc_fallbackpath;
bool audio_extn_hdmi_spk_enabled;
bool audio_extn_formats_enabled;
bool audio_extn_afe_proxy_enabled;
bool compress_voip_enabled;
bool fm_power_opt;
bool voice_concurrency;
bool record_play_concurrency;
bool use_xml_audio_policy_conf;
};
class APMConfigHelper : public RefBase {
public:
APMConfigHelper();
virtual ~APMConfigHelper() {};
/* member functions to query settigns */
bool isAudioOffloadVideoEnabled();
bool isAudioOffloadDisabled();
bool isAudioDeepbufferMediaEnabled();
bool isAVStreamingOffloadEnabled();
bool isAudioTrackOffloadEnabled();
bool isAudioMultipleOffloadEnable();
bool isVoiceDSDConcDisabled();
bool isSVAConcEnabled();
bool isVAConcEnabled();
bool isRecPlayConcDisabled();
bool useVoicePathForPCMVOIP();
bool isVoicePlayConcDisabled();
bool isVoiceRecConcDisabled();
bool isVoiceVOIPConcDisabled();
uint32_t getAudioOffloadMinDuration();
string getVoiceConcFallbackPath();
bool isHDMISpkEnabled();
bool isExtnFormatsEnabled();
bool isAFEProxyEnabled();
bool isCompressVOIPEnabled();
bool isFMPowerOptEnabled();
bool isVoiceConcEnabled();
bool isRecPlayConcEnabled();
bool useXMLAudioPolicyConf();
void dump(String8 *dst) const;
private:
inline void retrieveConfigs();
ApmValues mConfigs;
bool isRemote; // configs specified from remote
DISALLOW_EVIL_CONSTRUCTORS(APMConfigHelper);
};
}
#endif /* _APM_CONFIG_HELPER_H_ */

View File

@@ -0,0 +1,78 @@
#Diable custom APM
USE_CUSTOM_AUDIO_POLICY :=0
ifneq ($(USE_LEGACY_AUDIO_POLICY), 1)
ifeq ($(USE_CUSTOM_AUDIO_POLICY), 1)
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := AudioPolicyManager.cpp \
APMConfigHelper.cpp
LOCAL_C_INCLUDES := $(TOPDIR)frameworks/av/services \
$(TOPDIR)frameworks/av/services/audioflinger \
$(call include-path-for, audio-effects) \
$(call include-path-for, audio-utils) \
$(TOPDIR)frameworks/av/services/audiopolicy/common/include \
$(TOPDIR)frameworks/av/services/audiopolicy/engine/interface \
$(TOPDIR)frameworks/av/services/audiopolicy \
$(TOPDIR)frameworks/av/services/audiopolicy/common/managerdefinitions/include \
$(call include-path-for, avextension) \
LOCAL_HEADER_LIBRARIES := \
libaudioclient_headers \
libaudiofoundation_headers \
libbase_headers \
libmedia_headers \
libstagefright_foundation_headers
LOCAL_SHARED_LIBRARIES := \
libcutils \
libutils \
liblog \
libaudiofoundation \
libaudiopolicymanagerdefault
LOCAL_STATIC_LIBRARIES := \
libmedia_helper \
LOCAL_CFLAGS += -Wall -Werror
ifeq ($(strip $(AUDIO_FEATURE_ENABLED_VOICE_CONCURRENCY)),true)
LOCAL_CFLAGS += -DVOICE_CONCURRENCY
endif
ifeq ($(strip $(AUDIO_FEATURE_ENABLED_RECORD_PLAY_CONCURRENCY)),true)
LOCAL_CFLAGS += -DRECORD_PLAY_CONCURRENCY
endif
ifeq ($(strip $(AUDIO_FEATURE_ENABLED_EXTN_FORMATS)),true)
LOCAL_CFLAGS += -DAUDIO_EXTN_FORMATS_ENABLED
endif
ifeq ($(strip $(AUDIO_FEATURE_ENABLED_HDMI_SPK)),true)
LOCAL_CFLAGS += -DAUDIO_EXTN_HDMI_SPK_ENABLED
endif
ifeq ($(strip $(AUDIO_FEATURE_ENABLED_PROXY_DEVICE)),true)
LOCAL_CFLAGS += -DAUDIO_EXTN_AFE_PROXY_ENABLED
endif
ifeq ($(strip $(AUDIO_FEATURE_ENABLED_FM_POWER_OPT)),true)
LOCAL_CFLAGS += -DFM_POWER_OPT
endif
ifeq ($(USE_XML_AUDIO_POLICY_CONF), 1)
LOCAL_CFLAGS += -DUSE_XML_AUDIO_POLICY_CONF
endif
ifeq ($(strip $(AUDIO_FEATURE_ENABLED_COMPRESS_VOIP)),true)
LOCAL_CFLAGS += -DCOMPRESS_VOIP_ENABLED
endif
LOCAL_MODULE := libaudiopolicymanager
include $(BUILD_SHARED_LIBRARY)
endif
endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,189 @@
/*
* Copyright (c) 2013-2020 The Linux Foundation. All rights reserved.
* Not a contribution.
*
* Copyright (C) 2009 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 <audiopolicy/managerdefault/AudioPolicyManager.h>
#include <Volume.h>
#include "APMConfigHelper.h"
namespace android {
#ifndef AUDIO_EXTN_FORMATS_ENABLED
#define AUDIO_FORMAT_WMA 0x12000000UL
#define AUDIO_FORMAT_WMA_PRO 0x13000000UL
#define AUDIO_FORMAT_FLAC 0x1B000000UL
#define AUDIO_FORMAT_ALAC 0x1C000000UL
#define AUDIO_FORMAT_APE 0x1D000000UL
#endif
#define WMA_STD_NUM_FREQ 7
#define WMA_STD_NUM_CHANNELS 2
static uint32_t wmaStdSampleRateTbl[WMA_STD_NUM_FREQ] =
{
8000, 11025, 16000, 22050, 32000, 44100, 48000
};
static uint32_t wmaStdMinAvgByteRateTbl[WMA_STD_NUM_FREQ][WMA_STD_NUM_CHANNELS] =
{
{128, 12000},
{8016, 8016},
{10000, 16000},
{16016, 20008},
{20000, 24000},
{20008, 31960},
{63000, 63000}
};
static uint32_t wmaStdMaxAvgByteRateTbl[WMA_STD_NUM_FREQ][WMA_STD_NUM_CHANNELS] =
{
{8000, 12000},
{10168, 10168},
{16000, 20000},
{20008, 32048},
{20000, 48000},
{48024, 320032},
{256008, 256008}
};
#define MAX_BITRATE_WMA_PRO 1536000
#define MAX_BITRATE_WMA_LOSSLESS 1152000
#ifndef AAC_ADTS_OFFLOAD_ENABLED
#define AUDIO_FORMAT_AAC_ADTS 0x1E000000UL
#endif
#ifndef AUDIO_EXTN_AFE_PROXY_ENABLED
#define AUDIO_DEVICE_OUT_PROXY 0x1000000
#endif
// ----------------------------------------------------------------------------
class AudioPolicyManagerCustom: public AudioPolicyManager
{
public:
AudioPolicyManagerCustom(AudioPolicyClientInterface *clientInterface);
virtual ~AudioPolicyManagerCustom() {}
status_t setDeviceConnectionStateInt(audio_devices_t device,
audio_policy_dev_state_t state,
const char *device_address,
const char *device_name,
audio_format_t encodedFormat);
virtual void setPhoneState(audio_mode_t state);
virtual void setForceUse(audio_policy_force_use_t usage,
audio_policy_forced_cfg_t config);
virtual bool isOffloadSupported(const audio_offload_info_t& offloadInfo);
virtual status_t getInputForAttr(const audio_attributes_t *attr,
audio_io_handle_t *input,
audio_unique_id_t riid,
audio_session_t session,
uid_t uid,
const audio_config_base_t *config,
audio_input_flags_t flags,
audio_port_handle_t *selectedDeviceId,
input_type_t *inputType,
audio_port_handle_t *portId);
/* count active capture sessions (that are not sound trigger) using one of
the specified devices. Ignore devices if AUDIO_DEVICE_IN_DEFAULT is passed */
uint32_t activeNonSoundTriggerInputsCountOnDevices(
audio_devices_t devices = AUDIO_DEVICE_IN_DEFAULT) const;
// indicates to the audio policy manager that the input starts being used.
virtual status_t startInput(audio_port_handle_t portId);
// indicates to the audio policy manager that the input stops being used.
virtual status_t stopInput(audio_port_handle_t portId);
status_t dump(int fd) override;
static sp<APMConfigHelper> mApmConfigs;
protected:
// check that volume change is permitted, compute and send new volume to audio hardware
virtual status_t checkAndSetVolume(IVolumeCurves &curves,
VolumeSource volumeSource, int index,
const sp<AudioOutputDescriptor>& outputDesc,
DeviceTypeSet deviceTypes,
int delayMs = 0, bool force = false);
// avoid invalidation for active music stream on previous outputs
// which is supported on the new device.
bool isInvalidationOfMusicStreamNeeded(const audio_attributes_t &attr);
// Must be called before updateDevicesAndOutputs()
void checkOutputForAttributes(const audio_attributes_t &attr);
// if argument "device" is different from AUDIO_DEVICE_NONE, startSource() will force
// the re-evaluation of the output device.
status_t startSource(const sp<SwAudioOutputDescriptor>& outputDesc,
const sp<TrackClientDescriptor>& client,
uint32_t *delayMs);
status_t stopSource(const sp<SwAudioOutputDescriptor>& outputDesc,
const sp<TrackClientDescriptor>& client);
// event is one of STARTING_OUTPUT, STARTING_BEACON, STOPPING_OUTPUT, STOPPING_BEACON
// returns 0 if no mute/unmute event happened, the largest latency of the device where
// the mute/unmute happened
uint32_t handleEventForBeacon(int){return 0;}
uint32_t setBeaconMute(bool){return 0;}
static audio_output_flags_t getFallBackPath();
int mFallBackflag;
//parameter indicates of HDMI speakers disabled
bool mHdmiAudioDisabled;
//parameter indicates if HDMI plug in/out detected
bool mHdmiAudioEvent;
private:
// internal method to return the output handle for the given device and format
audio_io_handle_t getOutputForDevices(
const DeviceVector &devices,
audio_session_t session,
audio_stream_type_t stream,
const audio_config_t *config,
audio_output_flags_t *flags,
bool forceMutingHaptic = false);
// internal method to fill offload info in case of Direct PCM
status_t getOutputForAttr(const audio_attributes_t *attr,
audio_io_handle_t *output,
audio_session_t session,
audio_stream_type_t *stream,
uid_t uid,
const audio_config_t *config,
audio_output_flags_t *flags,
audio_port_handle_t *selectedDeviceId,
audio_port_handle_t *portId,
std::vector<audio_io_handle_t> *secondaryOutputs,
output_type_t *outputType);
// internal method to query hal for whether display-port is connected
// and can be used for voip/voice call
void chkDpConnAndAllowedForVoice();
// Used for voip + voice concurrency usecase
int mPrevPhoneState;
int mvoice_call_state;
// Used for record + playback concurrency
bool mIsInputRequestOnProgress;
};
};

View File

@@ -0,0 +1,30 @@
sourceFiles = ["cryptfs_hw.cpp"]
commonSharedLibraries = [
"libcutils",
"libutils",
"libdl",
"libhardware",
"liblog",
"libhwbinder",
"libhidlbase",
"libhidltransport",
"libbinder",
"vendor.qti.hardware.cryptfshw@1.0",
]
cc_library_shared {
name: "libcryptfs_hw",
header_libs: ["libhardware_headers",
"libcryptfshw_hidl_headers",],
srcs: sourceFiles,
shared_libs: commonSharedLibraries,
owner: "qti",
system_ext_specific: true,
}
cc_library_headers {
name: "libcryptfs_hw_headers",
export_include_dirs: ["."],
}

View File

@@ -0,0 +1,31 @@
Copyright (c) 2014, 2017, The Linux Foundation. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted (subject to the limitations in the
disclaimer below) provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of The Linux Foundation nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -0,0 +1,126 @@
/* Copyright (c) 2014, 2017, 2019 The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include "cutils/log.h"
#include "cutils/properties.h"
#include "cryptfs_hw.h"
#include "CryptfsHw.h"
using android::sp;
using vendor::qti::hardware::cryptfshw::V1_0::ICryptfsHw;
using ::android::hardware::Return;
using ::android::hardware::Void;
#define QTI_ICE_STORAGE_UFS 1
#define QTI_ICE_STORAGE_SDCC 2
int set_ice_param(int flag)
{
int rc = -1;
sp<ICryptfsHw> cryptfshwService = ICryptfsHw::getService();
if (cryptfshwService.get() == nullptr) {
ALOGE("Failed to get Cryptfshw service");
return rc;
}
rc = cryptfshwService->setIceParam(flag);
return rc;
}
int set_hw_device_encryption_key(const char* passwd, const char* enc_mode)
{
int rc = -1;
sp<ICryptfsHw> cryptfshwService = ICryptfsHw::getService();
if (cryptfshwService.get() == nullptr) {
ALOGE("Failed to get Cryptfshw service");
return rc;
}
rc = cryptfshwService->setKey(passwd, enc_mode);
return rc;
}
int update_hw_device_encryption_key(const char* oldpw, const char* newpw, const char* enc_mode)
{
int rc = -1;
sp<ICryptfsHw> cryptfshwService = ICryptfsHw::getService();
if (cryptfshwService.get() == nullptr) {
ALOGE("Failed to get Cryptfshw service");
return rc;
}
rc = cryptfshwService->updateKey(oldpw, newpw, enc_mode);
return rc;
}
unsigned int is_hw_disk_encryption(const char* encryption_mode)
{
int ret = 0;
if(encryption_mode) {
if (!strcmp(encryption_mode, "aes-xts")) {
SLOGD("HW based disk encryption is enabled \n");
ret = 1;
}
}
return ret;
}
int is_ice_enabled(void)
{
char prop_storage[PATH_MAX];
int storage_type = 0;
if (property_get("ro.boot.bootdevice", prop_storage, "")) {
if (strstr(prop_storage, "ufs")) {
/* All UFS based devices has ICE in it. So we dont need
* to check if corresponding device exists or not
*/
storage_type = QTI_ICE_STORAGE_UFS;
} else if (strstr(prop_storage, "sdhc")) {
if (access("/dev/icesdcc", F_OK) != -1)
storage_type = QTI_ICE_STORAGE_SDCC;
}
}
return storage_type;
}
int clear_hw_device_encryption_key()
{
int rc = -1;
sp<ICryptfsHw> cryptfshwService = ICryptfsHw::getService();
if (cryptfshwService.get() == nullptr) {
ALOGE("Failed to get Cryptfshw service");
return rc;
}
rc = cryptfshwService->clearKey();
return rc;
}

View File

@@ -0,0 +1,52 @@
/* Copyright (c) 2014, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __CRYPTFS_HW_H_
#define __CRYPTFS_HW_H_
#ifdef __cplusplus
extern "C" {
#endif
/*This is equivalent of MAX_CRYPTO_TYPE_NAME_LEN*/
#define CRYPTO_ALGO_LENGTH 64
#define START_ENC 0x1
#define START_ENCDEC 0x3
int set_hw_device_encryption_key(const char*, const char*);
int update_hw_device_encryption_key(const char*, const char*, const char*);
int clear_hw_device_encryption_key();
unsigned int is_hw_disk_encryption(const char*);
int is_ice_enabled(void);
inline int should_use_keymaster(){return 1;}
int set_ice_param(int flag);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1 @@
include $(call all-subdir-makefiles)

View File

@@ -0,0 +1,2 @@
include $(call all-subdir-makefiles)

View File

@@ -0,0 +1,15 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := sockev_cli.c
LOCAL_CFLAGS := -Wall -Werror
LOCAL_C_INCLUDES := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
LOCAL_ADDITIONAL_DEPENDENCIES := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
LOCAL_CLANG := true
LOCAL_MODULE := sockev
LOCAL_MODULE_TAGS := optional
include $(BUILD_EXECUTABLE)

View File

@@ -0,0 +1,96 @@
/******************************************************************************
S O C K E V _ C L I . C
Copyright (c) 2013, The Linux Foundation. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of The Linux Foundation nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
******************************************************************************/
/******************************************************************************
@file sockev_cli.c
@brief command line test utility to receive sockev netlink messages.
******************************************************************************/
#include <sys/socket.h>
#include <linux/netlink.h>
#include <linux/sockev.h>
#include <stdlib.h>
#include <stdio.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#define SOCKEVCLI_ERROR -1
int main(void)
{
int skfd, rc;
socklen_t addrlen;
struct sockaddr_nl my_addr, src_addr;
struct nlmsghdr *nlh = NULL;
struct sknlsockevmsg *msg;
nlh = (struct nlmsghdr *)
malloc(NLMSG_SPACE(sizeof(struct sknlsockevmsg) + 16));
if (!nlh) {
fprintf(stderr, "malloc() failed\n");
return SOCKEVCLI_ERROR;
}
skfd = socket(AF_NETLINK, SOCK_RAW, NETLINK_SOCKEV);
if (skfd < 0) {
fprintf(stderr, "nl_open_sock: socket failed\n");
return SOCKEVCLI_ERROR;
}
memset(&my_addr, 0, sizeof(struct sockaddr_nl));
my_addr.nl_family = AF_NETLINK;
my_addr.nl_pid = getpid();
my_addr.nl_groups = SKNLGRP_SOCKEV;
rc = bind(skfd, (struct sockaddr *)&my_addr,
sizeof(struct sockaddr_nl));
if (rc < 0) {
fprintf(stderr, "nl_open_sock: bind failed\n");
close(skfd);
return SOCKEVCLI_ERROR;
}
while (1) {
recvfrom(skfd, nlh, sizeof(struct sknlsockevmsg) + 16, 0,
(const struct sockaddr *)&src_addr, &addrlen);
msg = NLMSG_DATA(nlh);
printf("----------------------------\n");
printf("pid:\t%d\n", msg->pid);
printf("event:\t%s\n", msg->event);
printf("skfamily:\t0x%04X\n", msg->skfamily);
printf("skstate:\t%03d\n", msg->skstate);
printf("skprotocol:\t%03d\n", msg->skprotocol);
printf("sktype:\t0x%04X\n", msg->sktype);
printf("skflags:\t0x%016llX\n", msg->skflags);
}
return 0;
}

View File

@@ -0,0 +1,14 @@
---
Language: Cpp
BasedOnStyle: Google
Standard : C++11
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AllowShortFunctionsOnASingleLine: Inline
AllowShortBlocksOnASingleLine: false
ColumnLimit: 100
ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth: 4
DerivePointerAlignment: false
PointerAlignment: Right
#ReflowComments: false

View File

@@ -0,0 +1,27 @@
PRODUCT_PACKAGES += libdisplayconfig.system \
libgralloc.system.qti \
libdrm \
liblayerext.qti \
libsmomoconfig.qti \
libcomposerextn.qti \
libdisplayconfig.system.qti
SOONG_CONFIG_NAMESPACES += qtidisplaycommonsys
# Soong Keys
SOONG_CONFIG_qtidisplaycommonsys := displayextension composer3ext
# Soong Values
# displayextension controls global compile time disablement of SF extensions
SOONG_CONFIG_qtidisplaycommonsys_displayextension := false
# Variables can be added here on a transient basis to merge
# features that are not yet consumed in keystone
# Once the feature has been consumed, these can be removed
# and the feature can be enabled/disabled at run time via android
# properties
SOONG_CONFIG_qtidisplaycommonsys_composer3ext := false
ifeq ($(call is-vendor-board-platform,QCOM),true)
SOONG_CONFIG_qtidisplaycommonsys_displayextension := true
SOONG_CONFIG_qtidisplaycommonsys_composer3ext := true
endif

View File

@@ -0,0 +1,22 @@
cc_library_shared {
name: "libgralloc.system.qti",
system_ext_specific: true,
cflags: [
"-Wno-sign-conversion",
"-DLOG_TAG=\"qtigralloc\"",
],
shared_libs: [
"liblog",
"libcutils",
"libutils",
"libgralloctypes",
"libhidlbase",
"libhardware",
"android.hardware.graphics.mapper@4.0",
],
srcs: ["QtiGralloc.cpp"],
header_libs: ["display_intf_headers"],
}

View File

@@ -0,0 +1,583 @@
/*
* Copyright (c) 2020, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Changes from Qualcomm Innovation Center are provided under the following license:
*
* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
* SPDX-License-Identifier: BSD-3-Clause-Clear
*/
#include "QtiGralloc.h"
#include <log/log.h>
#include "color_extensions.h"
namespace qtigralloc {
using android::hardware::graphics::mapper::V4_0::IMapper;
static sp<IMapper> getInstance() {
static sp<IMapper> mapper = IMapper::getService();
return mapper;
}
Error decodeMetadataState(hidl_vec<uint8_t> &in, bool *out) {
if (!in.size() || !out) {
return Error::BAD_VALUE;
}
memcpy(out, in.data(), METADATA_SET_SIZE);
return Error::NONE;
}
Error encodeMetadataState(bool *in, hidl_vec<uint8_t> *out) {
if (!in || !out) {
return Error::BAD_VALUE;
}
out->resize(sizeof(bool) * METADATA_SET_SIZE);
memcpy(out->data(), in, sizeof(bool) * METADATA_SET_SIZE);
return Error::NONE;
}
Error decodeColorMetadata(hidl_vec<uint8_t> &in, ColorMetaData *out) {
if (!in.size() || !out) {
return Error::BAD_VALUE;
}
memcpy(out, in.data(), sizeof(ColorMetaData));
return Error::NONE;
}
Error encodeColorMetadata(ColorMetaData &in, hidl_vec<uint8_t> *out) {
if (!out) {
return Error::BAD_VALUE;
}
out->resize(sizeof(ColorMetaData));
memcpy(out->data(), &in, sizeof(ColorMetaData));
return Error::NONE;
}
// decode the raw graphics metadata from bytestream and store it in 'data' member of
// GraphicsMetadata struct during mapper->set call, 'size' member is unused.
Error decodeGraphicsMetadata(hidl_vec<uint8_t> &in, GraphicsMetadata *out) {
if (!in.size() || !out) {
return Error::BAD_VALUE;
}
memcpy(&(out->data), in.data(), GRAPHICS_METADATA_SIZE_IN_BYTES);
return Error::NONE;
}
// encode only 'data' member of GraphicsMetadata struct for retrieval of
// graphics metadata during mapper->get call
Error encodeGraphicsMetadata(GraphicsMetadata &in, hidl_vec<uint8_t> *out) {
if (!out) {
return Error::BAD_VALUE;
}
out->resize(GRAPHICS_METADATA_SIZE_IN_BYTES);
memcpy(out->data(), &(in.data), GRAPHICS_METADATA_SIZE_IN_BYTES);
return Error::NONE;
}
// decode the raw graphics metadata from bytestream before presenting it to caller
Error decodeGraphicsMetadataRaw(hidl_vec<uint8_t> &in, void *out) {
if (!in.size() || !out) {
return Error::BAD_VALUE;
}
memcpy(out, in.data(), GRAPHICS_METADATA_SIZE_IN_BYTES);
return Error::NONE;
}
// encode the raw graphics metadata in bytestream before calling mapper->set
Error encodeGraphicsMetadataRaw(void *in, hidl_vec<uint8_t> *out) {
if (!in || !out) {
return Error::BAD_VALUE;
}
out->resize(GRAPHICS_METADATA_SIZE_IN_BYTES);
memcpy(out->data(), in, GRAPHICS_METADATA_SIZE_IN_BYTES);
return Error::NONE;
}
Error decodeUBWCStats(hidl_vec<uint8_t> &in, UBWCStats *out) {
if (!in.size() || !out) {
return Error::BAD_VALUE;
}
memcpy(out, in.data(), UBWC_STATS_ARRAY_SIZE * sizeof(UBWCStats));
return Error::NONE;
}
Error encodeUBWCStats(UBWCStats *in, hidl_vec<uint8_t> *out) {
if (!in || !out) {
return Error::BAD_VALUE;
}
out->resize(UBWC_STATS_ARRAY_SIZE * sizeof(UBWCStats));
memcpy(out->data(), in, UBWC_STATS_ARRAY_SIZE * sizeof(UBWCStats));
return Error::NONE;
}
Error decodeCVPMetadata(hidl_vec<uint8_t> &in, CVPMetadata *out) {
if (!in.size() || !out) {
return Error::BAD_VALUE;
}
memcpy(out, in.data(), sizeof(CVPMetadata));
return Error::NONE;
}
Error encodeCVPMetadata(CVPMetadata &in, hidl_vec<uint8_t> *out) {
if (!out) {
return Error::BAD_VALUE;
}
out->resize(sizeof(CVPMetadata));
memcpy(out->data(), &in, sizeof(CVPMetadata));
return Error::NONE;
}
Error decodeVideoHistogramMetadata(hidl_vec<uint8_t> &in, VideoHistogramMetadata *out) {
if (!in.size() || !out) {
return Error::BAD_VALUE;
}
memcpy(out, in.data(), sizeof(VideoHistogramMetadata));
return Error::NONE;
}
Error encodeVideoHistogramMetadata(VideoHistogramMetadata &in, hidl_vec<uint8_t> *out) {
if (!out) {
return Error::BAD_VALUE;
}
out->resize(sizeof(VideoHistogramMetadata));
memcpy(out->data(), &in, sizeof(VideoHistogramMetadata));
return Error::NONE;
}
Error decodeVideoTranscodeStatsMetadata(hidl_vec<uint8_t> &in, VideoTranscodeStatsMetadata *out) {
if (!in.size() || !out) {
return Error::BAD_VALUE;
}
memcpy(out, in.data(), sizeof(VideoTranscodeStatsMetadata));
return Error::NONE;
}
Error encodeVideoTranscodeStatsMetadata(VideoTranscodeStatsMetadata &in, hidl_vec<uint8_t> *out) {
if (!out) {
return Error::BAD_VALUE;
}
out->resize(sizeof(VideoTranscodeStatsMetadata));
memcpy(out->data(), &in, sizeof(VideoTranscodeStatsMetadata));
return Error::NONE;
}
Error decodeVideoTimestampInfo(hidl_vec<uint8_t> &in, VideoTimestampInfo *out) {
if (!in.size() || !out) {
return Error::BAD_VALUE;
}
memcpy(out, in.data(), sizeof(VideoTimestampInfo));
return Error::NONE;
}
Error encodeVideoTimestampInfo(VideoTimestampInfo &in, hidl_vec<uint8_t> *out) {
if (!out) {
return Error::BAD_VALUE;
}
out->resize(sizeof(VideoTimestampInfo));
memcpy(out->data(), &in, sizeof(VideoTimestampInfo));
return Error::NONE;
}
Error decodeYUVPlaneInfoMetadata(hidl_vec<uint8_t> &in, qti_ycbcr *out) {
if (!in.size() || !out) {
return Error::BAD_VALUE;
}
qti_ycbcr *p = reinterpret_cast<qti_ycbcr *>(in.data());
memcpy(out, in.data(), (YCBCR_LAYOUT_ARRAY_SIZE * sizeof(qti_ycbcr)));
return Error::NONE;
}
Error encodeYUVPlaneInfoMetadata(qti_ycbcr *in, hidl_vec<uint8_t> *out) {
if (!out) {
return Error::BAD_VALUE;
}
out->resize(YCBCR_LAYOUT_ARRAY_SIZE * sizeof(qti_ycbcr));
memcpy(out->data(), in, YCBCR_LAYOUT_ARRAY_SIZE * sizeof(qti_ycbcr));
return Error::NONE;
}
Error decodeCustomContentMetadata(hidl_vec<uint8_t> &in, void *out) {
static size_t target_size = sizeof(CustomContentMetadata);
if (in.size() != target_size || !out) {
return Error::BAD_VALUE;
}
CustomContentMetadata *c_md_in = reinterpret_cast<CustomContentMetadata *>(in.data());
CustomContentMetadata *c_md_out = reinterpret_cast<CustomContentMetadata *>(out);
if (c_md_in->size > CUSTOM_METADATA_SIZE_BYTES) {
return Error::BAD_VALUE;
}
c_md_out->size = c_md_in->size;
memcpy(c_md_out->metadataPayload, c_md_in->metadataPayload, c_md_in->size);
return Error::NONE;
}
Error encodeCustomContentMetadata(const void *in, hidl_vec<uint8_t> *out) {
static size_t target_size = sizeof(CustomContentMetadata);
if (!in || !out) {
return Error::BAD_VALUE;
}
out->resize(target_size);
memcpy(out->data(), in, target_size);
return Error::NONE;
}
MetadataType getMetadataType(uint32_t in) {
switch (in) {
case QTI_VT_TIMESTAMP:
return MetadataType_VTTimestamp;
case QTI_VIDEO_PERF_MODE:
return MetadataType_VideoPerfMode;
case QTI_LINEAR_FORMAT:
return MetadataType_LinearFormat;
case QTI_SINGLE_BUFFER_MODE:
return MetadataType_SingleBufferMode;
case QTI_PP_PARAM_INTERLACED:
return MetadataType_PPParamInterlaced;
case QTI_MAP_SECURE_BUFFER:
return MetadataType_MapSecureBuffer;
case QTI_COLOR_METADATA:
return MetadataType_ColorMetadata;
case QTI_GRAPHICS_METADATA:
return MetadataType_GraphicsMetadata;
case QTI_UBWC_CR_STATS_INFO:
return MetadataType_UBWCCRStatsInfo;
case QTI_REFRESH_RATE:
return MetadataType_RefreshRate;
case QTI_CVP_METADATA:
return MetadataType_CVPMetadata;
case QTI_VIDEO_HISTOGRAM_STATS:
return MetadataType_VideoHistogramStats;
case QTI_VIDEO_TRANSCODE_STATS:
return MetadataType_VideoTranscodeStats;
case QTI_VIDEO_TS_INFO:
return MetadataType_VideoTimestampInfo;
case QTI_FD:
return MetadataType_FD;
case QTI_PRIVATE_FLAGS:
return MetadataType_PrivateFlags;
case QTI_ALIGNED_WIDTH_IN_PIXELS:
return MetadataType_AlignedWidthInPixels;
case QTI_ALIGNED_HEIGHT_IN_PIXELS:
return MetadataType_AlignedHeightInPixels;
case QTI_STANDARD_METADATA_STATUS:
return MetadataType_StandardMetadataStatus;
case QTI_VENDOR_METADATA_STATUS:
return MetadataType_VendorMetadataStatus;
case QTI_BUFFER_TYPE:
return MetadataType_BufferType;
case QTI_CUSTOM_DIMENSIONS_STRIDE:
return MetadataType_CustomDimensionsStride;
case QTI_CUSTOM_DIMENSIONS_HEIGHT:
return MetadataType_CustomDimensionsHeight;
case QTI_RGB_DATA_ADDRESS:
return MetadataType_RgbDataAddress;
case QTI_COLORSPACE:
return MetadataType_ColorSpace;
case QTI_YUV_PLANE_INFO:
return MetadataType_YuvPlaneInfo;
case QTI_TIMED_RENDERING:
return MetadataType_TimedRendering;
case QTI_CUSTOM_CONTENT_METADATA:
return MetadataType_CustomContentMetadata;
case QTI_BUFFER_DEQUEUE_DURATION:
return MetadataType_BufferDequeueDuration;
default:
return MetadataType_Invalid;
}
}
Error get(void *buffer, uint32_t type, void *param) {
hidl_vec<uint8_t> bytestream;
sp<IMapper> mapper = getInstance();
MetadataType metadata_type = getMetadataType(type);
if (metadata_type == MetadataType_Invalid) {
param = nullptr;
return Error::UNSUPPORTED;
}
auto err = Error::UNSUPPORTED;
mapper->get(buffer, metadata_type, [&](const auto &tmpError, const auto &tmpByteStream) {
err = tmpError;
bytestream = tmpByteStream;
});
if (err != Error::NONE) {
return err;
}
switch (type) {
case QTI_VT_TIMESTAMP:
err = static_cast<Error>(android::gralloc4::decodeUint64(
qtigralloc::MetadataType_VTTimestamp, bytestream, reinterpret_cast<uint64_t *>(param)));
break;
case QTI_VIDEO_PERF_MODE:
err = static_cast<Error>(android::gralloc4::decodeUint32(
qtigralloc::MetadataType_VideoPerfMode, bytestream, reinterpret_cast<uint32_t *>(param)));
break;
case QTI_LINEAR_FORMAT:
err = static_cast<Error>(android::gralloc4::decodeUint32(
qtigralloc::MetadataType_LinearFormat, bytestream, reinterpret_cast<uint32_t *>(param)));
break;
case QTI_SINGLE_BUFFER_MODE:
err = static_cast<Error>(
android::gralloc4::decodeUint32(qtigralloc::MetadataType_SingleBufferMode, bytestream,
reinterpret_cast<uint32_t *>(param)));
break;
case QTI_PP_PARAM_INTERLACED:
err = static_cast<Error>(
android::gralloc4::decodeInt32(qtigralloc::MetadataType_PPParamInterlaced, bytestream,
reinterpret_cast<int32_t *>(param)));
break;
case QTI_MAP_SECURE_BUFFER:
err = static_cast<Error>(
android::gralloc4::decodeInt32(qtigralloc::MetadataType_MapSecureBuffer, bytestream,
reinterpret_cast<int32_t *>(param)));
break;
case QTI_COLOR_METADATA:
err = decodeColorMetadata(bytestream, reinterpret_cast<ColorMetaData *>(param));
break;
case QTI_GRAPHICS_METADATA:
err = decodeGraphicsMetadataRaw(bytestream, param);
break;
case QTI_UBWC_CR_STATS_INFO:
err = decodeUBWCStats(bytestream, reinterpret_cast<UBWCStats *>(param));
break;
case QTI_REFRESH_RATE:
err = static_cast<Error>(android::gralloc4::decodeFloat(
qtigralloc::MetadataType_RefreshRate, bytestream, reinterpret_cast<float *>(param)));
break;
case QTI_CVP_METADATA:
err = decodeCVPMetadata(bytestream, reinterpret_cast<CVPMetadata *>(param));
break;
case QTI_VIDEO_HISTOGRAM_STATS:
err = decodeVideoHistogramMetadata(bytestream,
reinterpret_cast<VideoHistogramMetadata *>(param));
break;
case QTI_VIDEO_TRANSCODE_STATS:
err = decodeVideoTranscodeStatsMetadata(bytestream,
reinterpret_cast<VideoTranscodeStatsMetadata *>(param));
break;
case QTI_VIDEO_TS_INFO:
err = decodeVideoTimestampInfo(bytestream, reinterpret_cast<VideoTimestampInfo *>(param));
break;
case QTI_FD:
err = static_cast<Error>(android::gralloc4::decodeInt32(
qtigralloc::MetadataType_FD, bytestream, reinterpret_cast<int32_t *>(param)));
break;
case QTI_PRIVATE_FLAGS:
err = static_cast<Error>(android::gralloc4::decodeInt32(
qtigralloc::MetadataType_PrivateFlags, bytestream, reinterpret_cast<int32_t *>(param)));
break;
case QTI_ALIGNED_WIDTH_IN_PIXELS:
err = static_cast<Error>(
android::gralloc4::decodeUint32(qtigralloc::MetadataType_AlignedWidthInPixels, bytestream,
reinterpret_cast<uint32_t *>(param)));
break;
case QTI_ALIGNED_HEIGHT_IN_PIXELS:
err = static_cast<Error>(
android::gralloc4::decodeUint32(qtigralloc::MetadataType_AlignedHeightInPixels,
bytestream, reinterpret_cast<uint32_t *>(param)));
break;
case QTI_STANDARD_METADATA_STATUS:
case QTI_VENDOR_METADATA_STATUS:
err = decodeMetadataState(bytestream, reinterpret_cast<bool *>(param));
break;
case QTI_BUFFER_TYPE:
err = static_cast<Error>(android::gralloc4::decodeUint32(
qtigralloc::MetadataType_BufferType, bytestream, reinterpret_cast<uint32_t *>(param)));
break;
case QTI_CUSTOM_DIMENSIONS_STRIDE:
err = static_cast<Error>(
android::gralloc4::decodeUint32(qtigralloc::MetadataType_CustomDimensionsStride,
bytestream, reinterpret_cast<uint32_t *>(param)));
break;
case QTI_CUSTOM_DIMENSIONS_HEIGHT:
err = static_cast<Error>(
android::gralloc4::decodeUint32(qtigralloc::MetadataType_CustomDimensionsHeight,
bytestream, reinterpret_cast<uint32_t *>(param)));
break;
case QTI_RGB_DATA_ADDRESS:
err = static_cast<Error>(
android::gralloc4::decodeUint64(qtigralloc::MetadataType_RgbDataAddress, bytestream,
reinterpret_cast<uint64_t *>(param)));
break;
case QTI_COLORSPACE:
err = static_cast<Error>(android::gralloc4::decodeUint32(
qtigralloc::MetadataType_ColorSpace, bytestream, reinterpret_cast<uint32_t *>(param)));
break;
case QTI_YUV_PLANE_INFO:
err = decodeYUVPlaneInfoMetadata(bytestream, reinterpret_cast<qti_ycbcr *>(param));
break;
case QTI_TIMED_RENDERING:
err = static_cast<Error>(android::gralloc4::decodeUint32(
qtigralloc::MetadataType_TimedRendering, bytestream, reinterpret_cast<uint32_t *>(param)));
break;
case QTI_CUSTOM_CONTENT_METADATA:
err = decodeCustomContentMetadata(bytestream, param);
break;
case QTI_BUFFER_DEQUEUE_DURATION:
err = static_cast<Error>(android::gralloc4::decodeInt64(
qtigralloc::MetadataType_BufferDequeueDuration, bytestream,
reinterpret_cast<int64_t *>(param)));
break;
default:
param = nullptr;
return Error::UNSUPPORTED;
}
return err;
}
Error set(void *buffer, uint32_t type, void *param) {
hidl_vec<uint8_t> bytestream;
sp<IMapper> mapper = getInstance();
Error err = Error::UNSUPPORTED;
MetadataType metadata_type = getMetadataType(type);
if (metadata_type == MetadataType_Invalid) {
return err;
}
switch (type) {
case QTI_VT_TIMESTAMP:
err = static_cast<Error>(android::gralloc4::encodeUint64(
qtigralloc::MetadataType_VTTimestamp, *reinterpret_cast<uint64_t *>(param), &bytestream));
break;
case QTI_VIDEO_PERF_MODE:
err = static_cast<Error>(
android::gralloc4::encodeUint32(qtigralloc::MetadataType_VideoPerfMode,
*reinterpret_cast<uint32_t *>(param), &bytestream));
break;
case QTI_LINEAR_FORMAT:
err = static_cast<Error>(
android::gralloc4::encodeUint32(qtigralloc::MetadataType_LinearFormat,
*reinterpret_cast<uint32_t *>(param), &bytestream));
break;
case QTI_SINGLE_BUFFER_MODE:
err = static_cast<Error>(
android::gralloc4::encodeUint32(qtigralloc::MetadataType_SingleBufferMode,
*reinterpret_cast<uint32_t *>(param), &bytestream));
break;
case QTI_PP_PARAM_INTERLACED:
err = static_cast<Error>(
android::gralloc4::encodeInt32(qtigralloc::MetadataType_PPParamInterlaced,
*reinterpret_cast<int32_t *>(param), &bytestream));
break;
case QTI_MAP_SECURE_BUFFER:
err = static_cast<Error>(
android::gralloc4::encodeInt32(qtigralloc::MetadataType_MapSecureBuffer,
*reinterpret_cast<int32_t *>(param), &bytestream));
break;
case QTI_COLOR_METADATA:
err = encodeColorMetadata(*reinterpret_cast<ColorMetaData *>(param), &bytestream);
break;
case QTI_GRAPHICS_METADATA:
err = encodeGraphicsMetadataRaw(param, &bytestream);
break;
case QTI_UBWC_CR_STATS_INFO:
err = encodeUBWCStats(reinterpret_cast<UBWCStats *>(param), &bytestream);
break;
case QTI_REFRESH_RATE:
err = static_cast<Error>(android::gralloc4::encodeFloat(
qtigralloc::MetadataType_RefreshRate, *reinterpret_cast<float *>(param), &bytestream));
break;
case QTI_CVP_METADATA:
err = encodeCVPMetadata(*reinterpret_cast<CVPMetadata *>(param), &bytestream);
break;
case QTI_VIDEO_HISTOGRAM_STATS:
err = encodeVideoHistogramMetadata(*reinterpret_cast<VideoHistogramMetadata *>(param),
&bytestream);
break;
case QTI_VIDEO_TRANSCODE_STATS:
err = encodeVideoTranscodeStatsMetadata(
*reinterpret_cast<VideoTranscodeStatsMetadata *>(param), &bytestream);
break;
case QTI_VIDEO_TS_INFO:
err = encodeVideoTimestampInfo(*reinterpret_cast<VideoTimestampInfo *>(param), &bytestream);
break;
case QTI_TIMED_RENDERING:
err = static_cast<Error>(
android::gralloc4::encodeUint32(qtigralloc::MetadataType_TimedRendering,
*reinterpret_cast<uint32_t *>(param), &bytestream));
break;
case QTI_CUSTOM_CONTENT_METADATA:
err = encodeCustomContentMetadata(param, &bytestream);
break;
case QTI_BUFFER_DEQUEUE_DURATION:
err = static_cast<Error>(android::gralloc4::encodeInt64(
qtigralloc::MetadataType_BufferDequeueDuration,
*reinterpret_cast<int64_t *>(param), &bytestream));
break;
default:
param = nullptr;
return Error::UNSUPPORTED;
}
if (err != Error::NONE) {
return err;
}
return mapper->set(reinterpret_cast<void *>(buffer), metadata_type, bytestream);
}
int getMetadataState(void *buffer, uint32_t type) {
bool metadata_set[METADATA_SET_SIZE];
Error err;
if (IS_VENDOR_METADATA_TYPE(type)) {
err = get(buffer, QTI_VENDOR_METADATA_STATUS, &metadata_set);
} else {
err = get(buffer, QTI_STANDARD_METADATA_STATUS, &metadata_set);
}
if (err != Error::NONE) {
ALOGE("Unable to get metadata state");
return -1;
}
if (IS_VENDOR_METADATA_TYPE(type)) {
return metadata_set[GET_VENDOR_METADATA_STATUS_INDEX(type)];
} else if (GET_STANDARD_METADATA_STATUS_INDEX(type) < METADATA_SET_SIZE) {
return metadata_set[GET_STANDARD_METADATA_STATUS_INDEX(type)];
} else {
return -1;
}
}
} // namespace qtigralloc

View File

@@ -0,0 +1,21 @@
cc_library_shared {
name: "libqdMetaData.system",
system_ext_specific: true,
cflags: [
"-Wno-sign-conversion",
"-DLOG_TAG=\"qdmetadata\"",
"-D__QTI_DISPLAY_GRALLOC__",
],
shared_libs: [
"liblog",
"libcutils",
"libutils",
"libhidlbase",
"libgralloc.system.qti",
"libgralloctypes",
],
header_libs: ["libhardware_headers", "display_intf_headers"],
srcs: ["qdMetaData.cpp", "qd_utils.cpp"],
export_header_lib_headers: ["display_intf_headers"],
}

View File

@@ -0,0 +1,16 @@
h_sources = qdMetaData.h
cpp_sources = qdMetaData.cpp
AM_CPPFLAGS += -D__QTI_NO_GRALLOC4__
qdMetaData_includedir = $(pkgincludedir)/display
qdMetaData_include_HEADERS = $(h_sources)
lib_LTLIBRARIES = libqdMetaData.la
libqdMetaData_la_CC = @CC@
libqdMetaData_la_SOURCES = $(cpp_sources)
libqdMetaData_la_CFLAGS = $(AM_CFLAGS) -DLOG_TAG=\"DisplayMetaData\"
libqdMetaData_la_CPPFLAGS = $(AM_CPPFLAGS)
libqdMetaData_LDADD = -lcutils -llog
libqdMetaData_la_LDFLAGS = -shared -avoid-version

View File

@@ -0,0 +1,642 @@
/*
* Copyright (c) 2012-2021, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "qdMetaData.h"
#include <QtiGrallocPriv.h>
#include <errno.h>
#include <gralloc_priv.h>
#ifndef __QTI_NO_GRALLOC4__
#include <gralloctypes/Gralloc4.h>
#endif
#include <log/log.h>
#include <string.h>
#include <sys/mman.h>
#include <cinttypes>
static int colorMetaDataToColorSpace(ColorMetaData in, ColorSpace_t *out) {
if (in.colorPrimaries == ColorPrimaries_BT601_6_525 ||
in.colorPrimaries == ColorPrimaries_BT601_6_625) {
if (in.range == Range_Full) {
*out = ITU_R_601_FR;
} else {
*out = ITU_R_601;
}
} else if (in.colorPrimaries == ColorPrimaries_BT2020) {
if (in.range == Range_Full) {
*out = ITU_R_2020_FR;
} else {
*out = ITU_R_2020;
}
} else if (in.colorPrimaries == ColorPrimaries_BT709_5) {
if (in.range == Range_Full) {
*out = ITU_R_709_FR;
} else {
*out = ITU_R_709;
}
} else {
ALOGE(
"Cannot convert ColorMetaData to ColorSpace_t. "
"Primaries = %d, Range = %d",
in.colorPrimaries, in.range);
return -1;
}
return 0;
}
static int colorSpaceToColorMetadata(ColorSpace_t in, ColorMetaData *out) {
out->transfer = Transfer_sRGB;
switch (in) {
case ITU_R_601:
out->colorPrimaries = ColorPrimaries_BT601_6_525;
out->range = Range_Limited;
break;
case ITU_R_601_FR:
out->colorPrimaries = ColorPrimaries_BT601_6_525;
out->range = Range_Full;
break;
case ITU_R_709:
out->colorPrimaries = ColorPrimaries_BT709_5;
out->range = Range_Limited;
break;
case ITU_R_709_FR:
out->colorPrimaries = ColorPrimaries_BT709_5;
out->range = Range_Full;
break;
case ITU_R_2020:
out->colorPrimaries = ColorPrimaries_BT2020;
out->range = Range_Limited;
break;
case ITU_R_2020_FR:
out->colorPrimaries = ColorPrimaries_BT2020;
out->range = Range_Full;
break;
default:
ALOGE("Cannot convert ColorSpace_t %d to ColorMetaData", in);
return -1;
break;
}
return 0;
}
#ifndef __QTI_NO_GRALLOC4__
static bool getGralloc4Array(MetaData_t *metadata, int32_t paramType) {
switch (paramType) {
case SET_VT_TIMESTAMP:
return metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_VT_TIMESTAMP)];
case COLOR_METADATA:
return metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_COLOR_METADATA)];
case PP_PARAM_INTERLACED:
return metadata
->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_PP_PARAM_INTERLACED)];
case SET_VIDEO_PERF_MODE:
return metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_VIDEO_PERF_MODE)];
case SET_GRAPHICS_METADATA:
return metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_GRAPHICS_METADATA)];
case SET_UBWC_CR_STATS_INFO:
return metadata
->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_UBWC_CR_STATS_INFO)];
case UPDATE_BUFFER_GEOMETRY:
return metadata->isStandardMetadataSet[GET_STANDARD_METADATA_STATUS_INDEX(
::android::gralloc4::MetadataType_Crop.value)];
case UPDATE_REFRESH_RATE:
return metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_REFRESH_RATE)];
case UPDATE_COLOR_SPACE:
return metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_COLOR_METADATA)];
case MAP_SECURE_BUFFER:
return metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_MAP_SECURE_BUFFER)];
case LINEAR_FORMAT:
return metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_LINEAR_FORMAT)];
case SET_SINGLE_BUFFER_MODE:
return metadata
->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_SINGLE_BUFFER_MODE)];
case SET_CVP_METADATA:
return metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_CVP_METADATA)];
case SET_VIDEO_HISTOGRAM_STATS:
return metadata
->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_VIDEO_HISTOGRAM_STATS)];
case SET_VIDEO_TS_INFO:
return metadata
->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_VIDEO_TS_INFO)];
case GET_S3D_FORMAT:
return metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_S3D_FORMAT)];
default:
ALOGE("paramType %d not supported", paramType);
return false;
}
}
static void setGralloc4Array(MetaData_t *metadata, int32_t paramType, bool isSet) {
switch (paramType) {
case SET_VT_TIMESTAMP:
metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_VT_TIMESTAMP)] = isSet;
break;
case COLOR_METADATA:
metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_COLOR_METADATA)] = isSet;
break;
case PP_PARAM_INTERLACED:
metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_PP_PARAM_INTERLACED)] =
isSet;
break;
case SET_VIDEO_PERF_MODE:
metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_VIDEO_PERF_MODE)] = isSet;
break;
case SET_GRAPHICS_METADATA:
metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_GRAPHICS_METADATA)] =
isSet;
break;
case SET_UBWC_CR_STATS_INFO:
metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_UBWC_CR_STATS_INFO)] =
isSet;
break;
case UPDATE_BUFFER_GEOMETRY:
metadata->isStandardMetadataSet[GET_STANDARD_METADATA_STATUS_INDEX(
::android::gralloc4::MetadataType_Crop.value)] = isSet;
break;
case UPDATE_REFRESH_RATE:
metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_REFRESH_RATE)] = isSet;
break;
case UPDATE_COLOR_SPACE:
metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_COLOR_METADATA)] = isSet;
break;
case MAP_SECURE_BUFFER:
metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_MAP_SECURE_BUFFER)] =
isSet;
break;
case LINEAR_FORMAT:
metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_LINEAR_FORMAT)] = isSet;
break;
case SET_SINGLE_BUFFER_MODE:
metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_SINGLE_BUFFER_MODE)] =
isSet;
break;
case SET_CVP_METADATA:
metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_CVP_METADATA)] = isSet;
break;
case SET_VIDEO_HISTOGRAM_STATS:
metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_VIDEO_HISTOGRAM_STATS)] =
isSet;
break;
case SET_VIDEO_TS_INFO:
metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_VIDEO_TS_INFO)] =
isSet;
break;
case S3D_FORMAT:
metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_S3D_FORMAT)] = isSet;
break;
default:
ALOGE("paramType %d not supported in Gralloc4", paramType);
}
}
#else
static bool getGralloc4Array(MetaData_t *metadata, int32_t paramType) {
return true;
}
static void setGralloc4Array(MetaData_t *metadata, int32_t paramType, bool isSet) {
}
#endif
unsigned long getMetaDataSize() {
return static_cast<unsigned long>(ROUND_UP_PAGESIZE(sizeof(MetaData_t)));
}
// Cannot add default argument to existing function
unsigned long getMetaDataSizeWithReservedRegion(uint64_t reserved_size) {
return static_cast<unsigned long>(ROUND_UP_PAGESIZE(sizeof(MetaData_t) + reserved_size));
}
static int validateAndMap(private_handle_t* handle) {
if (private_handle_t::validate(handle)) {
ALOGE("%s: Private handle is invalid - handle:%p", __func__, handle);
return -1;
}
if (handle->fd_metadata < 0) {
// Metadata cannot be used
return -1;
}
if (!handle->base_metadata) {
auto size = getMetaDataSize();
void *base = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED,
handle->fd_metadata, 0);
if (base == reinterpret_cast<void*>(MAP_FAILED)) {
ALOGE("%s: metadata mmap failed - handle:%p fd: %d err: %s",
__func__, handle, handle->fd_metadata, strerror(errno));
return -1;
}
handle->base_metadata = (uintptr_t) base;
auto metadata = reinterpret_cast<MetaData_t *>(handle->base_metadata);
if (metadata->reservedSize) {
auto reserved_size = metadata->reservedSize;
munmap(reinterpret_cast<void *>(handle->base_metadata), getMetaDataSize());
handle->base_metadata = 0;
size = getMetaDataSizeWithReservedRegion(reserved_size);
void *new_base =
mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, handle->fd_metadata, 0);
if (new_base == reinterpret_cast<void *>(MAP_FAILED)) {
ALOGE("%s: metadata mmap failed - handle:%p fd: %d err: %s", __func__, handle,
handle->fd_metadata, strerror(errno));
return -1;
}
handle->base_metadata = (uintptr_t)new_base;
}
}
return 0;
}
static void unmapAndReset(private_handle_t *handle) {
if (private_handle_t::validate(handle) == 0 && handle->base_metadata) {
// If reservedSize is 0, the return value will be the same as getMetaDataSize
auto metadata = reinterpret_cast<MetaData_t *>(handle->base_metadata);
auto size = getMetaDataSizeWithReservedRegion(metadata->reservedSize);
munmap(reinterpret_cast<void *>(handle->base_metadata), size);
handle->base_metadata = 0;
}
}
int setMetaData(private_handle_t *handle, DispParamType paramType,
void *param) {
auto err = validateAndMap(handle);
if (err != 0)
return err;
return setMetaDataVa(reinterpret_cast<MetaData_t*>(handle->base_metadata),
paramType, param);
}
int setMetaDataVa(MetaData_t *data, DispParamType paramType,
void *param) {
if (data == nullptr)
return -EINVAL;
// If parameter is NULL reset the specific MetaData Key
if (!param) {
setGralloc4Array(data, paramType, false);
switch (paramType) {
case SET_VIDEO_PERF_MODE:
data->isVideoPerfMode = 0;
break;
case SET_CVP_METADATA:
data->cvpMetadata.size = 0;
break;
case SET_VIDEO_HISTOGRAM_STATS:
data->video_histogram_stats.stat_len = 0;
break;
default:
ALOGE("Unknown paramType %d", paramType);
break;
}
// param unset
return 0;
}
setGralloc4Array(data, paramType, true);
switch (paramType) {
case PP_PARAM_INTERLACED:
data->interlaced = *((int32_t *)param);
break;
case UPDATE_BUFFER_GEOMETRY: {
BufferDim_t in = *((BufferDim_t *)param);
data->crop = {0, 0, in.sliceWidth, in.sliceHeight};
break;
}
case UPDATE_REFRESH_RATE:
data->refreshrate = *((float *)param);
break;
case UPDATE_COLOR_SPACE: {
ColorMetaData color = {};
if (!colorSpaceToColorMetadata(*((ColorSpace_t *)param), &color)) {
data->color = color;
break;
}
return -EINVAL;
}
case MAP_SECURE_BUFFER:
data->mapSecureBuffer = *((int32_t *)param);
break;
case S3D_FORMAT:
data->s3dFormat = *((uint32_t *)param);
break;
case LINEAR_FORMAT:
data->linearFormat = *((uint32_t *)param);
break;
case SET_SINGLE_BUFFER_MODE:
data->isSingleBufferMode = *((uint32_t *)param);
break;
case SET_VT_TIMESTAMP:
data->vtTimeStamp = *((uint64_t *)param);
break;
case COLOR_METADATA:
data->color = *((ColorMetaData *)param);
break;
case SET_UBWC_CR_STATS_INFO: {
struct UBWCStats *stats = (struct UBWCStats *)param;
int numelems = sizeof(data->ubwcCRStats) / sizeof(struct UBWCStats);
for (int i = 0; i < numelems; i++) {
data->ubwcCRStats[i] = stats[i];
}
break;
}
case SET_VIDEO_PERF_MODE:
data->isVideoPerfMode = *((uint32_t *)param);
break;
case SET_GRAPHICS_METADATA: {
GraphicsMetadata payload = *((GraphicsMetadata*)(param));
data->graphics_metadata.size = payload.size;
memcpy(data->graphics_metadata.data, payload.data,
sizeof(data->graphics_metadata.data));
break;
}
case SET_CVP_METADATA: {
struct CVPMetadata *cvpMetadata = (struct CVPMetadata *)param;
if (cvpMetadata->size <= CVP_METADATA_SIZE) {
data->cvpMetadata.size = cvpMetadata->size;
memcpy(data->cvpMetadata.payload, cvpMetadata->payload,
cvpMetadata->size);
data->cvpMetadata.capture_frame_rate = cvpMetadata->capture_frame_rate;
data->cvpMetadata.cvp_frame_rate = cvpMetadata->cvp_frame_rate;
data->cvpMetadata.flags = cvpMetadata->flags;
memcpy(data->cvpMetadata.reserved, cvpMetadata->reserved,
(8 * sizeof(uint32_t)));
} else {
setGralloc4Array(data, paramType, false);
ALOGE("%s: cvp metadata length %d is more than max size %d", __func__,
cvpMetadata->size, CVP_METADATA_SIZE);
return -EINVAL;
}
break;
}
case SET_VIDEO_HISTOGRAM_STATS: {
struct VideoHistogramMetadata *vidstats = (struct VideoHistogramMetadata *)param;
if (vidstats->stat_len <= VIDEO_HISTOGRAM_STATS_SIZE) {
memcpy(data->video_histogram_stats.stats_info,
vidstats->stats_info, VIDEO_HISTOGRAM_STATS_SIZE);
data->video_histogram_stats.stat_len = vidstats->stat_len;
data->video_histogram_stats.frame_type = vidstats->frame_type;
data->video_histogram_stats.display_width = vidstats->display_width;
data->video_histogram_stats.display_height = vidstats->display_height;
data->video_histogram_stats.decode_width = vidstats->decode_width;
data->video_histogram_stats.decode_height = vidstats->decode_height;
} else {
setGralloc4Array(data, paramType, false);
ALOGE("%s: video stats length %u is more than max size %u", __func__,
vidstats->stat_len, VIDEO_HISTOGRAM_STATS_SIZE);
return -EINVAL;
}
break;
}
case SET_VIDEO_TS_INFO:
data->videoTsInfo = *((VideoTimestampInfo *)param);
break;
default:
ALOGE("Unknown paramType %d", paramType);
break;
}
return 0;
}
int clearMetaData(private_handle_t *handle, DispParamType paramType) {
auto err = validateAndMap(handle);
if (err != 0)
return err;
return clearMetaDataVa(reinterpret_cast<MetaData_t *>(handle->base_metadata),
paramType);
}
int clearMetaDataVa(MetaData_t *data, DispParamType paramType) {
if (data == nullptr)
return -EINVAL;
data->operation &= ~paramType;
switch (paramType) {
case SET_VIDEO_PERF_MODE:
data->isVideoPerfMode = 0;
break;
case SET_CVP_METADATA:
data->cvpMetadata.size = 0;
break;
case SET_VIDEO_HISTOGRAM_STATS:
data->video_histogram_stats.stat_len = 0;
break;
default:
ALOGE("Unknown paramType %d", paramType);
break;
}
return 0;
}
int getMetaData(private_handle_t *handle, DispFetchParamType paramType,
void *param) {
int ret = validateAndMap(handle);
if (ret != 0)
return ret;
return getMetaDataVa(reinterpret_cast<MetaData_t *>(handle->base_metadata),
paramType, param);
}
int getMetaDataVa(MetaData_t *data, DispFetchParamType paramType,
void *param) {
// Make sure we send 0 only if the operation queried is present
int ret = -EINVAL;
if (data == nullptr)
return ret;
if (param == nullptr)
return ret;
if (!getGralloc4Array(data, paramType)) {
return ret;
}
ret = 0;
switch (paramType) {
case GET_PP_PARAM_INTERLACED:
*((int32_t *)param) = data->interlaced;
break;
case GET_BUFFER_GEOMETRY:
*((BufferDim_t *)param) = {data->crop.right, data->crop.bottom};
break;
case GET_REFRESH_RATE:
*((float *)param) = data->refreshrate;
break;
case GET_COLOR_SPACE: {
ColorSpace_t color_space;
if (!colorMetaDataToColorSpace(data->color, &color_space)) {
*((ColorSpace_t *)param) = color_space;
} else {
ret = -EINVAL;
}
break;
}
case GET_MAP_SECURE_BUFFER:
*((int32_t *)param) = data->mapSecureBuffer;
break;
case GET_S3D_FORMAT:
*((uint32_t *)param) = data->s3dFormat;
break;
case GET_LINEAR_FORMAT:
*((uint32_t *)param) = data->linearFormat;
break;
case GET_SINGLE_BUFFER_MODE:
*((uint32_t *)param) = data->isSingleBufferMode;
break;
case GET_VT_TIMESTAMP:
*((uint64_t *)param) = data->vtTimeStamp;
break;
case GET_COLOR_METADATA:
*((ColorMetaData *)param) = data->color;
break;
case GET_UBWC_CR_STATS_INFO: {
struct UBWCStats *stats = (struct UBWCStats *)param;
int numelems = sizeof(data->ubwcCRStats) / sizeof(struct UBWCStats);
for (int i = 0; i < numelems; i++) {
stats[i] = data->ubwcCRStats[i];
}
break;
}
case GET_VIDEO_PERF_MODE:
*((uint32_t *)param) = data->isVideoPerfMode;
break;
case GET_GRAPHICS_METADATA:
memcpy(param, data->graphics_metadata.data, sizeof(data->graphics_metadata.data));
break;
case GET_CVP_METADATA: {
struct CVPMetadata *cvpMetadata = (struct CVPMetadata *)param;
cvpMetadata->size = 0;
if (data->cvpMetadata.size <= CVP_METADATA_SIZE) {
cvpMetadata->size = data->cvpMetadata.size;
memcpy(cvpMetadata->payload, data->cvpMetadata.payload, data->cvpMetadata.size);
cvpMetadata->capture_frame_rate = data->cvpMetadata.capture_frame_rate;
cvpMetadata->cvp_frame_rate = data->cvpMetadata.cvp_frame_rate;
cvpMetadata->flags = data->cvpMetadata.flags;
memcpy(cvpMetadata->reserved, data->cvpMetadata.reserved, (8 * sizeof(uint32_t)));
} else {
ret = -EINVAL;
}
break;
}
case GET_VIDEO_HISTOGRAM_STATS: {
struct VideoHistogramMetadata *vidstats = (struct VideoHistogramMetadata *)param;
vidstats->stat_len = 0;
if (data->video_histogram_stats.stat_len <= VIDEO_HISTOGRAM_STATS_SIZE) {
memcpy(vidstats->stats_info, data->video_histogram_stats.stats_info,
VIDEO_HISTOGRAM_STATS_SIZE);
vidstats->stat_len = data->video_histogram_stats.stat_len;
vidstats->frame_type = data->video_histogram_stats.frame_type;
vidstats->display_width = data->video_histogram_stats.display_width;
vidstats->display_height = data->video_histogram_stats.display_height;
vidstats->decode_width = data->video_histogram_stats.decode_width;
vidstats->decode_height = data->video_histogram_stats.decode_height;
} else {
ret = -EINVAL;
}
break;
}
case GET_VIDEO_TS_INFO:
*((VideoTimestampInfo *)param) = data->videoTsInfo;
break;
default:
ALOGE("Unknown paramType %d", paramType);
ret = -EINVAL;
break;
}
return ret;
}
int copyMetaData(struct private_handle_t *src, struct private_handle_t *dst) {
auto err = validateAndMap(src);
if (err != 0)
return err;
err = validateAndMap(dst);
if (err != 0)
return err;
MetaData_t *src_data = reinterpret_cast <MetaData_t *>(src->base_metadata);
MetaData_t *dst_data = reinterpret_cast <MetaData_t *>(dst->base_metadata);
*dst_data = *src_data;
return 0;
}
int copyMetaDataVaToHandle(MetaData_t *src_data, struct private_handle_t *dst) {
int err = -EINVAL;
if (src_data == nullptr)
return err;
err = validateAndMap(dst);
if (err != 0)
return err;
MetaData_t *dst_data = reinterpret_cast <MetaData_t *>(dst->base_metadata);
*dst_data = *src_data;
return 0;
}
int copyMetaDataHandleToVa(struct private_handle_t *src, MetaData_t *dst_data) {
int err = -EINVAL;
if (dst_data == nullptr)
return err;
err = validateAndMap(src);
if (err != 0)
return err;
MetaData_t *src_data = reinterpret_cast <MetaData_t *>(src->base_metadata);
*dst_data = *src_data;
return 0;
}
int copyMetaDataVaToVa(MetaData_t *src_data, MetaData_t *dst_data) {
int err = -EINVAL;
if (src_data == nullptr)
return err;
if (dst_data == nullptr)
return err;
*dst_data = *src_data;
return 0;
}
int setMetaDataAndUnmap(struct private_handle_t *handle, enum DispParamType paramType,
void *param) {
auto ret = setMetaData(handle, paramType, param);
unmapAndReset(handle);
return ret;
}
int getMetaDataAndUnmap(struct private_handle_t *handle,
enum DispFetchParamType paramType,
void *param) {
auto ret = getMetaData(handle, paramType, param);
unmapAndReset(handle);
return ret;
}

View File

@@ -0,0 +1,279 @@
/*
* Copyright (c) 2013, 2018, 2020 The Linux Foundation. All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <unistd.h>
#include <gralloc_priv.h>
#include "qd_utils.h"
static const int kFBNodeMax = 4;
namespace qdutils {
static int parseLine(char *input, char *tokens[], const uint32_t maxToken, uint32_t *count) {
char *tmpToken = NULL;
char *tmpPtr;
uint32_t index = 0;
const char *delim = ", =\n";
if (!input) {
return -1;
}
tmpToken = strtok_r(input, delim, &tmpPtr);
while (tmpToken && index < maxToken) {
tokens[index++] = tmpToken;
tmpToken = strtok_r(NULL, delim, &tmpPtr);
}
*count = index;
return 0;
}
static int getExternalNode(const char *type) {
FILE *displayDeviceFP = NULL;
char fbType[MAX_FRAME_BUFFER_NAME_SIZE];
char msmFbTypePath[MAX_FRAME_BUFFER_NAME_SIZE];
int j = 0;
for(j = 0; j < kFBNodeMax; j++) {
snprintf (msmFbTypePath, sizeof(msmFbTypePath),
"/sys/devices/virtual/graphics/fb%d/msm_fb_type", j);
displayDeviceFP = fopen(msmFbTypePath, "r");
if(displayDeviceFP) {
fread(fbType, sizeof(char), MAX_FRAME_BUFFER_NAME_SIZE,
displayDeviceFP);
if(strncmp(fbType, type, strlen(type)) == 0) {
ALOGD("%s: %s is at fb%d", __func__, type, j);
fclose(displayDeviceFP);
break;
}
fclose(displayDeviceFP);
} else {
ALOGE("%s: Failed to open fb node %s", __func__, msmFbTypePath);
}
}
if (j < kFBNodeMax)
return j;
else
ALOGE("%s: Failed to find %s node", __func__, type);
return -1;
}
int getHDMINode(void) {
return getExternalNode("dtv panel");
}
int getEdidRawData(char *buffer)
{
int size;
int edidFile;
char msmFbTypePath[MAX_FRAME_BUFFER_NAME_SIZE];
int node_id = getHDMINode();
if (node_id < 0) {
ALOGE("%s no HDMI node found", __func__);
return 0;
}
snprintf(msmFbTypePath, sizeof(msmFbTypePath),
"/sys/devices/virtual/graphics/fb%d/edid_raw_data", node_id);
edidFile = open(msmFbTypePath, O_RDONLY, 0);
if (edidFile < 0) {
ALOGE("%s no edid raw data found %s", __func__,msmFbTypePath);
return 0;
}
size = (int)read(edidFile, (char*)buffer, EDID_RAW_DATA_SIZE);
close(edidFile);
return size;
}
bool isDPConnected() {
char connectPath[MAX_FRAME_BUFFER_NAME_SIZE];
FILE *connectFile = NULL;
size_t len = MAX_STRING_LENGTH;
char stringBuffer[MAX_STRING_LENGTH];
char *line = stringBuffer;
int nodeId = getExternalNode("dp panel");
if (nodeId < 0) {
ALOGE("%s no DP node found", __func__);
return false;
}
snprintf(connectPath, sizeof(connectPath),
"/sys/devices/virtual/graphics/fb%d/connected", nodeId);
connectFile = fopen(connectPath, "rb");
if (!connectFile) {
ALOGW("Failed to open connect node for device node %s", connectPath);
return false;
}
if (getline(&line, &len, connectFile) < 0) {
fclose(connectFile);
return false;
}
fclose(connectFile);
return atoi(line);
}
int getDPTestConfig(uint32_t *panelBpp, uint32_t *patternType) {
if (!panelBpp || !patternType) {
return -1;
}
char configPath[MAX_FRAME_BUFFER_NAME_SIZE];
FILE *configFile = NULL;
uint32_t tokenCount = 0;
const uint32_t maxCount = 10;
char *tokens[maxCount] = { NULL };
size_t len = MAX_STRING_LENGTH;
char stringBuffer[MAX_STRING_LENGTH];
char *line = stringBuffer;
int nodeId = getExternalNode("dp panel");
if (nodeId < 0) {
ALOGE("%s no DP node found", __func__);
return -EINVAL;
}
snprintf(configPath, sizeof(configPath),
"/sys/devices/virtual/graphics/fb%d/config", nodeId);
configFile = fopen(configPath, "rb");
if (!configFile) {
ALOGW("Failed to open config node for device node %s", configPath);
return -EINVAL;
}
while (getline(&line, &len, configFile) != -1) {
if (!parseLine(line, tokens, maxCount, &tokenCount)) {
if (tokens[0] != NULL) {
if (!strncmp(tokens[0], "bpp", strlen("bpp"))) {
*panelBpp = static_cast<uint32_t>(atoi(tokens[1]));
} else if (!strncmp(tokens[0], "pattern", strlen("pattern"))) {
*patternType = static_cast<uint32_t>(atoi(tokens[1]));
}
}
}
}
fclose(configFile);
return 0;
}
DriverType getDriverType() {
const char *fb_caps = "/sys/devices/virtual/graphics/fb0/mdp/caps";
// 0 - File exists
return access(fb_caps, F_OK) ? DriverType::DRM : DriverType::FB;
}
const char *GetHALPixelFormatString(int format) {
switch (format) {
case HAL_PIXEL_FORMAT_RGBA_8888:
return "RGBA_8888";
case HAL_PIXEL_FORMAT_RGBX_8888:
return "RGBX_8888";
case HAL_PIXEL_FORMAT_RGB_888:
return "RGB_888";
case HAL_PIXEL_FORMAT_RGB_565:
return "RGB_565";
case HAL_PIXEL_FORMAT_BGR_565:
return "BGR_565";
case HAL_PIXEL_FORMAT_BGRA_8888:
return "BGRA_8888";
case HAL_PIXEL_FORMAT_RGBA_5551:
return "RGBA_5551";
case HAL_PIXEL_FORMAT_RGBA_4444:
return "RGBA_4444";
case HAL_PIXEL_FORMAT_YV12:
return "YV12";
case HAL_PIXEL_FORMAT_YCbCr_422_SP:
return "YCbCr_422_SP_NV16";
case HAL_PIXEL_FORMAT_YCrCb_420_SP:
return "YCrCb_420_SP_NV21";
case HAL_PIXEL_FORMAT_YCbCr_422_I:
return "YCbCr_422_I_YUY2";
case HAL_PIXEL_FORMAT_YCrCb_422_I:
return "YCrCb_422_I_YVYU";
case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
return "NV12_ENCODEABLE";
case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
return "YCbCr_420_SP_TILED_TILE_4x2";
case HAL_PIXEL_FORMAT_YCbCr_420_SP:
return "YCbCr_420_SP";
case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO:
return "YCrCb_420_SP_ADRENO";
case HAL_PIXEL_FORMAT_YCrCb_422_SP:
return "YCrCb_422_SP";
case HAL_PIXEL_FORMAT_R_8:
return "R_8";
case HAL_PIXEL_FORMAT_RG_88:
return "RG_88";
case HAL_PIXEL_FORMAT_INTERLACE:
return "INTERLACE";
case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
return "YCbCr_420_SP_VENUS";
case HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS:
return "YCrCb_420_SP_VENUS";
case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:
return "YCbCr_420_SP_VENUS_UBWC";
case HAL_PIXEL_FORMAT_RGBA_1010102:
return "RGBA_1010102";
case HAL_PIXEL_FORMAT_ARGB_2101010:
return "ARGB_2101010";
case HAL_PIXEL_FORMAT_RGBX_1010102:
return "RGBX_1010102";
case HAL_PIXEL_FORMAT_XRGB_2101010:
return "XRGB_2101010";
case HAL_PIXEL_FORMAT_BGRA_1010102:
return "BGRA_1010102";
case HAL_PIXEL_FORMAT_ABGR_2101010:
return "ABGR_2101010";
case HAL_PIXEL_FORMAT_BGRX_1010102:
return "BGRX_1010102";
case HAL_PIXEL_FORMAT_XBGR_2101010:
return "XBGR_2101010";
case HAL_PIXEL_FORMAT_YCbCr_420_P010:
return "YCbCr_420_P010";
case HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC:
return "YCbCr_420_TP10_UBWC";
case HAL_PIXEL_FORMAT_YCbCr_420_P010_VENUS:
return "YCbCr_420_P010_VENUS";
default:
return "Unknown_format";
}
}
}; //namespace qdutils

View File

@@ -0,0 +1,24 @@
cc_library_shared {
name: "libdisplayconfig.system.qti",
system_ext_specific: true,
cflags: [
"-Wno-sign-conversion",
"-Wno-unused-parameter",
"-DLOG_TAG=\"libdisplayconfigqti\"",
],
shared_libs: [
"liblog",
"libhidlbase",
"libutils",
"vendor.display.config@2.0"
],
header_libs: ["libhardware_headers", "display_intf_headers"],
srcs: [
"client_interface.cpp",
"client_impl.cpp",
"device_impl.cpp",
"device_interface.cpp",
],
export_header_lib_headers: ["display_intf_headers"],
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,185 @@
/*
* Copyright (c) 2020-2021 The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Changes from Qualcomm Innovation Center are provided under the following license:
*
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted (subject to the limitations in the
* disclaimer below) provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Qualcomm Innovation Center, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
* GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
* HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __CLIENT_IMPL_H__
#define __CLIENT_IMPL_H__
#define VALIDATE_CONFIG_SWITCH 1
#include <vendor/display/config/2.0/IDisplayConfig.h>
#include <hidl/HidlSupport.h>
#include <log/log.h>
#include <config/client_interface.h>
#include <string>
#include <vector>
#include "opcode_types.h"
namespace DisplayConfig {
using vendor::display::config::V2_0::IDisplayConfig;
using vendor::display::config::V2_0::IDisplayConfigCallback;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::hardware::hidl_handle;
using ::android::hardware::hidl_vec;
typedef hidl_vec<uint8_t> ByteStream;
typedef hidl_vec<hidl_handle> HandleStream;
class ClientCallback: public IDisplayConfigCallback {
public:
ClientCallback(ConfigCallback *cb) {
callback_ = cb;
}
private:
virtual Return<void> perform(uint32_t op_code, const ByteStream &input_params,
const HandleStream &input_handles);
void ParseNotifyCWBBufferDone(const ByteStream &input_params, const HandleStream &input_handles);
void ParseNotifyQsyncChange(const ByteStream &input_params);
void ParseNotifyIdleStatus(const ByteStream &input_params);
void ParseNotifyCameraSmooth(const ByteStream &input_params);
ConfigCallback *callback_ = nullptr;
};
class ClientImpl : public ClientInterface {
public:
int Init(std::string client_name, ConfigCallback *callback);
void DeInit();
virtual int IsDisplayConnected(DisplayType dpy, bool *connected);
virtual int SetDisplayStatus(DisplayType dpy, ExternalStatus status);
virtual int ConfigureDynRefreshRate(DynRefreshRateOp op, uint32_t refresh_rate);
virtual int GetConfigCount(DisplayType dpy, uint32_t *count);
virtual int GetActiveConfig(DisplayType dpy, uint32_t *config);
virtual int SetActiveConfig(DisplayType dpy, uint32_t config);
virtual int GetDisplayAttributes(uint32_t config_index, DisplayType dpy, Attributes *attributes);
virtual int SetPanelBrightness(uint32_t level);
virtual int GetPanelBrightness(uint32_t *level);
virtual int MinHdcpEncryptionLevelChanged(DisplayType dpy, uint32_t min_enc_level);
virtual int RefreshScreen();
virtual int ControlPartialUpdate(DisplayType dpy, bool enable);
virtual int ToggleScreenUpdate(bool on);
virtual int SetIdleTimeout(uint32_t value);
virtual int GetHDRCapabilities(DisplayType dpy, HDRCapsParams *caps);
virtual int SetCameraLaunchStatus(uint32_t on);
virtual int SetCameraSmoothInfo(CameraSmoothOp op, uint32_t fps);
virtual int DisplayBWTransactionPending(bool *status);
virtual int SetDisplayAnimating(uint64_t display_id, bool animating);
virtual int ControlIdlePowerCollapse(bool enable, bool synchronous);
virtual int GetWriteBackCapabilities(bool *is_wb_ubwc_supported);
virtual int SetDisplayDppsAdROI(uint32_t display_id, uint32_t h_start, uint32_t h_end,
uint32_t v_start, uint32_t v_end, uint32_t factor_in,
uint32_t factor_out);
virtual int UpdateVSyncSourceOnPowerModeOff();
virtual int UpdateVSyncSourceOnPowerModeDoze();
virtual int SetPowerMode(uint32_t disp_id, PowerMode power_mode);
virtual int IsPowerModeOverrideSupported(uint32_t disp_id, bool *supported);
virtual int IsHDRSupported(uint32_t disp_id, bool *supported);
virtual int IsWCGSupported(uint32_t disp_id, bool *supported);
virtual int SetLayerAsMask(uint32_t disp_id, uint64_t layer_id);
virtual int GetDebugProperty(const std::string prop_name, std::string *value);
virtual int GetActiveBuiltinDisplayAttributes(Attributes *attr);
virtual int SetPanelLuminanceAttributes(uint32_t disp_id, float min_lum, float max_lum);
virtual int IsBuiltInDisplay(uint32_t disp_id, bool *is_builtin);
virtual int IsAsyncVDSCreationSupported(bool *supported);
virtual int CreateVirtualDisplay(uint32_t width, uint32_t height, int format);
virtual int GetSupportedDSIBitClks(uint32_t disp_id, std::vector<uint64_t> *bit_clks);
virtual int GetDSIClk(uint32_t disp_id, uint64_t *bit_clk);
virtual int SetDSIClk(uint32_t disp_id, uint64_t bit_clk);
virtual int SetCWBOutputBuffer(uint32_t disp_id, const Rect rect, bool post_processed,
const native_handle_t *buffer);
virtual int SetQsyncMode(uint32_t disp_id, QsyncMode mode);
virtual int IsSmartPanelConfig(uint32_t disp_id, uint32_t config_id, bool *is_smart);
virtual int IsRotatorSupportedFormat(int hal_format, bool ubwc, bool *supported);
virtual int ControlQsyncCallback(bool enable);
virtual int SendTUIEvent(DisplayType dpy, TUIEventType event_type);
virtual int GetDisplayHwId(uint32_t disp_id, uint32_t *display_hw_id);
virtual int GetSupportedDisplayRefreshRates(DisplayType dpy,
std::vector<uint32_t> *supported_refresh_rates);
virtual int IsRCSupported(uint32_t disp_id, bool *supported);
virtual int ControlIdleStatusCallback(bool enable);
virtual int IsSupportedConfigSwitch(uint32_t disp_id, uint32_t config, bool *supported);
virtual int GetDisplayType(uint64_t physical_disp_id, DisplayType *disp_type);
virtual int AllowIdleFallback();
virtual int GetDisplayTileCount(uint64_t physical_disp_id, uint32_t *num_h_tiles,
uint32_t *num_v_tiles);
virtual int SetPowerModeTiled(uint64_t physical_disp_id, PowerMode power_mode,
uint32_t tile_h_loc, uint32_t tile_v_loc);
virtual int SetPanelBrightnessTiled(uint64_t physical_disp_id, uint32_t level,
uint32_t tile_h_loc, uint32_t tile_v_loc);
virtual int SetWiderModePreference(uint64_t physical_disp_id, WiderModePref mode_pref);
virtual int ControlCameraSmoothCallback(bool enable);
virtual int DummyDisplayConfigAPI();
private:
android::sp<IDisplayConfig> display_config_ = nullptr;
uint64_t client_handle_ = 0;
};
} // namespace DisplayConfig
#endif // __CLIENT_IMPL_H__

View File

@@ -0,0 +1,65 @@
/*
* Copyright (c) 2020 The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <string>
#include "client_impl.h"
namespace DisplayConfig {
int ClientInterface::Create(std::string client_name, ConfigCallback *callback,
ClientInterface **intf) {
if (!intf) {
return -1;
}
ClientImpl *impl = new ClientImpl();
if (!impl) {
return -1;
}
int ret = impl->Init(client_name, callback);
if (ret) {
delete impl;
return -1;
}
*intf = impl;
return 0;
}
void ClientInterface::Destroy(ClientInterface *intf) {
if (intf) {
ClientImpl *impl = static_cast<ClientImpl *>(intf);
impl->DeInit();
delete impl;
}
}
} // namespace DisplayConfig

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,196 @@
/*
* Copyright (c) 2021 The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Changes from Qualcomm Innovation Center are provided under the following license:
*
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted (subject to the limitations in the
* disclaimer below) provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Qualcomm Innovation Center, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
* GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
* HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __DEVICE_IMPL_H__
#define __DEVICE_IMPL_H__
#include <vendor/display/config/2.0/IDisplayConfig.h>
#include <hidl/HidlSupport.h>
#include <log/log.h>
#include <config/device_interface.h>
#include <map>
#include <utility>
#include <string>
#include <vector>
#include "opcode_types.h"
namespace DisplayConfig {
using vendor::display::config::V2_0::IDisplayConfig;
using vendor::display::config::V2_0::IDisplayConfigCallback;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::hardware::hidl_handle;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
using ::android::sp;
typedef hidl_vec<uint8_t> ByteStream;
typedef hidl_vec<hidl_handle> HandleStream;
class DeviceImpl : public IDisplayConfig, public android::hardware::hidl_death_recipient {
public:
static int CreateInstance(ClientContext *intf);
private:
class DeviceClientContext : public ConfigCallback {
public:
explicit DeviceClientContext(const sp<IDisplayConfigCallback> callback);
void SetDeviceConfigIntf(ConfigInterface *intf);
ConfigInterface* GetDeviceConfigIntf();
sp<IDisplayConfigCallback> GetDeviceConfigCallback();
virtual void NotifyCWBBufferDone(int32_t error, const native_handle_t *buffer);
virtual void NotifyQsyncChange(bool qsync_enabled, int32_t refresh_rate,
int32_t qsync_refresh_rate);
virtual void NotifyIdleStatus(bool is_idle);
virtual void NotifyCameraSmoothInfo(CameraSmoothOp op, uint32_t fps);
void ParseIsDisplayConnected(const ByteStream &input_params, perform_cb _hidl_cb);
void ParseSetDisplayStatus(const ByteStream &input_params, perform_cb _hidl_cb);
void ParseConfigureDynRefreshRate(const ByteStream &input_params, perform_cb _hidl_cb);
void ParseGetConfigCount(const ByteStream &input_params, perform_cb _hidl_cb);
void ParseGetActiveConfig(const ByteStream &input_params, perform_cb _hidl_cb);
void ParseSetActiveConfig(const ByteStream &input_params, perform_cb _hidl_cb);
void ParseGetDisplayAttributes(const ByteStream &input_params, perform_cb _hidl_cb);
void ParseSetPanelBrightness(const ByteStream &input_params, perform_cb _hidl_cb);
void ParseGetPanelBrightness(perform_cb _hidl_cb);
void ParseMinHdcpEncryptionLevelChanged(const ByteStream &input_params, perform_cb _hidl_cb);
void ParseRefreshScreen(perform_cb _hidl_cb);
void ParseControlPartialUpdate(const ByteStream &input_params, perform_cb _hidl_cb);
void ParseToggleScreenUpdate(const ByteStream &input_params, perform_cb _hidl_cb);
void ParseSetIdleTimeout(const ByteStream &input_params, perform_cb _hidl_cb);
void ParseGetHdrCapabilities(const ByteStream &input_params, perform_cb _hidl_cb);
void ParseSetCameraLaunchStatus(const ByteStream &input_params, perform_cb _hidl_cb);
void ParseSetCameraSmoothInfo(const ByteStream &input_params, perform_cb _hidl_cb);
void ParseControlCameraSmoothCallback(const ByteStream &input_params, perform_cb _hidl_cb);
void ParseDisplayBwTransactionPending(perform_cb _hidl_cb);
void ParseSetDisplayAnimating(const ByteStream &input_params, perform_cb _hidl_cb);
void ParseControlIdlePowerCollapse(const ByteStream &input_params, perform_cb _hidl_cb);
void ParseGetWritebackCapabilities(perform_cb _hidl_cb);
void ParseSetDisplayDppsAdRoi(const ByteStream &input_params, perform_cb _hidl_cb);
void ParseUpdateVsyncSourceOnPowerModeOff(perform_cb _hidl_cb);
void ParseUpdateVsyncSourceOnPowerModeDoze(perform_cb _hidl_cb);
void ParseSetPowerMode(const ByteStream &input_params, perform_cb _hidl_cb);
void ParseIsPowerModeOverrideSupported(const ByteStream &input_params, perform_cb _hidl_cb);
void ParseIsHdrSupported(const ByteStream &input_params, perform_cb _hidl_cb);
void ParseIsWcgSupported(const ByteStream &input_params, perform_cb _hidl_cb);
void ParseSetLayerAsMask(const ByteStream &input_params, perform_cb _hidl_cb);
void ParseGetDebugProperty(const ByteStream &input_params, perform_cb _hidl_cb);
void ParseGetActiveBuiltinDisplayAttributes(perform_cb _hidl_cb);
void ParseSetPanelLuminanceAttributes(const ByteStream &input_params, perform_cb _hidl_cb);
void ParseIsBuiltinDisplay(const ByteStream &input_params, perform_cb _hidl_cb);
void ParseSetCwbOutputBuffer(uint64_t clientHandle, const ByteStream &input_params,
const HandleStream &inputHandles, perform_cb _hidl_cb);
void ParseGetSupportedDsiBitclks(const ByteStream &input_params, perform_cb _hidl_cb);
void ParseGetDsiClk(const ByteStream &input_params, perform_cb _hidl_cb);
void ParseSetDsiClk(const ByteStream &input_params, perform_cb _hidl_cb);
void ParseSetQsyncMode(const ByteStream &input_params, perform_cb _hidl_cb);
void ParseIsSmartPanelConfig(const ByteStream &input_params, perform_cb _hidl_cb);
void ParseIsAsyncVdsSupported(perform_cb _hidl_cb);
void ParseCreateVirtualDisplay(const ByteStream &input_params, perform_cb _hidl_cb);
void ParseIsRotatorSupportedFormat(const ByteStream &input_params, perform_cb _hidl_cb);
void ParseControlQsyncCallback(uint64_t client_handle, const ByteStream &input_params,
perform_cb _hidl_cb);
void ParseSendTUIEvent(const ByteStream &input_params, perform_cb _hidl_cb);
void ParseGetDisplayHwId(const ByteStream &input_params, perform_cb _hidl_cb);
void ParseGetSupportedDisplayRefreshRates(const ByteStream &input_params, perform_cb _hidl_cb);
void ParseIsRCSupported(const ByteStream &input_params, perform_cb _hidl_cb);
void ParseControlIdleStatusCallback(uint64_t client_handle, const ByteStream &input_params,
perform_cb _hidl_cb);
void ParseIsSupportedConfigSwitch(const ByteStream &input_params, perform_cb _hidl_cb);
void ParseGetDisplayType(const ByteStream &input_params, perform_cb _hidl_cb);
void ParseAllowIdleFallback(perform_cb _hidl_cb);
void ParseGetDisplayTileCount(const ByteStream &input_params, perform_cb _hidl_cb);
void ParseSetPowerModeTiled(const ByteStream &input_params, perform_cb _hidl_cb);
void ParseSetPanelBrightnessTiled(const ByteStream &input_params, perform_cb _hidl_cb);
void ParseSetWiderModePreference(const ByteStream &input_params, perform_cb _hidl_cb);
private:
ConfigInterface *intf_ = nullptr;
const sp<IDisplayConfigCallback> callback_;
};
Return<void> registerClient(const hidl_string &client_name, const sp<IDisplayConfigCallback>& cb,
registerClient_cb _hidl_cb) override;
Return<void> perform(uint64_t client_handle, uint32_t op_code, const ByteStream &input_params,
const HandleStream &input_handles, perform_cb _hidl_cb) override;
void serviceDied(uint64_t client_handle,
const android::wp<::android::hidl::base::V1_0::IBase>& callback);
void ParseDestroy(uint64_t client_handle, perform_cb _hidl_cb);
ClientContext *intf_ = nullptr;
std::map<uint64_t, std::shared_ptr<DeviceClientContext>> display_config_map_;
uint64_t client_id_ = 0;
std::recursive_mutex death_service_mutex_;
static DeviceImpl *device_obj_;
static std::mutex device_lock_;
};
} // namespace DisplayConfig
#endif // __DEVICE_IMPL_H__

View File

@@ -0,0 +1,42 @@
/*
* Copyright (c) 2020 The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "device_impl.h"
namespace DisplayConfig {
int DeviceInterface::RegisterDevice(ClientContext *intf) {
if (!intf) {
return -1;
}
return DeviceImpl::CreateInstance(intf);
}
} // namespace DisplayConfig

View File

@@ -0,0 +1,135 @@
/*
* Copyright (c) 2020-2021 The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Changes from Qualcomm Innovation Center are provided under the following license:
*
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted (subject to the limitations in the
* disclaimer below) provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Qualcomm Innovation Center, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
* GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
* HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __OPCODE_TYPES_H__
#define __OPCODE_TYPES_H__
namespace DisplayConfig {
enum OpCode {
kIsDisplayConnected = 0,
kSetDisplayStatus = 1,
kConfigureDynRefreshRate = 2,
kGetConfigCount = 3,
kGetActiveConfig = 4,
kSetActiveConfig = 5,
kGetDisplayAttributes = 6,
kSetPanelBrightness = 7,
kGetPanelBrightness = 8,
kMinHdcpEncryptionLevelChanged = 9,
kRefreshScreen = 10,
kControlPartialUpdate = 11,
kToggleScreenUpdate = 12,
kSetIdleTimeout = 13,
kGetHdrCapabilities = 14,
kSetCameraLaunchStatus = 15,
kDisplayBwTransactionPending = 16,
kSetDisplayAnimating = 17,
kControlIdlePowerCollapse = 18,
kGetWritebackCapabilities = 19,
kSetDisplayDppsAdRoi = 20,
kUpdateVsyncSourceOnPowerModeOff = 21,
kUpdateVsyncSourceOnPowerModeDoze = 22,
kSetPowerMode = 23,
kIsPowerModeOverrideSupported = 24,
kIsHdrSupported = 25,
kIsWcgSupported = 26,
kSetLayerAsMask = 27,
kGetDebugProperty = 28,
kGetActiveBuiltinDisplayAttributes = 29,
kSetPanelLuminanceAttributes = 30,
kIsBuiltinDisplay = 31,
kSetCwbOutputBuffer = 32,
kGetSupportedDsiBitclks = 33,
kGetDsiClk = 34,
kSetDsiClk = 35,
kSetQsyncMode = 36,
kIsSmartPanelConfig = 37,
kIsAsyncVdsSupported = 38,
kCreateVirtualDisplay = 39,
kIsRotatorSupportedFormat = 40,
kControlQsyncCallback = 41,
kSendTUIEvent = 42,
kGetDisplayHwId = 43,
kGetSupportedDisplayRefreshRates = 44,
kIsRCSupported = 45,
kControlIdleStatusCallback = 46,
kIsSupportedConfigSwitch = 47,
kGetDisplayType = 48,
kAllowIdleFallback = 49,
kGetDisplayTileCount = 50,
kSetPowerModeTiled = 51,
kSetPanelBrightnessTiled = 52,
kSetWiderModePref = 53,
kSetCameraSmoothInfo = 54,
kControlCameraSmoothCallback = 55,
kDummyOpcode = 56,
kDestroy = 0xFFFF, // Destroy sequence execution
};
} // namespace DisplayConfig
#endif // __OPCODE_TYPES_H__

View File

@@ -0,0 +1,7 @@
java_library {
installable: true,
name: "tcmiface",
srcs: ["**/*.java"],
}

View File

@@ -0,0 +1,39 @@
/*
* Copyright (c) 2014, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of The Linux Foundation nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.quicinc.tcmiface;
/**
* @hide
*/
public interface DpmTcmIface {
/** @hide */
public void OnCloseIdleConn();
}

View File

@@ -0,0 +1,30 @@
cc_library_shared {
name: "libfm-hci",
srcs: ["fm_hci.cpp"],
shared_libs: [
"libdl",
"libcutils",
"libbase",
"libhidlbase",
"liblog",
"libutils",
"libbinder_ndk",
"libbinder",
"android.hardware.bluetooth.audio-V3-ndk",
//"vendor.qti.hardware.fm-V1-ndk",
//"vendor.qti.hardware.fm@1.0",
],
cflags: ["-Wno-unused-parameter"],
include_dirs: [
"vendor/qcom/opensource/commonsys/fm/helium",
],
system_ext_specific: true,
}

View File

@@ -0,0 +1,923 @@
/*
* Copyright (c) 2017, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*****************************************************************************
*
* This file contains main functions to support FM HCI interface to send
* commands and recieved events.
*
*****************************************************************************/
#define LOG_TAG "fm_hci"
#include <queue> // std::queue
#include <mutex> // std::mutex, std::unique_lock
#include <condition_variable> // std::condition_variable
#include <cstdlib>
#include <thread>
#include <android/binder_ibinder.h>
#include <android/binder_manager.h>
#include <android/binder_process.h>
//#include <binder_auto_utils.h>
#include <cassert>
#include <utils/Log.h>
#include <unistd.h>
#include <vendor/qti/hardware/fm/1.0/IFmHci.h>
#include <vendor/qti/hardware/fm/1.0/IFmHciCallbacks.h>
#include <vendor/qti/hardware/fm/1.0/types.h>
#include "fm_hci.h"
#include <hwbinder/ProcessState.h>
#include <aidl/vendor/qti/hardware/fm/BnFmHci.h>
#include <aidl/vendor/qti/hardware/fm/BnFmHciCallbacks.h>
#include <aidl/vendor/qti/hardware/fm/IFmHci.h>
#define ASSERT_LOG(condition, fmt, args...) \
do { \
if (!(condition)) { \
LOG_ALWAYS_FATAL("assertion '" #condition "' failed - " fmt, ##args); \
} \
} while (false)
using vendor::qti::hardware::fm::V1_0::IFmHci;
using vendor::qti::hardware::fm::V1_0::IFmHciCallbacks;
using vendor::qti::hardware::fm::V1_0::HciPacket;
using vendor::qti::hardware::fm::V1_0::Status;
using android::hardware::ProcessState;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::hardware::hidl_vec;
using ::android::hardware::hidl_death_recipient;
using ::aidl::vendor::qti::hardware::fm::BnFmHci;
using fm_aidl = ::aidl::vendor::qti::hardware::fm::IFmHci;
//using IBluetoothHci_1_1 = ::android::hardware::bluetooth::V1_1::IBluetoothHci;
using AidlStatus = ::aidl::vendor::qti::hardware::fm::Status;
static struct fm_hci_t hci;
typedef std::unique_lock<std::mutex> Lock;
static std::recursive_mutex mtx;
android::sp<IFmHci> fmHci;
std::shared_ptr<::aidl::vendor::qti::hardware::fm::IFmHci> fmAidlHci;
::ndk::ScopedAIBinder_DeathRecipient aidl_death_recipient_;
std::shared_ptr<::aidl::vendor::qti::hardware::fm::IFmHciCallbacks> aidl_callbacks_;
static int enqueue_fm_rx_event(struct fm_event_header_t *hdr);
static void dequeue_fm_rx_event();
static int enqueue_fm_tx_cmd(struct fm_command_header_t *hdr);
static void dequeue_fm_tx_cmd();
static void hci_tx_thread();
static void hci_rx_thread();
static int start_tx_thread();
static void stop_tx_thread();
static int start_rx_thread();
static void stop_rx_thread();
static void cleanup_threads();
static bool hci_initialize();
static void hci_transmit(struct fm_command_header_t *hdr);
static void hci_close();
static void initialization_complete(bool is_hci_initialize);
#define HCI_EV_HW_ERR_EVENT 0x1A
void hal_service_died() {
struct fm_event_header_t *temp = (struct fm_event_header_t *)
malloc(sizeof(struct fm_event_header_t));
if (temp != nullptr) {
temp->evt_code = HCI_EV_HW_ERR_EVENT;
temp->evt_len = 0;
ALOGI("%s: evt_code: 0x%x", __func__, temp->evt_code);
enqueue_fm_rx_event(temp);
} else {
ALOGE("%s: Memory Allocation failed for event buffer ",__func__);
}
}
class AidlHciCallbacks : public ::aidl::vendor::qti::hardware::fm::BnFmHciCallbacks {
public:
::ndk::ScopedAStatus initializationComplete(AidlStatus status) {
if(status == AidlStatus::SUCCESS)
{
initialization_complete(true);
} else {
initialization_complete(false);
}
return ::ndk::ScopedAStatus::ok();
}
::ndk::ScopedAStatus hciEventReceived(const std::vector<uint8_t>& event) override {
struct fm_event_header_t *temp = (struct fm_event_header_t *) malloc(event.size());
if (temp != nullptr) {
memcpy(temp, event.data(), event.size());
uint8_t evt = temp->evt_code;
ALOGI("%s: evt_code: 0x%x", __func__, evt);
enqueue_fm_rx_event(temp);
ALOGI("%s: evt_code: 0x%x done", __func__, evt);
} else {
ALOGE("%s: Memory Allocation failed for event buffer ",__func__);
}
return ::ndk::ScopedAStatus::ok();
}
private:
IFmHciCallbacks* callback_ = nullptr;
};
static constexpr char kFmAidlHalServiceName[] =
"vendor.qti.hardware.fm.IFmHci/default";
class FmHciDeathRecipient : public hidl_death_recipient {
public:
virtual void serviceDied(uint64_t /*cookie*/,
const android::wp<::android::hidl::base::V1_0::IBase>& /*who*/) {
ALOGE("Fm HAL service died!");
hal_service_died();
}
};
android::sp<FmHciDeathRecipient> fmHciDeathRecipient = new FmHciDeathRecipient();
/*******************************************************************************
**
** Function enqueue_fm_rx_event
**
** Description This function is called in the hal daemon context to queue
** FM events in RX queue.
**
** Parameters: hdr - contains the fm event header pointer
**
**
** Returns int
**
*******************************************************************************/
static int enqueue_fm_rx_event(struct fm_event_header_t *hdr)
{
ALOGV("%s: putting lock before enqueue ", __func__);
/*
* enqueue_fm_rx_event may need to wait for rx_cond_mtx here as
* last event is still under processing, besides current event
* has held internal_mutex_ when OnPacketReady called in data_handler.cpp
* if last event is HCI_EV_CMD_COMPLETE, it will try to hold
* internal_mutex_ again when calling close in data_handler,
* thus, last event will wait for internal_mutex_ while new event
* will wait util last event done, finally dead lock occurs.
* so we try to check hci state here if rx_cond_mtx is still locked
*/
int tryLockCount = 0;
while (1) {
if (!hci.rx_cond_mtx.try_lock()) {
if (hci.state == FM_RADIO_DISABLING || hci.state == FM_RADIO_DISABLED) {
ALOGI("%s: can't lock rx_cond_mtx and hci is not available", __func__);
return FM_HC_STATUS_NULL_POINTER;
}
usleep(1000);
tryLockCount++;
continue;
} else {
break;
}
}
hci.rx_queue_mtx.lock();
hci.rx_event_queue.push(hdr);
hci.rx_queue_mtx.unlock();
ALOGV("%s:notify to waiting thred", __func__);
hci.rx_cond.notify_all();
ALOGI("%s: FM-Event ENQUEUED SUCCESSFULLY tryLockCount = %d", __func__, tryLockCount);
hci.rx_cond_mtx.unlock();
return FM_HC_STATUS_SUCCESS;
}
/*******************************************************************************
**
** Function dequeue_fm_rx_event
**
** Description This function is called in the rx thread context to dequeue
** FM events from RX queue & processing the FM event.
**
** Parameters: void
**
**
** Returns void
**
*******************************************************************************/
static void dequeue_fm_rx_event()
{
fm_event_header_t *evt_buf;
ALOGI("%s", __func__);
while (1) {
hci.rx_queue_mtx.lock();
if (hci.rx_event_queue.empty()) {
ALOGI("No more FM Events are available in the RX Queue");
hci.rx_queue_mtx.unlock();
return;
} else {
}
evt_buf = hci.rx_event_queue.front();
hci.rx_event_queue.pop();
hci.rx_queue_mtx.unlock();
if (evt_buf->evt_code == FM_CMD_COMPLETE) {
ALOGI("%s: FM_CMD_COMPLETE: current_credits %d, %d Credits got from the SOC", __func__, hci.command_credits, evt_buf->params[0]);
if (hci.command_credits == 0) {
hci.command_credits += evt_buf->params[0];
ALOGV(" dequeue_fm_rx_event: wait for tx_cond_lock ");
hci.tx_cond_mtx.lock();
ALOGV(" dequeue_fm_rx_event: Notifying tx_cond_lock ");
hci.tx_cond.notify_all();
ALOGV(" dequeue_fm_rx_event: UNLOCKING tx_cond_lock ");
hci.tx_cond_mtx.unlock();
} else {
hci.command_credits += evt_buf->params[0];
}
} else if (evt_buf->evt_code == FM_CMD_STATUS) {
ALOGI("%s: FM_CMD_STATUS: current_credits %d, %d Credits got from the SOC", __func__, hci.command_credits, evt_buf->params[1]);
if (hci.command_credits == 0) {
hci.command_credits += evt_buf->params[1];
ALOGV(" dequeue_fm_rx_event: wait for tx_cond_lock ");
hci.tx_cond_mtx.lock();
ALOGV(" dequeue_fm_rx_event: Notifying tx_cond_lock ");
hci.tx_cond.notify_all();
ALOGV(" dequeue_fm_rx_event: UNLOCKING tx_cond_lock ");
hci.tx_cond_mtx.unlock();
} else {
hci.command_credits += evt_buf->params[1];
}
} else if (evt_buf->evt_code == FM_HW_ERR_EVENT) {
ALOGI("%s: FM H/w Err Event Recvd. Event Code: 0x%x", __func__, evt_buf->evt_code);
} else {
ALOGE("%s: Not CS/CC Event: Recvd. Event Code: 0x%x", __func__, evt_buf->evt_code);
}
if (hci.cb && hci.cb->process_event) {
ALOGI("%s: processing the event", __func__);
hci.cb->process_event((uint8_t *)evt_buf);
}
free(evt_buf);
evt_buf = NULL;
}
}
/*******************************************************************************
**
** Function enqueue_fm_tx_cmd
**
** Description This function is called in the application JNI context to
** queue FM commands in TX queue.
**
** Parameters: hdr - contains the fm command header pointer
**
**
** Returns int
**
*******************************************************************************/
static int enqueue_fm_tx_cmd(struct fm_command_header_t *hdr)
{
ALOGI("%s: opcode 0x%x len:%d ", __func__, hdr->opcode, hdr->len);
hci.tx_queue_mtx.lock();
hci.tx_cmd_queue.push(hdr);
hci.tx_queue_mtx.unlock();
ALOGI("%s: notifying credits %d", __func__, hci.command_credits);
if (hci.command_credits > 0) {
ALOGV(" enqueue_fm_tx_cmd: wait for tx_cond_lock ");
hci.tx_cond_mtx.lock();
ALOGV(" enqueue_fm_tx_cmd: Notifying tx_cond_lock ");
hci.tx_cond.notify_all();
ALOGV(" enqueue_fm_tx_cmd: UNLOCK tx_cond_lock ");
hci.tx_cond_mtx.unlock();
}
ALOGI("%s: FM-CMD ENQUEUED SUCCESSFULLY credits %d", __func__, hci.command_credits);
return FM_HC_STATUS_SUCCESS;
}
/*******************************************************************************
**
** Function dequeue_fm_tx_cmd
**
** Description This function is called in the tx thread context to dequeue
** & transmitting FM command to to HAL daemon.
**
** Parameters: void
**
**
** Returns void
**
*******************************************************************************/
static void dequeue_fm_tx_cmd()
{
fm_command_header_t *hdr;
ALOGI("%s command credits %d ", __func__, hci.command_credits);
while (1)
{
if (hci.command_credits == 0) {
return;
}
hci.tx_queue_mtx.lock();
ALOGV("%s is_que_empty %d", __func__,hci.tx_cmd_queue.empty());
if(hci.tx_cmd_queue.empty()){
ALOGI(" %s No more FM CMDs are available in the Queue",__func__);
hci.tx_queue_mtx.unlock();
return;
}
hdr = hci.tx_cmd_queue.front();
hci.tx_cmd_queue.pop();
hci.tx_queue_mtx.unlock();
ALOGV("%s: packet popped %d credits", __func__,hci.command_credits);
hci.command_credits--;
hci_transmit(hdr);
ALOGI("%s: packet transmitted %d credits", __func__,hci.command_credits);
}
ALOGI(" %s outside while(1), credits %d ", __func__, hci.command_credits);
}
/*******************************************************************************
**
** Function hci_tx_thread
**
** Description This function is main function of tx worker thread.
**
** Parameters: void
**
**
** Returns void
**
*******************************************************************************/
static void hci_tx_thread()
{
ALOGI("%s: ##### starting hci_tx_thread Worker thread!!! #####", __func__);
hci.is_tx_thread_running = true;
Lock lk(hci.tx_cond_mtx);
while (hci.state != FM_RADIO_DISABLING && hci.state != FM_RADIO_DISABLED) {
//wait for tx cmd
ALOGI("%s: before wait %d credits!!!" , __func__,hci.command_credits);
hci.tx_cond.wait(lk);
ALOGV("%s: after wait dequeueing the tx cmd!!!" , __func__);
dequeue_fm_tx_cmd();
}
hci.is_tx_thread_running =false;
ALOGI("%s: ##### Exiting hci_tx_thread Worker thread!!! #####", __func__);
}
/*******************************************************************************
**
** Function hci_rx_thread
**
** Description This function is main function of tx worker thread.
**
** Parameters: void
**
**
** Returns void
**
*******************************************************************************/
static void hci_rx_thread()
{
ALOGI("%s: ##### starting hci_rx_thread Worker thread!!! #####", __func__);
hci.is_rx_thread_running = true;
ALOGI("%s: constr unique_lock ", __func__);
Lock lk(hci.rx_cond_mtx);
while (hci.state != FM_RADIO_DISABLING && hci.state != FM_RADIO_DISABLED) {
//wait for rx event
ALOGI("%s:before wait", __func__);
hci.rx_cond.wait(lk);
ALOGI("%s:after wait ", __func__);
dequeue_fm_rx_event();
}
hci.is_rx_thread_running = false;
ALOGI("%s: ##### Exiting hci_rx_thread Worker thread!!! #####", __func__);
}
/*******************************************************************************
**
** Function start_tx_thread
**
** Description This function is called to start tx worker thread.
**
** Parameters: void
**
**
** Returns int
**
*******************************************************************************/
static int start_tx_thread()
{
ALOGI("FM-HCI: Creating the FM-HCI TX TASK...");
hci.tx_thread_ = std::thread(hci_tx_thread);
if (!hci.tx_thread_.joinable()) {
ALOGE("tx thread is not joinable");
return FM_HC_STATUS_FAIL;
}
return FM_HC_STATUS_SUCCESS;
}
/*******************************************************************************
**
** Function stop_tx_thread
**
** Description This function is called to stop tx worker thread.
**
** Parameters: void
**
**
** Returns int
**
*******************************************************************************/
static void stop_tx_thread()
{
ALOGI("%s:stop_tx_thread ++", __func__);
hci.tx_cond_mtx.lock();
hci.tx_cond.notify_all();
ALOGI("%s:notify to tx thread", __func__);
hci.tx_cond_mtx.unlock();
hci.tx_thread_.join();
ALOGI("%s:stop_tx_thread --", __func__);
}
/*******************************************************************************
**
** Function start_rx_thread
**
** Description This function is called to start rx worker thread.
**
** Parameters: void
**
**
** Returns int
**
*******************************************************************************/
static int start_rx_thread()
{
int ret = FM_HC_STATUS_SUCCESS;
ALOGI("FM-HCI: Creating the FM-HCI RX TASK...");
hci.rx_thread_ = std::thread(hci_rx_thread);
if (!hci.rx_thread_.joinable()) {
ALOGE("rx thread is not joinable");
return FM_HC_STATUS_FAIL;
}
return ret;
}
/*******************************************************************************
**
** Function stop_rx_thread
**
** Description This function is called to stop rx worker thread.
**
** Parameters: void
**
**
** Returns int
**
*******************************************************************************/
static void stop_rx_thread()
{
ALOGI("%s:stop_rx_thread ++", __func__);
hci.rx_cond.notify_all();
hci.rx_thread_.join();
ALOGI("%s:stop_rx_thread --", __func__);
}
/*******************************************************************************
**
** Function cleanup_threads
**
** Description This function is called to cleanup rx & tx worker thread.
**
** Parameters: void
**
**
** Returns int
**
*******************************************************************************/
static void cleanup_threads()
{
stop_rx_thread();
stop_tx_thread();
}
/*******************************************************************************
**
** Function initialization_complete
**
** Description This function is called, when initialization complete
** callback is called by hal daemon.
**
** Parameters: hdr - contains the fm event header pointer
**
**
** Returns int
**
*******************************************************************************/
static void initialization_complete(bool is_hci_initialize)
{
int ret;
ALOGI("++%s: is_hci_initialize: %d", __func__, is_hci_initialize);
hci.on_mtx.lock();
while (is_hci_initialize) {
ret = start_tx_thread();
if (ret)
{
cleanup_threads();
hci.state = FM_RADIO_DISABLING;
break;
}
ret = start_rx_thread();
if (ret)
{
cleanup_threads();
hci.state = FM_RADIO_DISABLING;
break;
}
hci.state = FM_RADIO_ENABLED;
break;
}
hci.on_cond.notify_all();
hci.on_mtx.unlock();
ALOGI("--%s: is_hci_initialize: %d", __func__, is_hci_initialize);
}
/*******************************************************************************
**
** Class FmHciCallbacks
**
** Description This is main class, which has the implemention for FM HCI
** callback functions.
**
** Member callback Functions: initializationComplete, hciEventReceived
**
**
** Returns int
**
*******************************************************************************/
class FmHciCallbacks : public IFmHciCallbacks {
public:
FmHciCallbacks() {
};
virtual ~FmHciCallbacks() = default;
Return<void> initializationComplete(Status status) {
if(status == Status::SUCCESS)
{
initialization_complete(true);
} else {
initialization_complete(false);
}
return Void();
}
Return<void> hciEventReceived(const hidl_vec<uint8_t>& event) {
struct fm_event_header_t *temp = (struct fm_event_header_t *) malloc(event.size());
if (temp != nullptr) {
memcpy(temp, event.data(), event.size());
uint8_t evt = temp->evt_code;
ALOGI("%s: evt_code: 0x%x", __func__, evt);
enqueue_fm_rx_event(temp);
ALOGI("%s: evt_code: 0x%x done", __func__, evt);
} else {
ALOGE("%s: Memory Allocation failed for event buffer ",__func__);
}
return Void();
}
};
bool start_aidl() {
ndk::SpAIBinder binder(AServiceManager_waitForService(kFmAidlHalServiceName));
fmAidlHci = fm_aidl::fromBinder(binder);
if (fmAidlHci != nullptr) {
ALOGE("Using the AIDL interface");
aidl_death_recipient_ =
::ndk::ScopedAIBinder_DeathRecipient(AIBinder_DeathRecipient_new([](void* cookie) {
ALOGE("The Fm HAL service died. Dumping logs and crashing in 1 second.");
LOG_ALWAYS_FATAL("The Bluetooth HAL died.");
}));
auto death_link =
AIBinder_linkToDeath(fmAidlHci->asBinder().get(), aidl_death_recipient_.get(), NULL);
ASSERT_LOG(
death_link == STATUS_OK, "Unable to set the death recipient for the Bluetooth HAL");
hci.state = FM_RADIO_ENABLING;
aidl_callbacks_ = ::ndk::SharedRefBase::make<AidlHciCallbacks>();
fmAidlHci->initialize(aidl_callbacks_);
}
return true;
}
bool start_hidl() {
fmHci = IFmHci::getService();
if(fmHci == nullptr) {
ALOGE("FM hal service is not running");
return FM_HC_STATUS_NULL_POINTER;
}
auto death_link = fmHci->linkToDeath(fmHciDeathRecipient, 0);
if (!death_link.isOk()) {
ALOGE("%s: Unable to set the death recipient for the Fm HAL", __func__);
abort();
}
if (fmHci != nullptr) {
hci.state = FM_RADIO_ENABLING;
android::sp<IFmHciCallbacks> callbacks = new FmHciCallbacks();
auto hidl_daemon_status = fmHci->initialize(callbacks);
if(!hidl_daemon_status.isOk()) {
ALOGE("%s: HIDL daemon is dead", __func__);
}
return true;
} else {
return false;
}
}
/*******************************************************************************
**
** Function hci_initialize
**
** Description This function is used to initialize fm hci hidl transport.
** It makes a binder call to hal daemon
**
** Parameters: void
**
**
** Returns bool
**
*******************************************************************************/
static bool hci_initialize()
{
ALOGI("%s: acquiring mutex", __func__);
std::lock_guard<std::recursive_mutex> lk(mtx);
if (AServiceManager_isDeclared(kFmAidlHalServiceName)) {
start_aidl();
} else {
start_hidl();
}
return true;
}
/*******************************************************************************
**
** Function hci_transmit
**
** Description This function is used to send fm command to fm hci hidl transport.
** It makes a binder call to hal daemon.
**
** Parameters: void
**
**
** Returns void
**
*******************************************************************************/
static void hci_transmit(struct fm_command_header_t *hdr) {
HciPacket data;
ALOGI("%s: opcode 0x%x len:%d, acquiring mutex", __func__, hdr->opcode, hdr->len);
std::lock_guard<std::recursive_mutex> lk(mtx);
if (fmHci != nullptr) {
data.setToExternal((uint8_t *)hdr, 3 + hdr->len);
auto hidl_daemon_status = fmHci->sendHciCommand(data);
if(!hidl_daemon_status.isOk()) {
ALOGE("%s: send Command failed, HIDL daemon is dead", __func__);
}
} else if( fmAidlHci != nullptr) {
data.setToExternal((uint8_t *)hdr, 3 + hdr->len);
auto hidl_daemon_status = fmAidlHci->sendHciCommand(data);
} else {
ALOGI("%s: fmHci is NULL", __func__);
}
free(hdr);
}
/*******************************************************************************
**
** Function hci_close
**
** Description This function is used to close fm hci hidl transport.
** It makes a binder call to hal daemon
**
** Parameters: void
**
**
** Returns void
**
*******************************************************************************/
static void hci_close()
{
ALOGI("%s: acquiring mutex", __func__);
std::lock_guard<std::recursive_mutex> lk(mtx);
if (fmHci != nullptr) {
auto death_unlink = fmHci->unlinkToDeath(fmHciDeathRecipient);
if (!death_unlink.isOk()) {
ALOGE( "%s: Error unlinking death recipient from the Fm HAL", __func__);
}
auto hidl_daemon_status = fmHci->close();
if(!hidl_daemon_status.isOk()) {
ALOGE("%s: HIDL daemon is dead", __func__);
}
fmHci = nullptr;
} else if(fmAidlHci != nullptr) {
auto death_unlink =
AIBinder_unlinkToDeath(fmAidlHci->asBinder().get(), aidl_death_recipient_.get(), NULL);
if (death_unlink != STATUS_OK) {
ALOGE("Error unlinking death recipient from the Bluetooth HAL");
}
auto close_status = fmAidlHci->close();
if (!close_status.isOk()) {
ALOGE("Error calling close on the Bluetooth HAL");
}
fmAidlHci = nullptr;
}
}
/*******************************************************************************
**
** Function fm_hci_init
**
** Description This function is used to intialize fm hci
**
** Parameters: hci_hal - contains the fm helium hal hci pointer
**
**
** Returns void
**
*******************************************************************************/
int fm_hci_init(fm_hci_hal_t *hci_hal)
{
int ret = FM_HC_STATUS_FAIL;
ALOGD("++%s", __func__);
if(hci.is_rx_thread_running)
{
ALOGI("%s:previous rx thread running wait until rx thread stops", __func__);
hci.rx_thread_.join();
ALOGI("%s:stop_rx_thread completed, proceed iniialization", __func__);
}
if (!hci_hal || !hci_hal->hal) {
ALOGE("NULL input argument");
return FM_HC_STATUS_NULL_POINTER;
}
memset(&hci, 0, sizeof(struct fm_hci_t));
hci.cb = hci_hal->cb;
hci.command_credits = 1;
hci.is_tx_thread_running = false;
hci.is_rx_thread_running = false;
hci.state = FM_RADIO_DISABLED;
hci_hal->hci = &hci;
if (hci_initialize()) {
//wait for iniialization complete
Lock lk(hci.on_mtx);
if(hci.state == FM_RADIO_ENABLING){
ALOGD("--%s waiting for iniialization complete hci state: %d ",
__func__, hci.state);
std::cv_status status = std::cv_status::no_timeout;
auto now = std::chrono::system_clock::now();
status =
hci.on_cond.wait_until(lk, now + std::chrono::seconds(HCI_TIMEOUT));
if (status == std::cv_status::timeout) {
ALOGE("hci_initialize failed, kill the fm process");
hci.on_mtx.unlock();
kill(getpid(), SIGKILL);
}
}
hci.on_mtx.unlock();
}
if (hci.state == FM_RADIO_ENABLED) {
while (hci.is_tx_thread_running == false
|| hci.is_rx_thread_running == false)
{
/* checking tx & rx thread running status after every
5ms before notifying on to upper layer */
usleep(5000);
}
ALOGD("--%s success", __func__);
ret = FM_HC_STATUS_SUCCESS;
} else {
ALOGD("--%s failed", __func__);
hci_close();
hci.state = FM_RADIO_DISABLED;
}
return ret;
}
/*******************************************************************************
**
** Function fm_hci_transmit
**
** Description This function is called by helium hal & is used enqueue the
** tx commands in tx queue.
**
** Parameters: p_hci - contains the fm helium hal hci pointer
** hdr - contains the fm command header pointer
**
** Returns void
**
*******************************************************************************/
int fm_hci_transmit(void *p_hci, struct fm_command_header_t *hdr)
{
if (!hdr) {
ALOGE("NULL input arguments");
return FM_HC_STATUS_NULL_POINTER;
}
return enqueue_fm_tx_cmd(hdr);
}
/*******************************************************************************
**
** Function fm_hci_close
**
** Description This function is used to close & cleanup hci
**
** Parameters: p_hci - contains the fm hci pointer
**
**
** Returns void
**
*******************************************************************************/
void fm_hci_close(void *p_hci)
{
ALOGI("%s", __func__);
hci.state = FM_RADIO_DISABLING;
hci_close();
stop_tx_thread();
if (hci.cb && hci.cb->fm_hci_close_done) {
ALOGI("%s:Notify FM OFF to hal", __func__);
hci.cb->fm_hci_close_done();
}
hci.state = FM_RADIO_DISABLED;
}

View File

@@ -0,0 +1,71 @@
/*
* Copyright (c) 2015-2017 The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __FM_HCI__
#define __FM_HCI__
#include "fm_hci_api.h"
#define FM_CMD_COMPLETE 0x0f
#define FM_CMD_STATUS 0x10
#define FM_HW_ERR_EVENT 0x1A
#define HCI_TIMEOUT 3
struct fm_hci_t {
public:
fm_power_state_t state;
std::condition_variable on_cond;
std::mutex on_mtx;
bool is_tx_thread_running;
bool is_rx_thread_running;
std::condition_variable tx_cond;
std::mutex tx_cond_mtx;
std::condition_variable rx_cond;
std::mutex rx_cond_mtx;
std::mutex tx_queue_mtx;
std::mutex rx_queue_mtx;
std::condition_variable cmd_credits_cond;
std::queue<struct fm_command_header_t *> tx_cmd_queue;
std::queue<struct fm_event_header_t *> rx_event_queue;
volatile uint16_t command_credits;
struct fm_hci_callbacks_t *cb;
std::thread tx_thread_;
std::thread rx_thread_;
};
#endif

View File

@@ -0,0 +1,143 @@
/*
* Copyright (c) 2015-2016 The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __FM_HCI_API__
#define __FM_HCI_API__
/** Host/Controller Library Return Status */
typedef enum {
FM_HC_STATUS_SUCCESS,
FM_HC_STATUS_FAIL,
FM_HC_STATUS_NOT_READY,
FM_HC_STATUS_NOMEM,
FM_HC_STATUS_BUSY,
FM_HC_STATUS_CORRUPTED_BUFFER,
FM_HC_STATUS_NULL_POINTER,
} fm_hc_status_t;
static char *status_s[] = {
"Success",
"Failed, generic error",
"Not ready",
"Memory not available",
"Resource busy",
"Buffer is corrupted",
"NULL pointer dereference",
};
static inline char *fm_hci_status(int status) {
return status_s[status];
}
typedef enum {
FM_RADIO_DISABLED,
FM_RADIO_DISABLING,
FM_RADIO_ENABLED,
FM_RADIO_ENABLING
} fm_power_state_t;
typedef int (*event_notification_cb_t)(unsigned char *buf);
typedef int (*hci_close_done_cb_t)(void);
struct fm_hci_callbacks_t {
event_notification_cb_t process_event;
hci_close_done_cb_t fm_hci_close_done;
};
typedef struct {
void *hci;
void *hal;
struct fm_hci_callbacks_t *cb;
}fm_hci_hal_t;
struct fm_command_header_t {
uint16_t opcode;
uint8_t len;
uint8_t params[];
}__attribute__((packed));
struct fm_event_header_t {
uint8_t evt_code;
uint8_t evt_len;
uint8_t params[];
}__attribute__((packed));
#ifdef __cplusplus
extern "C"
{
#endif
/*******************************************************************************
**
** Function fm_hci_init
**
** Description This function is used to intialize fm hci
**
** Parameters: hci_hal: contains the fm helium hal hci pointer
**
**
** Returns void
**
*******************************************************************************/
int fm_hci_init(fm_hci_hal_t *hal_hci);
/*******************************************************************************
**
** Function fm_hci_transmit
**
** Description This function is called by helium hal & is used enqueue the
** tx commands in tx queue.
**
** Parameters: p_hci - contains the fm helium hal hci pointer
** hdr - contains the fm command header pointer
**
** Returns void
**
*******************************************************************************/
int fm_hci_transmit(void *p_hci, struct fm_command_header_t *hdr);
/*******************************************************************************
**
** Function fm_hci_close
**
** Description This function is used to close & cleanup hci
**
** Parameters: p_hci: contains the fm hci pointer
**
**
** Returns void
**
*******************************************************************************/
void fm_hci_close(void *p_hci);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,13 @@
android_app {
name: "FM2",
srcs: ["src/com/caf/fmradio/CommaSeparatedFreqFileReader.java"] + ["src/com/caf/fmradio/FMAdapterApp.java"] + ["src/com/caf/fmradio/FMMediaButtonIntentReceiver.java"] + ["src/com/caf/fmradio/FMRadio.java"] + ["src/com/caf/fmradio/FMRadioService.java"] + ["src/com/caf/fmradio/FmSharedPreferences.java"] + ["src/com/caf/fmradio/FMStats.java"] + ["src/com/caf/fmradio/FmTags.java"] + ["src/com/caf/fmradio/GetNextFreqInterface.java"] + ["src/com/caf/fmradio/HorizontalNumberPicker.java"] + ["src/com/caf/fmradio/PresetList.java"] + ["src/com/caf/fmradio/PresetStation.java"] + ["src/com/caf/fmradio/Settings.java"] + ["src/com/caf/fmradio/StationListActivity.java"] + ["src/com/caf/fmradio/IFMRadioService.aidl"] + ["src/com/caf/fmradio/IFMRadioServiceCallbacks.aidl"] + ["src/com/caf/fmradio/IFMTransmitterServiceCallbacks.aidl"] + ["src/com/caf/hc_utils/**/*.java"],
certificate: "platform",
jni_libs: ["libqcomfm_jni"],
libs: ["qcom.fmradio"],
platform_apis: true,
aaptflags: ["--legacy"],
system_ext_specific: true,
}

View File

@@ -0,0 +1,139 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
* Copyright (c) 2009, 2012-2013,2015, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of The Linux Foundation nor
* the names of its contributors may be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.caf.fmradio" >
<uses-sdk android:minSdkVersion="34" android:targetSdkVersion="34"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL"/>
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
<uses-permission android:name="android.permission.MODIFY_PHONE_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.CAPTURE_AUDIO_OUTPUT" />
<uses-permission android:name="android.permission.CAPTURE_AUDIO_HOTWORD" />
<uses-permission android:name="android.permission.MANAGE_USERS"/>
<application
android:requestLegacyExternalStorage="true"
android:icon="@drawable/ic_launcher_fmradio"
android:label="@string/app_name"
android:allowTaskReparenting="true"
android:taskAffinity="com.caf.task.fmradio"
android:name=".FMAdapterApp">
<activity android:icon="@drawable/ic_launcher_fmradio"
android:name=".FMRadio"
android:label="@string/app_name"
android:clearTaskOnLaunch="true"
android:allowTaskReparenting="true"
android:launchMode="singleTask"
android:configChanges="keyboardHidden|orientation|screenSize"
android:excludeFromRecents="false"
android:exported="true" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="com.caf.fmradio.FMRADIO_ACTIVITY" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<receiver android:name="com.caf.fmradio.FMMediaButtonIntentReceiver"
android:exported="true" >
<intent-filter>
<action android:name="android.media.AUDIO_BECOMING_NOISY" />
</intent-filter>
</receiver>
<activity android:name=".Settings"
android:exported="true"
android:label="@string/settings_menu">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
</intent-filter>
</activity>
<activity android:name=".FMStats"
android:exported="true"
android:label="@string/test_menu">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
</intent-filter>
</activity>
<activity android:name=".FmTags"
android:exported="true"
android:label="@string/rt_plus_tags">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
</intent-filter>
</activity>
<activity android:name=".StationListActivity"
android:exported="true"
android:label="@string/app_label_all_channels"
android:configChanges="orientation|keyboardHidden|screenSize|fontScale">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
</intent-filter>
</activity>
<service android:name=".FMRadioService"
android:foregroundServiceType="mediaPlayback"
android:exported="true" />
</application>
</manifest>

View File

@@ -0,0 +1,223 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
* Copyright (c) 2009, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of The Linux Foundation nor
* the names of its contributors may be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<!--
This LinearLayout contains Station Information display and the
function buttons
-->
<LinearLayout android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="horizontal">
<LinearLayout android:background="@drawable/station_border"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical"
android:gravity="top|fill_vertical">
<RelativeLayout android:id="@+id/station_layout"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<!-- This included layout contains Station Information to display -->
<LinearLayout android:id="@+id/stationinfo_layout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5px"
android:layout_marginLeft="5px"
android:layout_marginRight="5px"
android:orientation="vertical"
android:gravity="fill_vertical">
<LinearLayout android:id="@+id/station_frequency_row"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingTop="25px"
android:paddingBottom="25px"
android:gravity="fill_vertical|center">
<TextView android:id="@+id/transmit_msg_tv"
android:textAppearance="?android:attr/textAppearanceSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="15px"
android:layout_centerHorizontal="true"
android:layout_alignWithParentIfMissing="true"
android:text="@string/transmit_msg_string" />
<TextView android:id="@+id/prog_frequency_tv"
android:textAppearance="?android:attr/textAppearanceLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_alignWithParentIfMissing="true"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:textSize="56px"
android:text="@string/frequency_string" />
</LinearLayout>
<!-- Station Radio Text information display -->
<TextView android:id="@+id/radio_text_tv"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textSize="16sp"
android:singleLine="true"
android:textStyle="bold"
android:paddingBottom="2px"
android:paddingLeft="5px"
android:paddingRight="5px"
android:gravity="center_horizontal"
android:text="@string/radio_text_string" />
<!-- android:gravity="center_horizontal" -->
</LinearLayout>
<ImageView android:id="@+id/btn_back"
android:clickable="true"
android:focusable="true"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:paddingLeft="10px"
android:paddingRight="2px"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:visibility="visible"
android:src="@drawable/btn_arrow_left" />
<ImageView android:id="@+id/btn_forward"
android:clickable="true"
android:focusable="true"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:paddingLeft="2px"
android:paddingRight="10px"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:visibility="visible"
android:src="@drawable/btn_arrow_right" />
</RelativeLayout>
</LinearLayout>
<LinearLayout android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_gravity="center"
android:layout_marginLeft="5px"
android:layout_marginRight="5px"
android:layout_marginBottom="2px">
<!-- On-Off button -->
<ImageButton android:id="@+id/btn_onoff"
android:layout_width="75px"
android:layout_height="75px"
android:src="@drawable/ic_btn_onoff"
android:layout_marginTop="15px"
android:layout_marginBottom="15px" />
</LinearLayout>
</LinearLayout>
<View
android:layout_width="fill_parent"
android:layout_height="1px"
android:background="#ffffffff" />
<!--
Layout contains the Next/Previous Presets and Tune buttons and status
msg text
-->
<LinearLayout android:id="@+id/presets_layout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_weight="0"
android:layout_gravity="center"
android:layout_marginTop="15dip"
android:layout_marginBottom="10dip"
android:gravity="center_horizontal">
<Button android:id="@+id/presets_button_1"
android:text="@string/default_station"
android:layout_marginLeft="20dip"
android:layout_marginRight="20dip"
android:textSize="24sp"
android:singleLine="true"
android:layout_width="110dip"
android:layout_height="65dip" />
<Button android:id="@+id/presets_button_2"
android:text="@string/default_station"
android:layout_marginRight="20dip"
android:textSize="24sp"
android:singleLine="true"
android:layout_width="110dip"
android:layout_height="65dip" />
<Button android:id="@+id/presets_button_3"
android:text="@string/default_station"
android:layout_marginRight="20dip"
android:textSize="24sp"
android:singleLine="true"
android:layout_width="110dip"
android:layout_height="65dip" />
<Button android:id="@+id/presets_button_4"
android:text="@string/default_blank"
android:layout_marginRight="20dip"
android:textSize="24sp"
android:singleLine="true"
android:layout_width="110dip"
android:layout_height="65dip" />
<Button android:id="@+id/presets_button_5"
android:text="@string/default_blank"
android:layout_marginRight="20dip"
android:textSize="24sp"
android:singleLine="true"
android:layout_width="110dip"
android:layout_height="65dip" />
<Button android:id="@+id/presets_button_6"
android:text="@string/default_blank"
android:layout_marginRight="20dip"
android:textSize="24sp"
android:singleLine="true"
android:layout_width="110dip"
android:layout_height="65dip"/>
</LinearLayout>
</LinearLayout>

View File

@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
* Copyright (c) 2009, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of The Linux Foundation nor
* the names of its contributors may be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-->
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXScale="0.75"
android:toXScale="1.5"
android:fromYScale="0.75"
android:toYScale="1.5"
android:pivotX="50%"
android:pivotY="50%"
android:startOffset="0"
android:duration="500"
android:fillBefore="true" />

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 588 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 593 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 610 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 708 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 715 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 762 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 576 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 587 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 614 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 519 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 491 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 511 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 604 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 581 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 616 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 483 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 488 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 515 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Some files were not shown because too many files have changed in this diff Show More