blob: e6fbfa910e3005bd48326dea7fbbea7c57745e44 [file] [log] [blame]
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_TAG "audio_hw_primary_factory"
//#define LOG_NDEBUG 0
#include <stdlib.h>
#include <errno.h>
#include <log/log.h>
#include <cutils/str_parms.h>
#include "factory_manager.h"
#include "audio_definition.h"
#include "audio_proxy_interface.h"
/******************************************************************************/
/** **/
/** The Factory Functions **/
/** **/
/******************************************************************************/
bool is_factory_mode(struct factory_manager *factory)
{
if(factory && factory->mode != FACTORY_MODE_NONE)
return true;
else
return false;
}
bool is_factory_loopback_mode(struct factory_manager *factory)
{
if(factory && factory->mode == FACTORY_MODE_LOOPBACK)
return true;
else
return false;
}
bool is_factory_bt_realtime_loopback_mode(struct factory_manager *factory)
{
if (factory && (factory->loopback_mode == FACTORY_LOOPBACK_REALTIME)
&& (factory->out_device == AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET) && (factory->in_device == AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET)) {
return true;
}
return false;
}
bool is_factory_rms_mode(struct factory_manager *factory)
{
if(factory && factory->mode == FACTORY_MODE_RMS)
return true;
else
return false;
}
static void factory_set_path_for_loopback(struct factory_manager *factory, const char *value)
{
ALOGD("%s: enter with value(%s)", __func__, value);
ALOGI("%s : loopback = %s ",__func__, value);
if(strncmp(value, "ear_ear", 7) == 0) {
factory->out_device = (AUDIO_DEVICE_OUT_WIRED_HEADSET);
factory->in_device = (AUDIO_DEVICE_IN_WIRED_HEADSET);
} else if(strncmp(value, "mic1_spk", 8) == 0) {
factory->out_device = (AUDIO_DEVICE_OUT_SPEAKER);
factory->in_device = (AUDIO_DEVICE_IN_BUILTIN_MIC);
} else if(strncmp(value, "mic2_spk", 8) == 0) {
factory->out_device = (AUDIO_DEVICE_OUT_SPEAKER);
factory->in_device = (AUDIO_DEVICE_IN_BACK_MIC);
} else if(strncmp(value, "mic1_rcv", 8) == 0) {
factory->out_device = (AUDIO_DEVICE_OUT_EARPIECE);
factory->in_device = (AUDIO_DEVICE_IN_BUILTIN_MIC);
} else if(strncmp(value, "mic2_rcv", 8) == 0) {
factory->out_device = (AUDIO_DEVICE_OUT_EARPIECE);
factory->in_device = (AUDIO_DEVICE_IN_BACK_MIC);
} else if(strncmp(value, "mic1_ear", 8) == 0) {
factory->out_device = (AUDIO_DEVICE_OUT_WIRED_HEADSET);
factory->in_device = (AUDIO_DEVICE_IN_BUILTIN_MIC);
} else if(strncmp(value, "mic2_ear", 8) == 0) {
factory->out_device = (AUDIO_DEVICE_OUT_WIRED_HEADSET);
factory->in_device = (AUDIO_DEVICE_IN_BACK_MIC);
} else if(strncmp(value, "bt_bt", 5) == 0) {
factory->out_device = (AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET);
factory->in_device = (AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET);
} else {
ALOGW("factory test path doesn't exist. default set earpiece.");
factory->out_device = (AUDIO_DEVICE_OUT_EARPIECE);
factory->in_device = (AUDIO_DEVICE_IN_BUILTIN_MIC);
}
return;
}
static void factory_set_path_for_force_route(struct factory_manager *factory, const char *value)
{
if (!factory->rms_test_enable)
factory->mode = FACTORY_MODE_FORCE_ROUTE;
if (!strcmp(value, "spk")) {
ALOGD("%s factory_test_route : spk", __func__);
factory->out_device = (AUDIO_DEVICE_OUT_SPEAKER & AUDIO_DEVICE_OUT_ALL);
} else if (!strcmp(value, "rcv")) {
ALOGD("%s factory_test_route : rcv", __func__);
factory->out_device = (AUDIO_DEVICE_OUT_EARPIECE & AUDIO_DEVICE_OUT_ALL);
} else if (!strcmp(value, "ear")) {
ALOGD("%s factory_test_route : ear", __func__);
factory->out_device = (AUDIO_DEVICE_OUT_WIRED_HEADSET & AUDIO_DEVICE_OUT_ALL);
} else if (!strcmp(value, "off")) {
ALOGD("%s factory_test_route : off", __func__);
factory->mode = FACTORY_MODE_NONE;
factory->out_device = (AUDIO_DEVICE_NONE);
}
return;
}
static void factory_set_path_for_rms(struct factory_manager *factory, const char *value)
{
if (strcmp(value, "on") == 0) {
ALOGD("%s factory_test_mic_check=on", __func__);
factory->mode = FACTORY_MODE_RMS;
factory->rms_test_enable = true;
} else if (strcmp(value, "main") == 0) {
ALOGD("%s factory_test_mic_check=main", __func__);
factory->in_device = (AUDIO_DEVICE_IN_BUILTIN_MIC);
} else if (strcmp(value, "sub") == 0) {
ALOGD("%s factory_test_mic_check=sub", __func__);
factory->in_device = (AUDIO_DEVICE_IN_BACK_MIC);
} else if (strcmp(value, "spk_mic1") == 0) { /*at + looptest=0,3,4 */
ALOGD("%s factory_test_mic_check=spk_mic1", __func__);
factory->in_device = (AUDIO_DEVICE_IN_BUILTIN_MIC);
} else if (strcmp(value, "off") == 0) {
ALOGD("%s factory_test_mic_check=off", __func__);
factory->mode = FACTORY_MODE_NONE;
factory->in_device = (AUDIO_DEVICE_NONE);
factory->rms_test_enable = false;
}
return;
}
void factory_set_parameters(struct audio_device *adev, struct str_parms *parms)
{
struct factory_manager *factory = adev->factory;
char *kv_pairs = str_parms_to_str(parms);
//ALOGV_IF(kv_pairs != NULL, "%s: enter: %s", __func__, kv_pairs);
char value[32];
int err = 0;
err = str_parms_get_str(parms, AUDIO_PARAMETER_FACTORY_TEST_TYPE, value, sizeof(value));
if (err >= 0 && factory) {
if (!strcmp(value, "codec")) {
factory->loopback_mode= FACTORY_LOOPBACK_CODEC;
} else if (!strcmp(value, "realtime")) {
factory->loopback_mode = FACTORY_LOOPBACK_REALTIME;
} else if (!strcmp(value, "pcm")) {
factory->loopback_mode = FACTORY_LOOPBACK_PCM;
} else if (!strcmp(value, "packet")) {
factory->loopback_mode = FACTORY_LOOPBACK_PACKET;
} else if (!strcmp(value, "packet_nodelay")) {
factory->loopback_mode = FACTORY_LOOPBACK_PACKET_NODELAY;
}
ALOGD("%s: FACTORY_TEST_TYPE=%d", __func__, factory->loopback_mode);
str_parms_del(parms, AUDIO_PARAMETER_FACTORY_TEST_TYPE);
}
err = str_parms_get_str(parms, AUDIO_PARAMETER_FACTORY_TEST_LOOPBACK, value, sizeof(value));
if (err >= 0 && factory) {
if (!strcmp(value, AUDIO_PARAMETER_VALUE_ON)) {
ALOGD("%s: FACTORY_TEST_LOOPBACK=on", __func__);
factory->mode = FACTORY_MODE_LOOPBACK;
#ifdef SUPPORT_STHAL_INTERFACE
proxy_call_status(adev->proxy, true);
#endif
} else if (!strcmp(value, AUDIO_PARAMETER_VALUE_OFF)) {
ALOGD("%s: FACTORY_TEST_LOOPBACK=off", __func__);
factory->mode = FACTORY_MODE_NONE;
factory->out_device = (AUDIO_DEVICE_NONE);
factory->in_device = (AUDIO_DEVICE_NONE);
/* 1. pcm device close */
if (factory->loopback_mode != FACTORY_LOOPBACK_REALTIME) {
voice_set_loopback_device(adev->voice, FACTORY_LOOPBACK_OFF,
AUDIO_DEVICE_OUT_EARPIECE, AUDIO_DEVICE_IN_BUILTIN_MIC);
proxy_stop_voice_call(adev->proxy);
}
factory->loopback_mode = FACTORY_LOOPBACK_OFF;
/* 2. reset device */
if (adev->primary_output != NULL) {
if (adev->primary_output->common.stream_status != STATUS_STANDBY)
adev_set_route((void *)adev->primary_output, AUSAGE_PLAYBACK, ROUTE, CALL_DRIVE);
else
adev_set_route((void *)adev->primary_output, AUSAGE_PLAYBACK, UNROUTE, CALL_DRIVE);
}
if (factory->loopback_mode != FACTORY_LOOPBACK_REALTIME) {
voice_set_call_mode(adev->voice, false);
}
#ifdef SUPPORT_STHAL_INTERFACE
proxy_call_status(adev->proxy, false);
#endif
}
str_parms_del(parms, AUDIO_PARAMETER_FACTORY_TEST_LOOPBACK);
}
err = str_parms_get_str(parms, AUDIO_PARAMETER_FACTORY_TEST_PATH, value, sizeof(value));
if (err > 0 && factory) {
factory_set_path_for_loopback(factory, value);
/* 1. set ril device */
if (factory->loopback_mode != FACTORY_LOOPBACK_REALTIME) {
voice_set_loopback_device(adev->voice, adev->factory->loopback_mode,
adev->factory->out_device, adev->factory->in_device);
}
/* 2. pcm device close for reset */
proxy_stop_voice_call(adev->proxy);
/* 3. set route */
if (adev->primary_output != NULL)
adev_set_route((void *)adev->primary_output, AUSAGE_PLAYBACK, ROUTE, CALL_DRIVE);
if (factory->loopback_mode != FACTORY_LOOPBACK_REALTIME) {
/* 4. pcm device open */
proxy_start_voice_call(adev->proxy);
/* 5. set volume */
voice_set_volume(adev->voice, adev->voice_volume);
/* 6. mic unmute */
voice_set_mic_mute(adev->voice, false);
}
str_parms_del(parms, AUDIO_PARAMETER_FACTORY_TEST_PATH);
}
err = str_parms_get_str(parms, AUDIO_PARAMETER_FACTORY_TEST_ROUTE, value, sizeof(value));
if (err > 0 && factory) {
factory_set_path_for_force_route(factory, value);
if (adev->primary_output != NULL) {
if (adev->primary_output->common.stream_status != STATUS_STANDBY)
adev_set_route((void *)adev->primary_output, AUSAGE_PLAYBACK, ROUTE, FORCE_ROUTE);
else
adev_set_route((void *)adev->primary_output, AUSAGE_PLAYBACK, UNROUTE, FORCE_ROUTE);
}
str_parms_del(parms, AUDIO_PARAMETER_FACTORY_TEST_ROUTE);
}
err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_FACTORY_RMS_TEST, value, sizeof(value));
if (err >= 0 && factory) {
factory_set_path_for_rms(factory, value);
if (adev->active_input != NULL
&& !(adev->active_input->requested_flags & AUDIO_INPUT_FLAG_HW_HOTWORD)
&& strcmp(value, "on") != 0)
adev_set_route((void *)adev->active_input, AUSAGE_CAPTURE, ROUTE, NON_FORCE_ROUTE);
str_parms_del(parms, AUDIO_PARAMETER_KEY_FACTORY_RMS_TEST);
}
//ALOGD("%s: exit", __func__);
free(kv_pairs);
return ;
}
void factory_deinit(struct factory_manager *factory)
{
if (factory)
free(factory);
return ;
}
struct factory_manager* factory_init()
{
struct factory_manager *factory = NULL;
factory = calloc(1, sizeof(struct factory_manager));
if (factory) {
factory->mode = FACTORY_MODE_NONE;
factory->loopback_mode= FACTORY_LOOPBACK_OFF;
factory->out_device = AUDIO_DEVICE_NONE;
factory->in_device = AUDIO_DEVICE_NONE;
factory->rms_test_enable = false;
factory->is_dspk_changed = false;
// false : SPK2 (rcv side spk) test, using mixer string "speaker2"
// true : SPK CAL test, using mixer string "dual-speaker"
factory->is_calibration_test = false;
}
return factory;
}