summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Android.mk3
-rw-r--r--BoardConfig.mk6
-rw-r--r--CleanSpec.mk1
-rw-r--r--audio/Android.mk4
-rw-r--r--[-rwxr-xr-x]audio/audio_hw.c786
-rw-r--r--audio/audio_policy.conf52
-rw-r--r--[-rwxr-xr-x]audio/ril_interface.c23
-rw-r--r--[-rwxr-xr-x]audio/ril_interface.h1
-rw-r--r--board-info.txt2
-rw-r--r--device.mk60
-rw-r--r--dumpstate/Android.mk2
-rw-r--r--egl.cfg4
-rw-r--r--full_tuna.mk4
-rw-r--r--gps.conf1
-rwxr-xr-xinit.tuna.rc49
-rwxr-xr-xinit.tuna.usb.rc38
-rw-r--r--kernelbin3918936 -> 4105396 bytes
-rw-r--r--keymaster/Android.mk43
-rw-r--r--keymaster/keymaster_tuna.cpp966
-rw-r--r--liblight/lights.c14
-rw-r--r--libsensors/SamsungSensorBase.cpp4
-rw-r--r--libsensors/sensors.cpp12
-rw-r--r--media_codecs.xml119
-rwxr-xr-xmedia_profiles.xml14
-rw-r--r--nfc/nfc_hw.c6
-rw-r--r--overlay/frameworks/base/core/res/res/values/config.xml10
-rw-r--r--overlay/frameworks/base/core/res/res/xml/storage_list.xml2
-rw-r--r--overlay/packages/apps/Settings/res/values-pl/arrays.xml12
-rw-r--r--overlay/packages/apps/Settings/res/values/bools.xml2
-rw-r--r--power/Android.mk27
-rw-r--r--power/power_tuna.c124
-rw-r--r--recovery/Android.mk2
-rw-r--r--recovery/recovery_ui.c115
-rw-r--r--recovery/recovery_ui.cpp111
-rw-r--r--sii9234_rcp.kcm15
-rw-r--r--sii9234_rcp.kl49
36 files changed, 2284 insertions, 399 deletions
diff --git a/Android.mk b/Android.mk
index 035d08a..0e3f37d 100644
--- a/Android.mk
+++ b/Android.mk
@@ -22,6 +22,7 @@
LOCAL_PATH := $(call my-dir)
+ifeq ($(BOARD_CREATE_TUNA_HDCP_KEYS_SYMLINK), true)
include $(CLEAR_VARS)
LOCAL_MODULE := tuna_hdcp_keys
@@ -44,3 +45,5 @@ $(LOCAL_BUILT_MODULE):
$(hide) touch $@
include $(call all-makefiles-under,$(LOCAL_PATH))
+
+endif
diff --git a/BoardConfig.mk b/BoardConfig.mk
index b1a43ac..7fa3d44 100644
--- a/BoardConfig.mk
+++ b/BoardConfig.mk
@@ -35,14 +35,18 @@ BOARD_KERNEL_BASE := 0x80000000
TARGET_NO_RADIOIMAGE := true
TARGET_BOARD_PLATFORM := omap4
TARGET_BOOTLOADER_BOARD_NAME := tuna
-TARGET_BOARD_INFO_FILE := device/samsung/tuna/board-info.txt
+TARGET_BOARD_INFO_FILE ?= device/samsung/tuna/board-info.txt
BOARD_EGL_CFG := device/samsung/tuna/egl.cfg
+BOARD_CREATE_TUNA_HDCP_KEYS_SYMLINK := true
#BOARD_USES_HGL := true
#BOARD_USES_OVERLAY := true
USE_OPENGL_RENDERER := true
+# set if the target supports FBIO_WAITFORVSYNC
+TARGET_HAS_WAITFORVSYNC := true
+
TARGET_RECOVERY_PIXEL_FORMAT := "BGRA_8888"
TARGET_RECOVERY_UI_LIB := librecovery_ui_tuna
diff --git a/CleanSpec.mk b/CleanSpec.mk
index cff019a..51b1305 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -50,3 +50,4 @@
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/root/default.prop)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/APPS/phone_intermediates)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/etc/updatecmds/migrate_nfc.txt)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib/hw/keystore.tuna.so)
diff --git a/audio/Android.mk b/audio/Android.mk
index 28aae85..e422761 100644
--- a/audio/Android.mk
+++ b/audio/Android.mk
@@ -21,8 +21,8 @@ LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
LOCAL_SRC_FILES := audio_hw.c ril_interface.c
LOCAL_C_INCLUDES += \
external/tinyalsa/include \
- system/media/audio_utils/include \
- system/media/audio_effects/include
+ $(call include-path-for, audio-utils) \
+ $(call include-path-for, audio-effects)
LOCAL_SHARED_LIBRARIES := liblog libcutils libtinyalsa libaudioutils libdl
LOCAL_MODULE_TAGS := optional
diff --git a/audio/audio_hw.c b/audio/audio_hw.c
index 850a1b1..403e5f3 100755..100644
--- a/audio/audio_hw.c
+++ b/audio/audio_hw.c
@@ -39,6 +39,7 @@
#include "ril_interface.h"
+
/* Mixer control names */
#define MIXER_DL2_LEFT_EQUALIZER "DL2 Left Equalizer"
#define MIXER_DL2_RIGHT_EQUALIZER "DL2 Right Equalizer"
@@ -399,6 +400,38 @@ struct route_setting mm_ul2_amic_right[] = {
},
};
+/* dual mic configuration with main mic on main channel and sub mic on aux channel.
+ * Used for handset mode (near talk) */
+struct route_setting mm_ul2_amic_dual_main_sub[] = {
+ {
+ .ctl_name = MIXER_MUX_UL10,
+ .strval = MIXER_AMIC0,
+ },
+ {
+ .ctl_name = MIXER_MUX_UL11,
+ .strval = MIXER_AMIC1,
+ },
+ {
+ .ctl_name = NULL,
+ },
+};
+
+/* dual mic configuration with sub mic on main channel and main mic on aux channel.
+ * Used for speakerphone mode (far talk) */
+struct route_setting mm_ul2_amic_dual_sub_main[] = {
+ {
+ .ctl_name = MIXER_MUX_UL10,
+ .strval = MIXER_AMIC1,
+ },
+ {
+ .ctl_name = MIXER_MUX_UL11,
+ .strval = MIXER_AMIC0,
+ },
+ {
+ .ctl_name = NULL,
+ },
+};
+
/* VX UL front-end paths */
struct route_setting vx_ul_amic_left[] = {
{
@@ -483,7 +516,7 @@ struct tuna_audio_device {
pthread_mutex_t lock; /* see note below on mutex acquisition order */
struct mixer *mixer;
struct mixer_ctls mixer_ctls;
- int mode;
+ audio_mode_t mode;
int devices;
struct pcm *pcm_modem_dl;
struct pcm *pcm_modem_ul;
@@ -527,6 +560,19 @@ struct tuna_stream_out {
#define MAX_PREPROCESSORS 3 /* maximum one AGC + one NS + one AEC per input stream */
+struct effect_info_s {
+ effect_handle_t effect_itfe;
+ size_t num_channel_configs;
+ channel_config_t* channel_configs;
+};
+
+#define NUM_IN_AUX_CNL_CONFIGS 2
+channel_config_t in_aux_cnl_configs[NUM_IN_AUX_CNL_CONFIGS] = {
+ { AUDIO_CHANNEL_IN_FRONT , AUDIO_CHANNEL_IN_BACK},
+ { AUDIO_CHANNEL_IN_STEREO , AUDIO_CHANNEL_IN_RIGHT}
+};
+
+
struct tuna_stream_in {
struct audio_stream_in stream;
@@ -536,23 +582,33 @@ struct tuna_stream_in {
int device;
struct resampler_itfe *resampler;
struct resampler_buffer_provider buf_provider;
- int16_t *buffer;
- size_t frames_in;
unsigned int requested_rate;
int standby;
int source;
struct echo_reference_itfe *echo_reference;
bool need_echo_reference;
- effect_handle_t preprocessors[MAX_PREPROCESSORS];
- int num_preprocessors;
- int16_t *proc_buf;
+
+ int16_t *read_buf;
+ size_t read_buf_size;
+ size_t read_buf_frames;
+
+ int16_t *proc_buf_in;
+ int16_t *proc_buf_out;
size_t proc_buf_size;
- size_t proc_frames_in;
+ size_t proc_buf_frames;
+
int16_t *ref_buf;
size_t ref_buf_size;
- size_t ref_frames_in;
+ size_t ref_buf_frames;
+
int read_status;
+ int num_preprocessors;
+ struct effect_info_s preprocessors[MAX_PREPROCESSORS];
+
+ bool aux_channels_changed;
+ uint32_t main_channels;
+ uint32_t aux_channels;
struct tuna_audio_device *dev;
};
@@ -567,6 +623,7 @@ static void select_input_device(struct tuna_audio_device *adev);
static int adev_set_voice_volume(struct audio_hw_device *dev, float volume);
static int do_input_standby(struct tuna_stream_in *in);
static int do_output_standby(struct tuna_stream_out *out);
+static void in_update_aux_channels(struct tuna_stream_in *in, effect_handle_t effect);
/* Returns true on devices that are toro, false otherwise */
static int is_device_toro(void)
@@ -616,7 +673,7 @@ static int set_route_by_array(struct mixer *mixer, struct route_setting *route,
static int start_call(struct tuna_audio_device *adev)
{
- LOGE("Opening modem PCMs");
+ ALOGE("Opening modem PCMs");
pcm_config_vx.rate = adev->wb_amr ? VX_WB_SAMPLING_RATE : VX_NB_SAMPLING_RATE;
@@ -624,7 +681,7 @@ static int start_call(struct tuna_audio_device *adev)
if (adev->pcm_modem_dl == NULL) {
adev->pcm_modem_dl = pcm_open(0, PORT_MODEM, PCM_OUT, &pcm_config_vx);
if (!pcm_is_ready(adev->pcm_modem_dl)) {
- LOGE("cannot open PCM modem DL stream: %s", pcm_get_error(adev->pcm_modem_dl));
+ ALOGE("cannot open PCM modem DL stream: %s", pcm_get_error(adev->pcm_modem_dl));
goto err_open_dl;
}
}
@@ -632,7 +689,7 @@ static int start_call(struct tuna_audio_device *adev)
if (adev->pcm_modem_ul == NULL) {
adev->pcm_modem_ul = pcm_open(0, PORT_MODEM, PCM_IN, &pcm_config_vx);
if (!pcm_is_ready(adev->pcm_modem_ul)) {
- LOGE("cannot open PCM modem UL stream: %s", pcm_get_error(adev->pcm_modem_ul));
+ ALOGE("cannot open PCM modem UL stream: %s", pcm_get_error(adev->pcm_modem_ul));
goto err_open_ul;
}
}
@@ -654,7 +711,7 @@ err_open_dl:
static void end_call(struct tuna_audio_device *adev)
{
- LOGE("Closing modem PCMs");
+ ALOGE("Closing modem PCMs");
pcm_stop(adev->pcm_modem_dl);
pcm_stop(adev->pcm_modem_ul);
@@ -740,7 +797,7 @@ static void set_input_volumes(struct tuna_audio_device *adev, int main_mic_on,
if (adev->mode == AUDIO_MODE_IN_CALL) {
int sub_mic_volume = is_device_toro() ? VOICE_CALL_SUB_MIC_VOLUME_TORO :
- VOICE_CALL_SUB_MIC_VOLUME_MAGURO;
+ VOICE_CALL_SUB_MIC_VOLUME_MAGURO;
/* special case: don't look at input source for IN_CALL state */
volume = DB_TO_ABE_GAIN(main_mic_on ? VOICE_CALL_MAIN_MIC_VOLUME :
(headset_mic_on ? VOICE_CALL_HEADSET_MIC_VOLUME :
@@ -876,7 +933,7 @@ static void force_all_standby(struct tuna_audio_device *adev)
static void select_mode(struct tuna_audio_device *adev)
{
if (adev->mode == AUDIO_MODE_IN_CALL) {
- LOGE("Entering IN_CALL state, in_call=%d", adev->in_call);
+ ALOGE("Entering IN_CALL state, in_call=%d", adev->in_call);
if (!adev->in_call) {
force_all_standby(adev);
/* force earpiece route for in call state if speaker is the
@@ -896,12 +953,11 @@ static void select_mode(struct tuna_audio_device *adev)
adev->devices &= ~AUDIO_DEVICE_OUT_SPEAKER;
select_output_device(adev);
start_call(adev);
- ril_set_call_clock_sync(&adev->ril, SOUND_CLOCK_START);
adev_set_voice_volume(&adev->hw_device, adev->voice_volume);
adev->in_call = 1;
}
} else {
- LOGE("Leaving IN_CALL state, in_call=%d, mode=%d",
+ ALOGE("Leaving IN_CALL state, in_call=%d, mode=%d",
adev->in_call, adev->mode);
if (adev->in_call) {
adev->in_call = 0;
@@ -1083,12 +1139,32 @@ static void select_input_device(struct tuna_audio_device *adev)
set_route_by_array(adev->mixer, mm_ul2_bt, 1);
else {
/* Select front end */
- if (main_mic_on || headset_on)
- set_route_by_array(adev->mixer, mm_ul2_amic_left, 1);
- else if (sub_mic_on)
- set_route_by_array(adev->mixer, mm_ul2_amic_right, 1);
- else
- set_route_by_array(adev->mixer, mm_ul2_amic_left, 0);
+
+
+ if ((adev->active_input != 0) && (adev->active_input->aux_channels)) {
+ ALOGV("select input device(): multi-mic configuration main mic %s sub mic %s",
+ main_mic_on ? "ON" : "OFF", sub_mic_on ? "ON" : "OFF");
+ if (main_mic_on) {
+ set_route_by_array(adev->mixer, mm_ul2_amic_dual_main_sub, 1);
+ sub_mic_on = 1;
+ }
+ else if (sub_mic_on) {
+ set_route_by_array(adev->mixer, mm_ul2_amic_dual_sub_main, 1);
+ main_mic_on = 1;
+ }
+ else {
+ set_route_by_array(adev->mixer, mm_ul2_amic_dual_main_sub, 0);
+ }
+ } else {
+ ALOGV("select input device(): single mic configuration");
+ if (main_mic_on || headset_on)
+ set_route_by_array(adev->mixer, mm_ul2_amic_left, 1);
+ else if (sub_mic_on)
+ set_route_by_array(adev->mixer, mm_ul2_amic_right, 1);
+ else
+ set_route_by_array(adev->mixer, mm_ul2_amic_left, 0);
+ }
+
/* Select back end */
mixer_ctl_set_enum_by_string(adev->mixer_ctls.right_capture,
@@ -1147,7 +1223,7 @@ static int start_output_stream(struct tuna_stream_out *out)
/* Close any PCMs that could not be opened properly and return an error */
for (i = 0; i < PCM_TOTAL; i++) {
if (out->pcm[i] && !pcm_is_ready(out->pcm[i])) {
- LOGE("cannot open pcm_out driver: %s", pcm_get_error(out->pcm[i]));
+ ALOGE("cannot open pcm_out driver: %s", pcm_get_error(out->pcm[i]));
pcm_close(out->pcm[i]);
out->pcm[i] = NULL;
success = false;
@@ -1166,7 +1242,7 @@ static int start_output_stream(struct tuna_stream_out *out)
return -ENOMEM;
}
-static int check_input_parameters(uint32_t sample_rate, int format, int channel_count)
+static int check_input_parameters(uint32_t sample_rate, audio_format_t format, int channel_count)
{
if (format != AUDIO_FORMAT_PCM_16_BIT)
return -EINVAL;
@@ -1191,7 +1267,7 @@ static int check_input_parameters(uint32_t sample_rate, int format, int channel_
return 0;
}
-static size_t get_input_buffer_size(uint32_t sample_rate, int format, int channel_count)
+static size_t get_input_buffer_size(uint32_t sample_rate, audio_format_t format, int channel_count)
{
size_t size;
size_t device_rate;
@@ -1281,7 +1357,7 @@ static int get_playback_delay(struct tuna_stream_out *out,
buffer->time_stamp.tv_sec = 0;
buffer->time_stamp.tv_nsec = 0;
buffer->delay_ns = 0;
- LOGV("get_playback_delay(): pcm_get_htimestamp error,"
+ ALOGV("get_playback_delay(): pcm_get_htimestamp error,"
"setting playbackTimestamp to 0");
return status;
}
@@ -1325,12 +1401,12 @@ static uint32_t out_get_channels(const struct audio_stream *stream)
return AUDIO_CHANNEL_OUT_STEREO;
}
-static int out_get_format(const struct audio_stream *stream)
+static audio_format_t out_get_format(const struct audio_stream *stream)
{
return AUDIO_FORMAT_PCM_16_BIT;
}
-static int out_set_format(struct audio_stream *stream, int format)
+static int out_set_format(struct audio_stream *stream, audio_format_t format)
{
return 0;
}
@@ -1432,7 +1508,8 @@ static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
(adev->devices & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET)) ||
(adev->devices & (AUDIO_DEVICE_OUT_AUX_DIGITAL |
AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET)) ||
- (val == AUDIO_DEVICE_OUT_SPEAKER))
+ ((val & AUDIO_DEVICE_OUT_SPEAKER) ^
+ (adev->devices & AUDIO_DEVICE_OUT_SPEAKER)))
do_output_standby(out);
}
adev->devices &= ~AUDIO_DEVICE_OUT_ALL;
@@ -1485,7 +1562,6 @@ static ssize_t out_write(struct audio_stream_out *stream, const void* buffer,
struct tuna_stream_in *in;
bool low_power;
int kernel_frames;
- void *buf;
/* If we're in out_write, we will find at least one pcm active */
int primary_pcm = -1;
int i;
@@ -1645,6 +1721,27 @@ static int start_input_stream(struct tuna_stream_in *in)
select_input_device(adev);
}
+ if (in->aux_channels_changed)
+ {
+ in->aux_channels_changed = false;
+ in->config.channels = popcount(in->main_channels | in->aux_channels);
+
+ if (in->resampler) {
+ /* release and recreate the resampler with the new number of channel of the input */
+ release_resampler(in->resampler);
+ in->resampler = NULL;
+ ret = create_resampler(in->config.rate,
+ in->requested_rate,
+ in->config.channels,
+ RESAMPLER_QUALITY_DEFAULT,
+ &in->buf_provider,
+ &in->resampler);
+ }
+ ALOGV("start_input_stream(): New channel configuration, "
+ "main_channels = [%04x], aux_channels = [%04x], config.channels = %d",
+ in->main_channels, in->aux_channels, in->config.channels);
+ }
+
if (in->need_echo_reference && in->echo_reference == NULL)
in->echo_reference = get_echo_reference(adev,
AUDIO_FORMAT_PCM_16_BIT,
@@ -1654,16 +1751,20 @@ static int start_input_stream(struct tuna_stream_in *in)
/* this assumes routing is done previously */
in->pcm = pcm_open(0, PORT_MM2_UL, PCM_IN, &in->config);
if (!pcm_is_ready(in->pcm)) {
- LOGE("cannot open pcm_in driver: %s", pcm_get_error(in->pcm));
+ ALOGE("cannot open pcm_in driver: %s", pcm_get_error(in->pcm));
pcm_close(in->pcm);
adev->active_input = NULL;
return -ENOMEM;
}
+ /* force read and proc buf reallocation case of frame size or channel count change */
+ in->read_buf_frames = 0;
+ in->read_buf_size = 0;
+ in->proc_buf_frames = 0;
+ in->proc_buf_size = 0;
/* if no supported sample rate is available, use the resampler */
if (in->resampler) {
in->resampler->reset(in->resampler);
- in->frames_in = 0;
}
return 0;
}
@@ -1686,26 +1787,22 @@ static size_t in_get_buffer_size(const struct audio_stream *stream)
return get_input_buffer_size(in->requested_rate,
AUDIO_FORMAT_PCM_16_BIT,
- in->config.channels);
+ popcount(in->main_channels));
}
static uint32_t in_get_channels(const struct audio_stream *stream)
{
struct tuna_stream_in *in = (struct tuna_stream_in *)stream;
- if (in->config.channels == 1) {
- return AUDIO_CHANNEL_IN_MONO;
- } else {
- return AUDIO_CHANNEL_IN_STEREO;
- }
+ return in->main_channels;
}
-static int in_get_format(const struct audio_stream *stream)
+static audio_format_t in_get_format(const struct audio_stream *stream)
{
return AUDIO_FORMAT_PCM_16_BIT;
}
-static int in_set_format(struct audio_stream *stream, int format)
+static int in_set_format(struct audio_stream *stream, audio_format_t format)
{
return 0;
}
@@ -1786,6 +1883,9 @@ static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
if ((in->device != val) && (val != 0)) {
in->device = val;
do_standby = true;
+ /* make sure new device selection is incompatible with multi-mic pre processing
+ * configuration */
+ in_update_aux_channels(in, NULL);
}
}
@@ -1826,15 +1926,19 @@ static void get_capture_delay(struct tuna_stream_in *in,
buffer->time_stamp.tv_sec = 0;
buffer->time_stamp.tv_nsec = 0;
buffer->delay_ns = 0;
- LOGW("read get_capture_delay(): pcm_htimestamp error");
+ ALOGW("read get_capture_delay(): pcm_htimestamp error");
return;
}
/* read frames available in audio HAL input buffer
* add number of frames being read as we want the capture time of first sample
* in current buffer */
- buf_delay = (long)(((int64_t)(in->frames_in + in->proc_frames_in) * 1000000000)
- / in->config.rate);
+ /* frames in in->buffer are at driver sampling rate while frames in in->proc_buf are
+ * at requested sampling rate */
+ buf_delay = (long)(((int64_t)(in->read_buf_frames) * 1000000000) / in->config.rate +
+ ((int64_t)(in->proc_buf_frames) * 1000000000) /
+ in->requested_rate);
+
/* add delay introduced by resampler */
rsmp_delay = 0;
if (in->resampler) {
@@ -1847,12 +1951,12 @@ static void get_capture_delay(struct tuna_stream_in *in,
buffer->time_stamp = tstamp;
buffer->delay_ns = delay_ns;
- LOGV("get_capture_delay time_stamp = [%ld].[%ld], delay_ns: [%d],"
+ ALOGV("get_capture_delay time_stamp = [%ld].[%ld], delay_ns: [%d],"
" kernel_delay:[%ld], buf_delay:[%ld], rsmp_delay:[%ld], kernel_frames:[%d], "
- "in->frames_in:[%d], in->proc_frames_in:[%d], frames:[%d]",
+ "in->read_buf_frames:[%d], in->proc_buf_frames:[%d], frames:[%d]",
buffer->time_stamp.tv_sec , buffer->time_stamp.tv_nsec, buffer->delay_ns,
kernel_delay, buf_delay, rsmp_delay, kernel_frames,
- in->frames_in, in->proc_frames_in, frames);
+ in->read_buf_frames, in->proc_buf_frames, frames);
}
@@ -1861,31 +1965,32 @@ static int32_t update_echo_reference(struct tuna_stream_in *in, size_t frames)
struct echo_reference_buffer b;
b.delay_ns = 0;
- LOGV("update_echo_reference, frames = [%d], in->ref_frames_in = [%d], "
+ ALOGV("update_echo_reference, frames = [%d], in->ref_buf_frames = [%d], "
"b.frame_count = [%d]",
- frames, in->ref_frames_in, frames - in->ref_frames_in);
- if (in->ref_frames_in < frames) {
+ frames, in->ref_buf_frames, frames - in->ref_buf_frames);
+ if (in->ref_buf_frames < frames) {
if (in->ref_buf_size < frames) {
in->ref_buf_size = frames;
- in->ref_buf = (int16_t *)realloc(in->ref_buf,
- in->ref_buf_size *
- in->config.channels * sizeof(int16_t));
+ in->ref_buf = (int16_t *)realloc(in->ref_buf, pcm_frames_to_bytes(in->pcm, frames));
+ ALOG_ASSERT((in->ref_buf != NULL),
+ "update_echo_reference() failed to reallocate ref_buf");
+ ALOGV("update_echo_reference(): ref_buf %p extended to %d bytes",
+ in->ref_buf, pcm_frames_to_bytes(in->pcm, frames));
}
-
- b.frame_count = frames - in->ref_frames_in;
- b.raw = (void *)(in->ref_buf + in->ref_frames_in * in->config.channels);
+ b.frame_count = frames - in->ref_buf_frames;
+ b.raw = (void *)(in->ref_buf + in->ref_buf_frames * in->config.channels);
get_capture_delay(in, frames, &b);
if (in->echo_reference->read(in->echo_reference, &b) == 0)
{
- in->ref_frames_in += b.frame_count;
- LOGV("update_echo_reference: in->ref_frames_in:[%d], "
+ in->ref_buf_frames += b.frame_count;
+ ALOGV("update_echo_reference(): in->ref_buf_frames:[%d], "
"in->ref_buf_size:[%d], frames:[%d], b.frame_count:[%d]",
- in->ref_frames_in, in->ref_buf_size, frames, b.frame_count);
+ in->ref_buf_frames, in->ref_buf_size, frames, b.frame_count);
}
} else
- LOGW("update_echo_reference: NOT enough frames to read ref buffer");
+ ALOGW("update_echo_reference(): NOT enough frames to read ref buffer");
return b.delay_ns;
}
@@ -1925,32 +2030,32 @@ static int set_preprocessor_echo_delay(effect_handle_t handle,
static void push_echo_reference(struct tuna_stream_in *in, size_t frames)
{
/* read frames from echo reference buffer and update echo delay
- * in->ref_frames_in is updated with frames available in in->ref_buf */
+ * in->ref_buf_frames is updated with frames available in in->ref_buf */
int32_t delay_us = update_echo_reference(in, frames)/1000;
int i;
audio_buffer_t buf;
- if (in->ref_frames_in < frames)
- frames = in->ref_frames_in;
+ if (in->ref_buf_frames < frames)
+ frames = in->ref_buf_frames;
buf.frameCount = frames;
buf.raw = in->ref_buf;
for (i = 0; i < in->num_preprocessors; i++) {
- if ((*in->preprocessors[i])->process_reverse == NULL)
+ if ((*in->preprocessors[i].effect_itfe)->process_reverse == NULL)
continue;
- (*in->preprocessors[i])->process_reverse(in->preprocessors[i],
+ (*in->preprocessors[i].effect_itfe)->process_reverse(in->preprocessors[i].effect_itfe,
&buf,
NULL);
- set_preprocessor_echo_delay(in->preprocessors[i], delay_us);
+ set_preprocessor_echo_delay(in->preprocessors[i].effect_itfe, delay_us);
}
- in->ref_frames_in -= buf.frameCount;
- if (in->ref_frames_in) {
+ in->ref_buf_frames -= buf.frameCount;
+ if (in->ref_buf_frames) {
memcpy(in->ref_buf,
in->ref_buf + buf.frameCount * in->config.channels,
- in->ref_frames_in * in->config.channels * sizeof(int16_t));
+ in->ref_buf_frames * in->config.channels * sizeof(int16_t));
}
}
@@ -1972,23 +2077,31 @@ static int get_next_buffer(struct resampler_buffer_provider *buffer_provider,
return -ENODEV;
}
- if (in->frames_in == 0) {
- in->read_status = pcm_read(in->pcm,
- (void*)in->buffer,
- in->config.period_size *
- audio_stream_frame_size(&in->stream.common));
+ if (in->read_buf_frames == 0) {
+ size_t size_in_bytes = pcm_frames_to_bytes(in->pcm, in->config.period_size);
+ if (in->read_buf_size < in->config.period_size) {
+ in->read_buf_size = in->config.period_size;
+ in->read_buf = (int16_t *) realloc(in->read_buf, size_in_bytes);
+ ALOG_ASSERT((in->read_buf != NULL),
+ "get_next_buffer() failed to reallocate read_buf");
+ ALOGV("get_next_buffer(): read_buf %p extended to %d bytes",
+ in->read_buf, size_in_bytes);
+ }
+
+ in->read_status = pcm_read(in->pcm, (void*)in->read_buf, size_in_bytes);
+
if (in->read_status != 0) {
- LOGE("get_next_buffer() pcm_read error %d", in->read_status);
+ ALOGE("get_next_buffer() pcm_read error %d", in->read_status);
buffer->raw = NULL;
buffer->frame_count = 0;
return in->read_status;
}
- in->frames_in = in->config.period_size;
+ in->read_buf_frames = in->config.period_size;
}
- buffer->frame_count = (buffer->frame_count > in->frames_in) ?
- in->frames_in : buffer->frame_count;
- buffer->i16 = in->buffer + (in->config.period_size - in->frames_in) *
+ buffer->frame_count = (buffer->frame_count > in->read_buf_frames) ?
+ in->read_buf_frames : buffer->frame_count;
+ buffer->i16 = in->read_buf + (in->config.period_size - in->read_buf_frames) *
in->config.channels;
return in->read_status;
@@ -2006,7 +2119,7 @@ static void release_buffer(struct resampler_buffer_provider *buffer_provider,
in = (struct tuna_stream_in *)((char *)buffer_provider -
offsetof(struct tuna_stream_in, buf_provider));
- in->frames_in -= buffer->frame_count;
+ in->read_buf_frames -= buffer->frame_count;
}
/* read_frames() reads frames from kernel driver, down samples to capture rate
@@ -2019,9 +2132,10 @@ static ssize_t read_frames(struct tuna_stream_in *in, void *buffer, ssize_t fram
size_t frames_rd = frames - frames_wr;
if (in->resampler != NULL) {
in->resampler->resample_from_provider(in->resampler,
- (int16_t *)((char *)buffer +
- frames_wr * audio_stream_frame_size(&in->stream.common)),
- &frames_rd);
+ (int16_t *)((char *)buffer +
+ pcm_frames_to_bytes(in->pcm ,frames_wr)),
+ &frames_rd);
+
} else {
struct resampler_buffer buf = {
{ raw : NULL, },
@@ -2030,9 +2144,9 @@ static ssize_t read_frames(struct tuna_stream_in *in, void *buffer, ssize_t fram
get_next_buffer(&in->buf_provider, &buf);
if (buf.raw != NULL) {
memcpy((char *)buffer +
- frames_wr * audio_stream_frame_size(&in->stream.common),
+ pcm_frames_to_bytes(in->pcm, frames_wr),
buf.raw,
- buf.frame_count * audio_stream_frame_size(&in->stream.common));
+ pcm_frames_to_bytes(in->pcm, buf.frame_count));
frames_rd = buf.frame_count;
}
release_buffer(&in->buf_provider, &buf);
@@ -2056,66 +2170,127 @@ static ssize_t process_frames(struct tuna_stream_in *in, void* buffer, ssize_t f
audio_buffer_t in_buf;
audio_buffer_t out_buf;
int i;
+ bool has_aux_channels = (~in->main_channels & in->aux_channels);
+ void *proc_buf_out;
+
+ if (has_aux_channels)
+ proc_buf_out = in->proc_buf_out;
+ else
+ proc_buf_out = buffer;
+ /* since all the processing below is done in frames and using the config.channels
+ * as the number of channels, no changes is required in case aux_channels are present */
while (frames_wr < frames) {
/* first reload enough frames at the end of process input buffer */
- if (in->proc_frames_in < (size_t)frames) {
+ if (in->proc_buf_frames < (size_t)frames) {
ssize_t frames_rd;
if (in->proc_buf_size < (size_t)frames) {
+ size_t size_in_bytes = pcm_frames_to_bytes(in->pcm, frames);
+
in->proc_buf_size = (size_t)frames;
- in->proc_buf = (int16_t *)realloc(in->proc_buf,
- in->proc_buf_size *
- in->config.channels * sizeof(int16_t));
- LOGV("process_frames(): in->proc_buf %p size extended to %d frames",
- in->proc_buf, in->proc_buf_size);
+ in->proc_buf_in = (int16_t *)realloc(in->proc_buf_in, size_in_bytes);
+ ALOG_ASSERT((in->proc_buf_in != NULL),
+ "process_frames() failed to reallocate proc_buf_in");
+ if (has_aux_channels) {
+ in->proc_buf_out = (int16_t *)realloc(in->proc_buf_out, size_in_bytes);
+ ALOG_ASSERT((in->proc_buf_out != NULL),
+ "process_frames() failed to reallocate proc_buf_out");
+ proc_buf_out = in->proc_buf_out;
+ }
+ ALOGV("process_frames(): proc_buf_in %p extended to %d bytes",
+ in->proc_buf_in, size_in_bytes);
}
frames_rd = read_frames(in,
- in->proc_buf +
- in->proc_frames_in * in->config.channels,
- frames - in->proc_frames_in);
+ in->proc_buf_in +
+ in->proc_buf_frames * in->config.channels,
+ frames - in->proc_buf_frames);
if (frames_rd < 0) {
frames_wr = frames_rd;
break;
}
- in->proc_frames_in += frames_rd;
+ in->proc_buf_frames += frames_rd;
}
if (in->echo_reference != NULL)
- push_echo_reference(in, in->proc_frames_in);
+ push_echo_reference(in, in->proc_buf_frames);
/* in_buf.frameCount and out_buf.frameCount indicate respectively
* the maximum number of frames to be consumed and produced by process() */
- in_buf.frameCount = in->proc_frames_in;
- in_buf.s16 = in->proc_buf;
+ in_buf.frameCount = in->proc_buf_frames;
+ in_buf.s16 = in->proc_buf_in;
out_buf.frameCount = frames - frames_wr;
- out_buf.s16 = (int16_t *)buffer + frames_wr * in->config.channels;
-
- for (i = 0; i < in->num_preprocessors; i++)
- (*in->preprocessors[i])->process(in->preprocessors[i],
+ out_buf.s16 = (int16_t *)proc_buf_out + frames_wr * in->config.channels;
+
+ /* FIXME: this works because of current pre processing library implementation that
+ * does the actual process only when the last enabled effect process is called.
+ * The generic solution is to have an output buffer for each effect and pass it as
+ * input to the next.
+ */
+ for (i = 0; i < in->num_preprocessors; i++) {
+ (*in->preprocessors[i].effect_itfe)->process(in->preprocessors[i].effect_itfe,
&in_buf,
&out_buf);
+ }
/* process() has updated the number of frames consumed and produced in
* in_buf.frameCount and out_buf.frameCount respectively
- * move remaining frames to the beginning of in->proc_buf */
- in->proc_frames_in -= in_buf.frameCount;
- if (in->proc_frames_in) {
- memcpy(in->proc_buf,
- in->proc_buf + in_buf.frameCount * in->config.channels,
- in->proc_frames_in * in->config.channels * sizeof(int16_t));
+ * move remaining frames to the beginning of in->proc_buf_in */
+ in->proc_buf_frames -= in_buf.frameCount;
+
+ if (in->proc_buf_frames) {
+ memcpy(in->proc_buf_in,
+ in->proc_buf_in + in_buf.frameCount * in->config.channels,
+ in->proc_buf_frames * in->config.channels * sizeof(int16_t));
}
/* if not enough frames were passed to process(), read more and retry. */
- if (out_buf.frameCount == 0)
+ if (out_buf.frameCount == 0) {
+ ALOGW("No frames produced by preproc");
continue;
+ }
- frames_wr += out_buf.frameCount;
+ if ((frames_wr + (ssize_t)out_buf.frameCount) <= frames) {
+ frames_wr += out_buf.frameCount;
+ } else {
+ /* The effect does not comply to the API. In theory, we should never end up here! */
+ ALOGE("preprocessing produced too many frames: %d + %d > %d !",
+ (unsigned int)frames_wr, out_buf.frameCount, (unsigned int)frames);
+ frames_wr = frames;
+ }
}
+
+ /* Remove aux_channels that have been added on top of main_channels
+ * Assumption is made that the channels are interleaved and that the main
+ * channels are first. */
+ if (has_aux_channels)
+ {
+ size_t src_channels = in->config.channels;
+ size_t dst_channels = popcount(in->main_channels);
+ int16_t* src_buffer = (int16_t *)proc_buf_out;
+ int16_t* dst_buffer = (int16_t *)buffer;
+
+ if (dst_channels == 1) {
+ for (i = frames_wr; i > 0; i--)
+ {
+ *dst_buffer++ = *src_buffer;
+ src_buffer += src_channels;
+ }
+ } else {
+ for (i = frames_wr; i > 0; i--)
+ {
+ memcpy(dst_buffer, src_buffer, dst_channels*sizeof(int16_t));
+ dst_buffer += dst_channels;
+ src_buffer += src_channels;
+ }
+ }
+ }
+
return frames_wr;
}
static ssize_t in_read(struct audio_stream_in *stream, void* buffer,
+
size_t bytes)
{
int ret = 0;
@@ -2166,6 +2341,284 @@ static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream)
return 0;
}
+#define GET_COMMAND_STATUS(status, fct_status, cmd_status) \
+ do { \
+ if (fct_status != 0) \
+ status = fct_status; \
+ else if (cmd_status != 0) \
+ status = cmd_status; \
+ } while(0)
+
+static int in_configure_reverse(struct tuna_stream_in *in)
+{
+ int32_t cmd_status;
+ uint32_t size = sizeof(int);
+ effect_config_t config;
+ int32_t status = 0;
+ int32_t fct_status = 0;
+ int i;
+
+ if (in->num_preprocessors > 0) {
+ config.inputCfg.channels = in->main_channels;
+ config.outputCfg.channels = in->main_channels;
+ config.inputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
+ config.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
+ config.inputCfg.samplingRate = in->requested_rate;
+ config.outputCfg.samplingRate = in->requested_rate;
+ config.inputCfg.mask =
+ ( EFFECT_CONFIG_SMP_RATE | EFFECT_CONFIG_CHANNELS | EFFECT_CONFIG_FORMAT );
+ config.outputCfg.mask =
+ ( EFFECT_CONFIG_SMP_RATE | EFFECT_CONFIG_CHANNELS | EFFECT_CONFIG_FORMAT );
+
+ for (i = 0; i < in->num_preprocessors; i++)
+ {
+ if ((*in->preprocessors[i].effect_itfe)->process_reverse == NULL)
+ continue;
+ fct_status = (*(in->preprocessors[i].effect_itfe))->command(
+ in->preprocessors[i].effect_itfe,
+ EFFECT_CMD_SET_CONFIG_REVERSE,
+ sizeof(effect_config_t),
+ &config,
+ &size,
+ &cmd_status);
+ GET_COMMAND_STATUS(status, fct_status, cmd_status);
+ }
+ }
+ return status;
+}
+
+#define MAX_NUM_CHANNEL_CONFIGS 10
+
+static void in_read_audio_effect_channel_configs(struct tuna_stream_in *in,
+ struct effect_info_s *effect_info)
+{
+ /* size and format of the cmd are defined in hardware/audio_effect.h */
+ effect_handle_t effect = effect_info->effect_itfe;
+ uint32_t cmd_size = 2 * sizeof(uint32_t);
+ uint32_t cmd[] = { EFFECT_FEATURE_AUX_CHANNELS, MAX_NUM_CHANNEL_CONFIGS };
+ /* reply = status + number of configs (n) + n x channel_config_t */
+ uint32_t reply_size =
+ 2 * sizeof(uint32_t) + (MAX_NUM_CHANNEL_CONFIGS * sizeof(channel_config_t));
+ int32_t reply[reply_size];
+ int32_t cmd_status;
+
+ ALOG_ASSERT((effect_info->num_channel_configs == 0),
+ "in_read_audio_effect_channel_configs() num_channel_configs not cleared");
+ ALOG_ASSERT((effect_info->channel_configs == NULL),
+ "in_read_audio_effect_channel_configs() channel_configs not cleared");
+
+ /* if this command is not supported, then the effect is supposed to return -EINVAL.
+ * This error will be interpreted as if the effect supports the main_channels but does not
+ * support any aux_channels */
+ cmd_status = (*effect)->command(effect,
+ EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS,
+ cmd_size,
+ (void*)&cmd,
+ &reply_size,
+ (void*)&reply);
+
+ if (cmd_status != 0) {
+ ALOGV("in_read_audio_effect_channel_configs(): "
+ "fx->command returned %d", cmd_status);
+ return;
+ }
+
+ if (reply[0] != 0) {
+ ALOGW("in_read_audio_effect_channel_configs(): "
+ "command EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS error %d num configs %d",
+ reply[0], (reply[0] == -ENOMEM) ? reply[1] : MAX_NUM_CHANNEL_CONFIGS);
+ return;
+ }
+
+ /* the feature is not supported */
+ ALOGV("in_read_audio_effect_channel_configs()(): "
+ "Feature supported and adding %d channel configs to the list", reply[1]);
+ effect_info->num_channel_configs = reply[1];
+ effect_info->channel_configs =
+ (channel_config_t *) malloc(sizeof(channel_config_t) * reply[1]); /* n x configs */
+ memcpy(effect_info->channel_configs, (reply + 2), sizeof(channel_config_t) * reply[1]);
+}
+
+
+static uint32_t in_get_aux_channels(struct tuna_stream_in *in)
+{
+ int i;
+ channel_config_t new_chcfg = {0, 0};
+
+ if (in->num_preprocessors == 0)
+ return 0;
+
+ /* do not enable dual mic configurations when capturing from other microphones than
+ * main or sub */
+ if (!(in->device & (AUDIO_DEVICE_IN_BUILTIN_MIC | AUDIO_DEVICE_IN_BACK_MIC)))
+ return 0;
+
+ /* retain most complex aux channels configuration compatible with requested main channels and
+ * supported by audio driver and all pre processors */
+ for (i = 0; i < NUM_IN_AUX_CNL_CONFIGS; i++) {
+ channel_config_t *cur_chcfg = &in_aux_cnl_configs[i];
+ if (cur_chcfg->main_channels == in->main_channels) {
+ size_t match_cnt;
+ size_t idx_preproc;
+ for (idx_preproc = 0, match_cnt = 0;
+ /* no need to continue if at least one preprocessor doesn't match */
+ idx_preproc < (size_t)in->num_preprocessors && match_cnt == idx_preproc;
+ idx_preproc++) {
+ struct effect_info_s *effect_info = &in->preprocessors[idx_preproc];
+ size_t idx_chcfg;
+
+ for (idx_chcfg = 0; idx_chcfg < effect_info->num_channel_configs; idx_chcfg++) {
+ if (memcmp(effect_info->channel_configs + idx_chcfg,
+ cur_chcfg,
+ sizeof(channel_config_t)) == 0) {
+ match_cnt++;
+ break;
+ }
+ }
+ }
+ /* if all preprocessors match, we have a candidate */
+ if (match_cnt == (size_t)in->num_preprocessors) {
+ /* retain most complex aux channels configuration */
+ if (popcount(cur_chcfg->aux_channels) > popcount(new_chcfg.aux_channels)) {
+ new_chcfg = *cur_chcfg;
+ }
+ }
+ }
+ }
+
+ ALOGV("in_get_aux_channels(): return %04x", new_chcfg.aux_channels);
+
+ return new_chcfg.aux_channels;
+}
+
+static int in_configure_effect_channels(effect_handle_t effect,
+ channel_config_t *channel_config)
+{
+ int status = 0;
+ int fct_status;
+ int32_t cmd_status;
+ uint32_t reply_size;
+ effect_config_t config;
+ uint32_t cmd[(sizeof(uint32_t) + sizeof(channel_config_t) - 1) / sizeof(uint32_t) + 1];
+
+ ALOGV("in_configure_effect_channels(): configure effect with channels: [%04x][%04x]",
+ channel_config->main_channels,
+ channel_config->aux_channels);
+
+ config.inputCfg.mask = EFFECT_CONFIG_CHANNELS;
+ config.outputCfg.mask = EFFECT_CONFIG_CHANNELS;
+ reply_size = sizeof(effect_config_t);
+ fct_status = (*effect)->command(effect,
+ EFFECT_CMD_GET_CONFIG,
+ 0,
+ NULL,
+ &reply_size,
+ &config);
+ if (fct_status != 0) {
+ ALOGE("in_configure_effect_channels(): EFFECT_CMD_GET_CONFIG failed");
+ return fct_status;
+ }
+
+ config.inputCfg.channels = channel_config->main_channels | channel_config->aux_channels;
+ config.outputCfg.channels = config.inputCfg.channels;
+ reply_size = sizeof(uint32_t);
+ fct_status = (*effect)->command(effect,
+ EFFECT_CMD_SET_CONFIG,
+ sizeof(effect_config_t),
+ &config,
+ &reply_size,
+ &cmd_status);
+ GET_COMMAND_STATUS(status, fct_status, cmd_status);
+
+ cmd[0] = EFFECT_FEATURE_AUX_CHANNELS;
+ memcpy(cmd + 1, channel_config, sizeof(channel_config_t));
+ reply_size = sizeof(uint32_t);
+ fct_status = (*effect)->command(effect,
+ EFFECT_CMD_SET_FEATURE_CONFIG,
+ sizeof(cmd), //sizeof(uint32_t) + sizeof(channel_config_t),
+ cmd,
+ &reply_size,
+ &cmd_status);
+ GET_COMMAND_STATUS(status, fct_status, cmd_status);
+
+ /* some implementations need to be re-enabled after a config change */
+ reply_size = sizeof(uint32_t);
+ fct_status = (*effect)->command(effect,
+ EFFECT_CMD_ENABLE,
+ 0,
+ NULL,
+ &reply_size,
+ &cmd_status);
+ GET_COMMAND_STATUS(status, fct_status, cmd_status);
+
+ return status;
+}
+
+static int in_reconfigure_channels(struct tuna_stream_in *in,
+ effect_handle_t effect,
+ channel_config_t *channel_config,
+ bool config_changed) {
+
+ int status = 0;
+
+ ALOGV("in_reconfigure_channels(): config_changed %d effect %p",
+ config_changed, effect);
+
+ /* if config changed, reconfigure all previously added effects */
+ if (config_changed) {
+ int i;
+ for (i = 0; i < in->num_preprocessors; i++)
+ {
+ int cur_status = in_configure_effect_channels(in->preprocessors[i].effect_itfe,
+ channel_config);
+ if (cur_status != 0) {
+ ALOGV("in_reconfigure_channels(): error %d configuring effect "
+ "%d with channels: [%04x][%04x]",
+ cur_status,
+ i,
+ channel_config->main_channels,
+ channel_config->aux_channels);
+ status = cur_status;
+ }
+ }
+ } else if (effect != NULL && channel_config->aux_channels) {
+ /* if aux channels config did not change but aux channels are present,
+ * we still need to configure the effect being added */
+ status = in_configure_effect_channels(effect, channel_config);
+ }
+ return status;
+}
+
+static void in_update_aux_channels(struct tuna_stream_in *in,
+ effect_handle_t effect)
+{
+ uint32_t aux_channels;
+ channel_config_t channel_config;
+ int status;
+
+ aux_channels = in_get_aux_channels(in);
+
+ channel_config.main_channels = in->main_channels;
+ channel_config.aux_channels = aux_channels;
+ status = in_reconfigure_channels(in,
+ effect,
+ &channel_config,
+ (aux_channels != in->aux_channels));
+
+ if (status != 0) {
+ ALOGV("in_update_aux_channels(): in_reconfigure_channels error %d", status);
+ /* resetting aux channels configuration */
+ aux_channels = 0;
+ channel_config.aux_channels = 0;
+ in_reconfigure_channels(in, effect, &channel_config, true);
+ }
+ if (in->aux_channels != aux_channels) {
+ in->aux_channels_changed = true;
+ in->aux_channels = aux_channels;
+ do_input_standby(in);
+ }
+}
+
static int in_add_audio_effect(const struct audio_stream *stream,
effect_handle_t effect)
{
@@ -2184,15 +2637,26 @@ static int in_add_audio_effect(const struct audio_stream *stream,
if (status != 0)
goto exit;
- in->preprocessors[in->num_preprocessors++] = effect;
+ in->preprocessors[in->num_preprocessors].effect_itfe = effect;
+ /* add the supported channel of the effect in the channel_configs */
+ in_read_audio_effect_channel_configs(in, &in->preprocessors[in->num_preprocessors]);
+
+ in->num_preprocessors++;
+
+ /* check compatibility between main channel supported and possible auxiliary channels */
+ in_update_aux_channels(in, effect);
+
+ ALOGV("in_add_audio_effect(), effect type: %08x", desc.type.timeLow);
if (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0) {
in->need_echo_reference = true;
do_input_standby(in);
+ in_configure_reverse(in);
}
exit:
+ ALOGW_IF(status != 0, "in_add_audio_effect() error %d", status);
pthread_mutex_unlock(&in->lock);
pthread_mutex_unlock(&in->dev->lock);
return status;
@@ -2204,7 +2668,6 @@ static int in_remove_audio_effect(const struct audio_stream *stream,
struct tuna_stream_in *in = (struct tuna_stream_in *)stream;
int i;
int status = -EINVAL;
- bool found = false;
effect_descriptor_t desc;
pthread_mutex_lock(&in->dev->lock);
@@ -2215,14 +2678,17 @@ static int in_remove_audio_effect(const struct audio_stream *stream,
}
for (i = 0; i < in->num_preprocessors; i++) {
- if (found) {
- in->preprocessors[i - 1] = in->preprocessors[i];
+ if (status == 0) { /* status == 0 means an effect was removed from a previous slot */
+ in->preprocessors[i - 1].effect_itfe = in->preprocessors[i].effect_itfe;
+ in->preprocessors[i - 1].channel_configs = in->preprocessors[i].channel_configs;
+ in->preprocessors[i - 1].num_channel_configs = in->preprocessors[i].num_channel_configs;
+ ALOGV("in_remove_audio_effect moving fx from %d to %d", i, i - 1);
continue;
}
- if (in->preprocessors[i] == effect) {
- in->preprocessors[i] = NULL;
+ if (in->preprocessors[i].effect_itfe == effect) {
+ ALOGV("in_remove_audio_effect found fx at index %d", i);
+ free(in->preprocessors[i].channel_configs);
status = 0;
- found = true;
}
}
@@ -2230,10 +2696,21 @@ static int in_remove_audio_effect(const struct audio_stream *stream,
goto exit;
in->num_preprocessors--;
+ /* if we remove one effect, at least the last preproc should be reset */
+ in->preprocessors[in->num_preprocessors].num_channel_configs = 0;
+ in->preprocessors[in->num_preprocessors].effect_itfe = NULL;
+ in->preprocessors[in->num_preprocessors].channel_configs = NULL;
+
+
+ /* check compatibility between main channel supported and possible auxiliary channels */
+ in_update_aux_channels(in, NULL);
status = (*effect)->get_descriptor(effect, &desc);
if (status != 0)
goto exit;
+
+ ALOGV("in_remove_audio_effect(), effect type: %08x", desc.type.timeLow);
+
if (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0) {
in->need_echo_reference = false;
do_input_standby(in);
@@ -2241,6 +2718,7 @@ static int in_remove_audio_effect(const struct audio_stream *stream,
exit:
+ ALOGW_IF(status != 0, "in_remove_audio_effect() error %d", status);
pthread_mutex_unlock(&in->lock);
pthread_mutex_unlock(&in->dev->lock);
return status;
@@ -2248,14 +2726,18 @@ exit:
static int adev_open_output_stream(struct audio_hw_device *dev,
- uint32_t devices, int *format,
- uint32_t *channels, uint32_t *sample_rate,
+ audio_io_handle_t handle,
+ audio_devices_t devices,
+ audio_output_flags_t flags,
+ struct audio_config *config,
struct audio_stream_out **stream_out)
{
struct tuna_audio_device *ladev = (struct tuna_audio_device *)dev;
struct tuna_stream_out *out;
int ret;
+ *stream_out = NULL;
+
out = (struct tuna_stream_out *)calloc(1, sizeof(struct tuna_stream_out));
if (!out)
return -ENOMEM;
@@ -2298,16 +2780,15 @@ static int adev_open_output_stream(struct audio_hw_device *dev,
* This is because out_set_parameters() with a route is not
* guaranteed to be called after an output stream is opened. */
- *format = out_get_format(&out->stream.common);
- *channels = out_get_channels(&out->stream.common);
- *sample_rate = out_get_sample_rate(&out->stream.common);
+ config->format = out_get_format(&out->stream.common);
+ config->channel_mask = out_get_channels(&out->stream.common);
+ config->sample_rate = out_get_sample_rate(&out->stream.common);
*stream_out = &out->stream;
return 0;
err_open:
free(out);
- *stream_out = NULL;
return ret;
}
@@ -2405,7 +2886,7 @@ static int adev_set_master_volume(struct audio_hw_device *dev, float volume)
return -ENOSYS;
}
-static int adev_set_mode(struct audio_hw_device *dev, int mode)
+static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
{
struct tuna_audio_device *adev = (struct tuna_audio_device *)dev;
@@ -2438,29 +2919,30 @@ static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
}
static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev,
- uint32_t sample_rate, int format,
- int channel_count)
+ const struct audio_config *config)
{
size_t size;
-
- if (check_input_parameters(sample_rate, format, channel_count) != 0)
+ int channel_count = popcount(config->channel_mask);
+ if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
return 0;
- return get_input_buffer_size(sample_rate, format, channel_count);
+ return get_input_buffer_size(config->sample_rate, config->format, channel_count);
}
-static int adev_open_input_stream(struct audio_hw_device *dev, uint32_t devices,
- int *format, uint32_t *channel_mask,
- uint32_t *sample_rate,
- audio_in_acoustics_t acoustics,
+static int adev_open_input_stream(struct audio_hw_device *dev,
+ audio_io_handle_t handle,
+ audio_devices_t devices,
+ struct audio_config *config,
struct audio_stream_in **stream_in)
{
struct tuna_audio_device *ladev = (struct tuna_audio_device *)dev;
struct tuna_stream_in *in;
int ret;
- int channel_count = popcount(*channel_mask);
+ int channel_count = popcount(config->channel_mask);
+
+ *stream_in = NULL;
- if (check_input_parameters(*sample_rate, *format, channel_count) != 0)
+ if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
return -EINVAL;
in = (struct tuna_stream_in *)calloc(1, sizeof(struct tuna_stream_in));
@@ -2483,17 +2965,15 @@ static int adev_open_input_stream(struct audio_hw_device *dev, uint32_t devices,
in->stream.read = in_read;
in->stream.get_input_frames_lost = in_get_input_frames_lost;
- in->requested_rate = *sample_rate;
+ in->requested_rate = config->sample_rate;
memcpy(&in->config, &pcm_config_mm_ul, sizeof(pcm_config_mm_ul));
in->config.channels = channel_count;
- in->buffer = malloc(in->config.period_size *
- audio_stream_frame_size(&in->stream.common));
- if (!in->buffer) {
- ret = -ENOMEM;
- goto err;
- }
+ in->main_channels = config->channel_mask;
+
+ /* initialisation of preprocessor structure array is implicit with the calloc.
+ * same for in->aux_channels and in->aux_channels_changed */
if (in->requested_rate != in->config.rate) {
in->buf_provider.get_next_buffer = get_next_buffer;
@@ -2523,7 +3003,6 @@ err:
release_resampler(in->resampler);
free(in);
- *stream_in = NULL;
return ret;
}
@@ -2531,15 +3010,22 @@ static void adev_close_input_stream(struct audio_hw_device *dev,
struct audio_stream_in *stream)
{
struct tuna_stream_in *in = (struct tuna_stream_in *)stream;
+ int i;
in_standby(&stream->common);
+ for (i = 0; i < in->num_preprocessors; i++) {
+ free(in->preprocessors[i].channel_configs);
+ }
+
+ free(in->read_buf);
if (in->resampler) {
- free(in->buffer);
release_resampler(in->resampler);
}
- if (in->proc_buf)
- free(in->proc_buf);
+ if (in->proc_buf_in)
+ free(in->proc_buf_in);
+ if (in->proc_buf_out)
+ free(in->proc_buf_out);
if (in->ref_buf)
free(in->ref_buf);
@@ -2601,7 +3087,7 @@ static int adev_open(const hw_module_t* module, const char* name,
return -ENOMEM;
adev->hw_device.common.tag = HARDWARE_DEVICE_TAG;
- adev->hw_device.common.version = 0;
+ adev->hw_device.common.version = AUDIO_DEVICE_API_VERSION_1_0;
adev->hw_device.common.module = (struct hw_module_t *) module;
adev->hw_device.common.close = adev_close;
@@ -2624,7 +3110,7 @@ static int adev_open(const hw_module_t* module, const char* name,
adev->mixer = mixer_open(0);
if (!adev->mixer) {
free(adev);
- LOGE("Unable to open the mixer, aborting.");
+ ALOGE("Unable to open the mixer, aborting.");
return -EINVAL;
}
@@ -2679,7 +3165,7 @@ static int adev_open(const hw_module_t* module, const char* name,
!adev->mixer_ctls.earpiece_volume) {
mixer_close(adev->mixer);
free(adev);
- LOGE("Unable to locate all mixer controls, aborting.");
+ ALOGE("Unable to locate all mixer controls, aborting.");
return -EINVAL;
}
@@ -2716,8 +3202,8 @@ static struct hw_module_methods_t hal_module_methods = {
struct audio_module HAL_MODULE_INFO_SYM = {
.common = {
.tag = HARDWARE_MODULE_TAG,
- .version_major = 1,
- .version_minor = 0,
+ .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
+ .hal_api_version = HARDWARE_HAL_API_VERSION,
.id = AUDIO_HARDWARE_MODULE_ID,
.name = "Tuna audio HW HAL",
.author = "The Android Open Source Project",
diff --git a/audio/audio_policy.conf b/audio/audio_policy.conf
new file mode 100644
index 0000000..ca95b0b
--- /dev/null
+++ b/audio/audio_policy.conf
@@ -0,0 +1,52 @@
+# Global configuration section: lists input and output devices always present on the device
+# as well as the output device selected by default.
+# Devices are designated by a string that corresponds to the enum in audio.h
+
+global_configuration {
+ attached_output_devices AUDIO_DEVICE_OUT_EARPIECE|AUDIO_DEVICE_OUT_SPEAKER
+ default_output_device AUDIO_DEVICE_OUT_SPEAKER
+ attached_input_devices AUDIO_DEVICE_IN_BUILTIN_MIC|AUDIO_DEVICE_IN_BACK_MIC
+}
+
+# audio hardware module section: contains descriptors for all audio hw modules present on the
+# device. Each hw module node is named after the corresponding hw module library base name.
+# For instance, "primary" corresponds to audio.primary.<device>.so.
+# The "primary" module is mandatory and must include at least one output with
+# AUDIO_OUTPUT_FLAG_PRIMARY flag.
+# Each module descriptor contains one or more output profile descriptors and zero or more
+# input profile descriptors. Each profile lists all the parameters supported by a given output
+# or input stream category.
+# The "channel_masks", "formats", "devices" and "flags" are specified using strings corresponding
+# to enums in audio.h and audio_policy.h. They are concatenated by use of "|" without space or "\n".
+
+audio_hw_modules {
+ primary {
+ outputs {
+ primary {
+ sampling_rates 44100
+ channel_masks AUDIO_CHANNEL_OUT_STEREO
+ formats AUDIO_FORMAT_PCM_16_BIT
+ devices AUDIO_DEVICE_OUT_EARPIECE|AUDIO_DEVICE_OUT_SPEAKER|AUDIO_DEVICE_OUT_WIRED_HEADSET|AUDIO_DEVICE_OUT_WIRED_HEADPHONE|AUDIO_DEVICE_OUT_ALL_SCO|AUDIO_DEVICE_OUT_AUX_DIGITAL|AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET
+ flags AUDIO_OUTPUT_FLAG_PRIMARY
+ }
+ }
+ inputs {
+ primary {
+ sampling_rates 8000|11025|16000|22050|32000|44100|48000
+ channel_masks AUDIO_CHANNEL_IN_MONO|AUDIO_CHANNEL_IN_STEREO
+ formats AUDIO_FORMAT_PCM_16_BIT
+ devices AUDIO_DEVICE_IN_BUILTIN_MIC|AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET|AUDIO_DEVICE_IN_WIRED_HEADSET|AUDIO_DEVICE_IN_BACK_MIC
+ }
+ }
+ }
+ a2dp {
+ outputs {
+ a2dp {
+ sampling_rates 44100
+ channel_masks AUDIO_CHANNEL_OUT_STEREO
+ formats AUDIO_FORMAT_PCM_16_BIT
+ devices AUDIO_DEVICE_OUT_ALL_A2DP
+ }
+ }
+ }
+}
diff --git a/audio/ril_interface.c b/audio/ril_interface.c
index 4e1e2a1..3d7ce06 100755..100644
--- a/audio/ril_interface.c
+++ b/audio/ril_interface.c
@@ -36,7 +36,6 @@ int (*_ril_is_connected)(void *);
int (*_ril_disconnect)(void *);
int (*_ril_set_call_volume)(void *, enum ril_sound_type, int);
int (*_ril_set_call_audio_path)(void *, enum ril_audio_path);
-int (*_ril_set_call_clock_sync)(void *, enum ril_clock_state);
int (*_ril_register_unsolicited_handler)(void *, int, void *);
int (*_ril_get_wb_amr)(void *, void *);
@@ -72,7 +71,7 @@ static int ril_connect_if_required(struct ril_handle *ril)
return 0;
if (_ril_connect(ril->client) != RIL_CLIENT_ERR_SUCCESS) {
- LOGE("ril_connect() failed");
+ ALOGE("ril_connect() failed");
return -1;
}
@@ -94,7 +93,7 @@ int ril_open(struct ril_handle *ril)
ril->handle = dlopen(RIL_CLIENT_LIBPATH, RTLD_NOW);
if (!ril->handle) {
- LOGE("Cannot open '%s'", RIL_CLIENT_LIBPATH);
+ ALOGE("Cannot open '%s'", RIL_CLIENT_LIBPATH);
return -1;
}
@@ -105,7 +104,6 @@ int ril_open(struct ril_handle *ril)
_ril_disconnect = dlsym(ril->handle, "Disconnect_RILD");
_ril_set_call_volume = dlsym(ril->handle, "SetCallVolume");
_ril_set_call_audio_path = dlsym(ril->handle, "SetCallAudioPath");
- _ril_set_call_clock_sync = dlsym(ril->handle, "SetCallClockSync");
_ril_register_unsolicited_handler = dlsym(ril->handle,
"RegisterUnsolicitedHandler");
/* since this function is not supported in all RILs, don't require it */
@@ -113,16 +111,15 @@ int ril_open(struct ril_handle *ril)
if (!_ril_open_client || !_ril_close_client || !_ril_connect ||
!_ril_is_connected || !_ril_disconnect || !_ril_set_call_volume ||
- !_ril_set_call_audio_path || !_ril_set_call_clock_sync ||
- !_ril_register_unsolicited_handler) {
- LOGE("Cannot get symbols from '%s'", RIL_CLIENT_LIBPATH);
+ !_ril_set_call_audio_path || !_ril_register_unsolicited_handler) {
+ ALOGE("Cannot get symbols from '%s'", RIL_CLIENT_LIBPATH);
dlclose(ril->handle);
return -1;
}
ril->client = _ril_open_client();
if (!ril->client) {
- LOGE("ril_open_client() failed");
+ ALOGE("ril_open_client() failed");
dlclose(ril->handle);
return -1;
}
@@ -148,7 +145,7 @@ int ril_close(struct ril_handle *ril)
if ((_ril_disconnect(ril->client) != RIL_CLIENT_ERR_SUCCESS) ||
(_ril_close_client(ril->client) != RIL_CLIENT_ERR_SUCCESS)) {
- LOGE("ril_disconnect() or ril_close_client() failed");
+ ALOGE("ril_disconnect() or ril_close_client() failed");
return -1;
}
@@ -173,11 +170,3 @@ int ril_set_call_audio_path(struct ril_handle *ril, enum ril_audio_path path)
return _ril_set_call_audio_path(ril->client, path);
}
-
-int ril_set_call_clock_sync(struct ril_handle *ril, enum ril_clock_state state)
-{
- if (ril_connect_if_required(ril))
- return 0;
-
- return _ril_set_call_clock_sync(ril->client, state);
-}
diff --git a/audio/ril_interface.h b/audio/ril_interface.h
index 676772c..2ea83f8 100755..100644
--- a/audio/ril_interface.h
+++ b/audio/ril_interface.h
@@ -66,7 +66,6 @@ int ril_close(struct ril_handle *ril);
int ril_set_call_volume(struct ril_handle *ril, enum ril_sound_type sound_type,
float volume);
int ril_set_call_audio_path(struct ril_handle *ril, enum ril_audio_path path);
-int ril_set_call_clock_sync(struct ril_handle *ril, enum ril_clock_state state);
void ril_register_set_wb_amr_callback(void *function, void *data);
#endif
diff --git a/board-info.txt b/board-info.txt
index e906c5e..9d45087 100644
--- a/board-info.txt
+++ b/board-info.txt
@@ -1,3 +1,3 @@
require board=tuna
-require version-bootloader=PRIMELA03
+require version-bootloader=PRIMELC03
diff --git a/device.mk b/device.mk
index 962d7b5..6bfd46e 100644
--- a/device.mk
+++ b/device.mk
@@ -47,19 +47,30 @@ PRODUCT_PACKAGES += \
nfc.tuna
PRODUCT_PACKAGES += \
+ power.tuna
+
+# Audio
+PRODUCT_PACKAGES += \
audio.primary.tuna \
- audio.a2dp.default \
- libaudioutils
+ audio.a2dp.default
+
+PRODUCT_COPY_FILES += \
+ device/samsung/tuna/audio/audio_policy.conf:system/etc/audio_policy.conf
+
PRODUCT_PACKAGES += \
tuna_hdcp_keys
-PRODUCT_COPY_FILES := \
+#PRODUCT_PACKAGES += \
+# keystore.tuna
+
+PRODUCT_COPY_FILES += \
$(LOCAL_KERNEL):kernel \
device/samsung/tuna/init.tuna.rc:root/init.tuna.rc \
device/samsung/tuna/init.tuna.usb.rc:root/init.tuna.usb.rc \
device/samsung/tuna/ueventd.tuna.rc:root/ueventd.tuna.rc \
device/samsung/tuna/media_profiles.xml:system/etc/media_profiles.xml \
+ device/samsung/tuna/media_codecs.xml:system/etc/media_codecs.xml \
device/samsung/tuna/gps.conf:system/etc/gps.conf
# Bluetooth configuration files
@@ -75,8 +86,7 @@ PRODUCT_COPY_FILES += \
device/samsung/tuna/bcmdhd.cal:system/etc/wifi/bcmdhd.cal
PRODUCT_PROPERTY_OVERRIDES := \
- wifi.interface=wlan0 \
- wifi.supplicant_scan_interval=15
+ wifi.interface=wlan0
# Set default USB interface
PRODUCT_DEFAULT_PROPERTY_OVERRIDES += \
@@ -101,7 +111,9 @@ PRODUCT_COPY_FILES += \
device/samsung/tuna/tuna-gpio-keypad.kl:system/usr/keylayout/tuna-gpio-keypad.kl \
device/samsung/tuna/tuna-gpio-keypad.kcm:system/usr/keychars/tuna-gpio-keypad.kcm \
device/samsung/tuna/sec_jack.kl:system/usr/keylayout/sec_jack.kl \
- device/samsung/tuna/sec_jack.kcm:system/usr/keychars/sec_jack.kcm
+ device/samsung/tuna/sec_jack.kcm:system/usr/keychars/sec_jack.kcm \
+ device/samsung/tuna/sii9234_rcp.kl:system/usr/keylayout/sii9234_rcp.kl \
+ device/samsung/tuna/sii9234_rcp.kcm:system/usr/keychars/sii9234_rcp.kcm
# Input device calibration files
PRODUCT_COPY_FILES += \
@@ -109,21 +121,21 @@ PRODUCT_COPY_FILES += \
# These are the hardware-specific features
PRODUCT_COPY_FILES += \
- frameworks/base/data/etc/handheld_core_hardware.xml:system/etc/permissions/handheld_core_hardware.xml \
- frameworks/base/data/etc/android.hardware.camera.flash-autofocus.xml:system/etc/permissions/android.hardware.camera.flash-autofocus.xml \
- frameworks/base/data/etc/android.hardware.camera.front.xml:system/etc/permissions/android.hardware.camera.front.xml \
- frameworks/base/data/etc/android.hardware.location.gps.xml:system/etc/permissions/android.hardware.location.gps.xml \
- frameworks/base/data/etc/android.hardware.wifi.xml:system/etc/permissions/android.hardware.wifi.xml \
- frameworks/base/data/etc/android.hardware.wifi.direct.xml:system/etc/permissions/android.hardware.wifi.direct.xml \
- frameworks/base/data/etc/android.hardware.sensor.proximity.xml:system/etc/permissions/android.hardware.sensor.proximity.xml \
- frameworks/base/data/etc/android.hardware.sensor.light.xml:system/etc/permissions/android.hardware.sensor.light.xml \
- frameworks/base/data/etc/android.hardware.sensor.gyroscope.xml:system/etc/permissions/android.hardware.sensor.gyroscope.xml \
- frameworks/base/data/etc/android.hardware.sensor.barometer.xml:system/etc/permissions/android.hardware.sensor.barometer.xml \
- frameworks/base/data/etc/android.hardware.touchscreen.multitouch.jazzhand.xml:system/etc/permissions/android.hardware.touchscreen.multitouch.jazzhand.xml \
- frameworks/base/data/etc/android.hardware.nfc.xml:system/etc/permissions/android.hardware.nfc.xml \
- frameworks/base/data/etc/android.software.sip.voip.xml:system/etc/permissions/android.software.sip.voip.xml \
- frameworks/base/data/etc/android.hardware.usb.accessory.xml:system/etc/permissions/android.hardware.usb.accessory.xml \
- frameworks/base/data/etc/android.hardware.usb.host.xml:system/etc/permissions/android.hardware.usb.host.xml \
+ frameworks/native/data/etc/handheld_core_hardware.xml:system/etc/permissions/handheld_core_hardware.xml \
+ frameworks/native/data/etc/android.hardware.camera.flash-autofocus.xml:system/etc/permissions/android.hardware.camera.flash-autofocus.xml \
+ frameworks/native/data/etc/android.hardware.camera.front.xml:system/etc/permissions/android.hardware.camera.front.xml \
+ frameworks/native/data/etc/android.hardware.location.gps.xml:system/etc/permissions/android.hardware.location.gps.xml \
+ frameworks/native/data/etc/android.hardware.wifi.xml:system/etc/permissions/android.hardware.wifi.xml \
+ frameworks/native/data/etc/android.hardware.wifi.direct.xml:system/etc/permissions/android.hardware.wifi.direct.xml \
+ frameworks/native/data/etc/android.hardware.sensor.proximity.xml:system/etc/permissions/android.hardware.sensor.proximity.xml \
+ frameworks/native/data/etc/android.hardware.sensor.light.xml:system/etc/permissions/android.hardware.sensor.light.xml \
+ frameworks/native/data/etc/android.hardware.sensor.gyroscope.xml:system/etc/permissions/android.hardware.sensor.gyroscope.xml \
+ frameworks/native/data/etc/android.hardware.sensor.barometer.xml:system/etc/permissions/android.hardware.sensor.barometer.xml \
+ frameworks/native/data/etc/android.hardware.touchscreen.multitouch.jazzhand.xml:system/etc/permissions/android.hardware.touchscreen.multitouch.jazzhand.xml \
+ frameworks/native/data/etc/android.hardware.nfc.xml:system/etc/permissions/android.hardware.nfc.xml \
+ frameworks/native/data/etc/android.software.sip.voip.xml:system/etc/permissions/android.software.sip.voip.xml \
+ frameworks/native/data/etc/android.hardware.usb.accessory.xml:system/etc/permissions/android.hardware.usb.accessory.xml \
+ frameworks/native/data/etc/android.hardware.usb.host.xml:system/etc/permissions/android.hardware.usb.host.xml \
packages/wallpapers/LivePicker/android.software.live_wallpaper.xml:system/etc/permissions/android.software.live_wallpaper.xml
# HACK: copy panda init for now to boot on both boards
@@ -145,13 +157,13 @@ PRODUCT_COPY_FILES += \
# file that declares the MIFARE NFC constant
PRODUCT_COPY_FILES += \
- device/sample/nxp/com.nxp.mifare.xml:system/etc/permissions/com.nxp.mifare.xml
+ frameworks/native/data/etc/com.nxp.mifare.xml:system/etc/permissions/com.nxp.mifare.xml
# NFC EXTRAS add-on API
PRODUCT_PACKAGES += \
com.android.nfc_extras
PRODUCT_COPY_FILES += \
- frameworks/base/nfc-extras/com.android.nfc_extras.xml:system/etc/permissions/com.android.nfc_extras.xml
+ frameworks/native/data/etc/com.android.nfc_extras.xml:system/etc/permissions/com.android.nfc_extras.xml
# NFCEE access control
ifeq ($(TARGET_BUILD_VARIANT),user)
@@ -187,7 +199,7 @@ PRODUCT_COPY_FILES += \
system/extras/bugmailer/bugmailer.sh:system/bin/bugmailer.sh \
system/extras/bugmailer/send_bug:system/bin/send_bug
-$(call inherit-product, frameworks/base/build/phone-xhdpi-1024-dalvik-heap.mk)
+$(call inherit-product, frameworks/native/build/phone-xhdpi-1024-dalvik-heap.mk)
$(call inherit-product-if-exists, vendor/nxp/pn544/nxp-pn544-fw-vendor.mk)
$(call inherit-product, hardware/ti/omap4xxx/omap4.mk)
diff --git a/dumpstate/Android.mk b/dumpstate/Android.mk
index e4168db..ce5195b 100644
--- a/dumpstate/Android.mk
+++ b/dumpstate/Android.mk
@@ -15,7 +15,7 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
-LOCAL_C_INCLUDES := frameworks/base/cmds/dumpstate
+LOCAL_C_INCLUDES := frameworks/native/cmds/dumpstate
LOCAL_SRC_FILES := dumpstate.c
diff --git a/egl.cfg b/egl.cfg
index a6f606e..edf6a25 100644
--- a/egl.cfg
+++ b/egl.cfg
@@ -1,3 +1 @@
-0 0 android
-0 1 POWERVR_SGX540_120
-
+0 0 POWERVR_SGX540_120
diff --git a/full_tuna.mk b/full_tuna.mk
index f2d8d61..0e4aa5b 100644
--- a/full_tuna.mk
+++ b/full_tuna.mk
@@ -21,10 +21,6 @@
# lines, full and toro, hence its name.
#
-# Camera
-PRODUCT_PACKAGES := \
- Camera
-
# Inherit from those products. Most specific first.
$(call inherit-product, $(SRC_TARGET_DIR)/product/full_base.mk)
# This is where we'd set a backup provider if we had one
diff --git a/gps.conf b/gps.conf
index bd431a6..e3fb1df 100644
--- a/gps.conf
+++ b/gps.conf
@@ -1,4 +1,3 @@
-NTP_SERVER=north-america.pool.ntp.org
XTRA_SERVER_1=http://xtra1.gpsonextra.net/xtra.bin
XTRA_SERVER_2=http://xtra2.gpsonextra.net/xtra.bin
XTRA_SERVER_3=http://xtra3.gpsonextra.net/xtra.bin
diff --git a/init.tuna.rc b/init.tuna.rc
index 70f1cbe..36d6bb9 100755
--- a/init.tuna.rc
+++ b/init.tuna.rc
@@ -1,14 +1,16 @@
import init.tuna.usb.rc
on early-init
- export EXTERNAL_STORAGE /mnt/sdcard
- mkdir /mnt/sdcard 0000 system system
+ export EXTERNAL_STORAGE /storage/sdcard0
+ mkdir /storage 0050 system sdcard_r
+ mkdir /storage/sdcard0 0000 system system
# for backwards compatibility
- symlink /mnt/sdcard /sdcard
+ symlink /storage/sdcard0 /sdcard
+ symlink /storage/sdcard0 /mnt/sdcard
on post-fs-data
- # we will remap this as /mnt/sdcard with the sdcard fuse tool
- mkdir /data/media 0775 media_rw media_rw
+ # we will remap this as /storage/sdcard0 with the sdcard fuse tool
+ mkdir /data/media 0770 media_rw media_rw
chown media_rw media_rw /data/media
mkdir /data/misc/wifi 0770 wifi wifi
mkdir /data/misc/wifi/sockets 0770 wifi wifi
@@ -23,6 +25,9 @@ on post-fs-data
mkdir /data/misc/camera 0770 media media
mkdir /data/misc/camera/R5_MVEN003_LD2_ND0_IR0_SH0_FL1_SVEN003_DCCID1044 0770 media media
+ mkdir /data/radio 0775 radio radio
+ mkdir /data/radio/log 0775 radio radio
+
setprop vold.post_fs_data_done 1
# LTE
@@ -38,14 +43,6 @@ on boot
chmod 0666 /dev/pvrsrvkm
setprop ro.crypto.keyfile.userdata /dev/block/platform/omap/omap_hsmmc.0/by-name/metadata
-# Lower maximum frequency when screen is off
- write /sys/devices/system/cpu/cpu0/cpufreq/screen_off_max_freq 700000
-
-# cpufreq interactive governor: timer 20ms, min sample 20ms, hispeed 700MHz
- write /sys/devices/system/cpu/cpufreq/interactive/timer_rate 20000
- write /sys/devices/system/cpu/cpufreq/interactive/min_sample_time 20000
- write /sys/devices/system/cpu/cpufreq/interactive/hispeed_freq 700000
-
# autosuspend root hubs immediatly after attached devices
write /sys/bus/usb/devices/usb1/power/autosuspend_delay_ms 0
write /sys/bus/usb/devices/usb2/power/autosuspend_delay_ms 0
@@ -77,8 +74,6 @@ on fs
# We chown/chmod /factory because mount is run as root + defaults
chown radio radio /factory
chmod 0775 /factory
- mkdir /data/radio 0775 radio radio
- mkdir /data/radio/log 0775 radio radio
# add symlink for HDCP key
symlink /factory/hdcp.keys /system/vendor/firmware/hdcp.keys
@@ -116,10 +111,10 @@ on fs
chown radio radio /sys/bus/usb/devices/usb1/power/control
on property:persist.sys.tuna.off_mode=*
- write /d/pm_debug/enable_off_mode $persist.sys.tuna.off_mode
+ write /d/pm_debug/enable_off_mode ${persist.sys.tuna.off_mode}
on property:ril.modem.lte.powercontrol=*
- write /sys/bus/usb/devices/1-1/power/control $ril.modem.lte.powercontrol
+ write /sys/bus/usb/devices/1-1/power/control ${ril.modem.lte.powercontrol}
service fRom /system/bin/fRom \
-x /data/misc/camera/R5_MVEN003_LD2_ND0_IR0_SH0_FL1_SVEN003_DCCID1044 \
@@ -138,7 +133,7 @@ service hciattach /system/bin/brcm_patchram_plus --enable_hci --no2bytes --enabl
disabled
oneshot
-service pvrsrvinit /vendor/bin/pvrsrvinit
+service pvrsrvctl /vendor/bin/pvrsrvctl --start --no-module
class core
user root
group root
@@ -167,14 +162,26 @@ service smc_pa_wvdrm /system/bin/smc_pa_ctrl \
group drmrpc
oneshot
-# create virtual SD card at /mnt/sdcard, based on the /data/media directory
+# create virtual SD card at /storage/sdcard0, based on the /data/media directory
# daemon will drop to user/group system/media_rw after initializing
# underlying files in /data/media will be created with user and group media_rw (1023)
service sdcard /system/bin/sdcard /data/media 1023 1023
class late_start
+service p2p_supplicant /system/bin/wpa_supplicant \
+ -iwlan0 -Dnl80211 -c/data/misc/wifi/wpa_supplicant.conf -N \
+ -ip2p0 -Dnl80211 -c/data/misc/wifi/p2p_supplicant.conf -e/data/misc/wifi/entropy.bin -puse_p2p_group_interface=1
+ # we will start as root and wpa_supplicant will switch to user wifi
+ # after setting up the capabilities required for WEXT
+ # user wifi
+ # group wifi inet keystore
+ class main
+ socket wpa_wlan0 dgram 660 wifi wifi
+ disabled
+ oneshot
+
service wpa_supplicant /system/bin/wpa_supplicant \
- -Dnl80211 -iwlan0 -puse_p2p_group_interface=1 -e/data/misc/wifi/entropy.bin
+ -iwlan0 -Dnl80211 -c/data/misc/wifi/wpa_supplicant.conf -e/data/misc/wifi/entropy.bin
# we will start as root and wpa_supplicant will switch to user wifi
# after setting up the capabilities required for WEXT
# user wifi
@@ -184,7 +191,7 @@ service wpa_supplicant /system/bin/wpa_supplicant \
disabled
oneshot
-service dhcpcd_wlan0 /system/bin/dhcpcd -ABKL
+service dhcpcd_wlan0 /system/bin/dhcpcd -aABKL
class main
disabled
oneshot
diff --git a/init.tuna.usb.rc b/init.tuna.usb.rc
index 20bf090..e86a7bd 100755
--- a/init.tuna.usb.rc
+++ b/init.tuna.usb.rc
@@ -1,79 +1,79 @@
on init
- write /sys/class/android_usb/android0/iSerial $ro.serialno
+ write /sys/class/android_usb/android0/iSerial ${ro.serialno}
write /sys/class/android_usb/android0/f_rndis/manufacturer Samsung
write /sys/class/android_usb/android0/f_rndis/vendorID 04e8
write /sys/class/android_usb/android0/f_rndis/wceis 1
on boot
- write /sys/class/android_usb/android0/iManufacturer $ro.product.manufacturer
- write /sys/class/android_usb/android0/iProduct $ro.product.model
+ write /sys/class/android_usb/android0/iManufacturer ${ro.product.manufacturer}
+ write /sys/class/android_usb/android0/iProduct ${ro.product.model}
on property:sys.usb.config=mtp
write /sys/class/android_usb/android0/enable 0
write /sys/class/android_usb/android0/idVendor 04e8
write /sys/class/android_usb/android0/idProduct 685c
- write /sys/class/android_usb/android0/functions $sys.usb.config
+ write /sys/class/android_usb/android0/functions ${sys.usb.config}
write /sys/class/android_usb/android0/enable 1
- setprop sys.usb.state $sys.usb.config
+ setprop sys.usb.state ${sys.usb.config}
on property:sys.usb.config=mtp,adb
write /sys/class/android_usb/android0/enable 0
write /sys/class/android_usb/android0/idVendor 04e8
write /sys/class/android_usb/android0/idProduct 6860
- write /sys/class/android_usb/android0/functions $sys.usb.config
+ write /sys/class/android_usb/android0/functions ${sys.usb.config}
write /sys/class/android_usb/android0/enable 1
start adbd
- setprop sys.usb.state $sys.usb.config
+ setprop sys.usb.state ${sys.usb.config}
on property:sys.usb.config=rndis
write /sys/class/android_usb/android0/enable 0
write /sys/class/android_usb/android0/idVendor 04e8
write /sys/class/android_usb/android0/idProduct 6863
- write /sys/class/android_usb/android0/functions $sys.usb.config
+ write /sys/class/android_usb/android0/functions ${sys.usb.config}
write /sys/class/android_usb/android0/bDeviceClass 224
write /sys/class/android_usb/android0/enable 1
- setprop sys.usb.state $sys.usb.config
+ setprop sys.usb.state ${sys.usb.config}
on property:sys.usb.config=rndis,adb
write /sys/class/android_usb/android0/enable 0
write /sys/class/android_usb/android0/idVendor 04e8
write /sys/class/android_usb/android0/idProduct 6864
- write /sys/class/android_usb/android0/functions $sys.usb.config
+ write /sys/class/android_usb/android0/functions ${sys.usb.config}
write /sys/class/android_usb/android0/bDeviceClass 224
write /sys/class/android_usb/android0/enable 1
start adbd
- setprop sys.usb.state $sys.usb.config
+ setprop sys.usb.state ${sys.usb.config}
on property:sys.usb.config=ptp
write /sys/class/android_usb/android0/enable 0
write /sys/class/android_usb/android0/idVendor 04e8
write /sys/class/android_usb/android0/idProduct 6865
- write /sys/class/android_usb/android0/functions $sys.usb.config
+ write /sys/class/android_usb/android0/functions ${sys.usb.config}
write /sys/class/android_usb/android0/enable 1
- setprop sys.usb.state $sys.usb.config
+ setprop sys.usb.state ${sys.usb.config}
on property:sys.usb.config=ptp,adb
write /sys/class/android_usb/android0/enable 0
write /sys/class/android_usb/android0/idVendor 04e8
write /sys/class/android_usb/android0/idProduct 6866
- write /sys/class/android_usb/android0/functions $sys.usb.config
+ write /sys/class/android_usb/android0/functions ${sys.usb.config}
write /sys/class/android_usb/android0/enable 1
start adbd
- setprop sys.usb.state $sys.usb.config
+ setprop sys.usb.state ${sys.usb.config}
on property:sys.usb.config=rndis,dm
write /sys/class/android_usb/android0/enable 0
write /sys/class/android_usb/android0/idVendor 04e8
write /sys/class/android_usb/android0/idProduct 6864
- write /sys/class/android_usb/android0/functions $sys.usb.config
+ write /sys/class/android_usb/android0/functions ${sys.usb.config}
write /sys/class/android_usb/android0/enable 1
- setprop sys.usb.state $sys.usb.config
+ setprop sys.usb.state ${sys.usb.config}
on property:sys.usb.config=rndis,acm,dm
write /sys/class/android_usb/android0/enable 0
write /sys/class/android_usb/android0/idVendor 04e8
write /sys/class/android_usb/android0/idProduct 6864
- write /sys/class/android_usb/android0/functions $sys.usb.config
+ write /sys/class/android_usb/android0/functions ${sys.usb.config}
write /sys/class/android_usb/android0/f_acm/instances 1
write /sys/class/android_usb/android0/enable 1
- setprop sys.usb.state $sys.usb.config
+ setprop sys.usb.state ${sys.usb.config}
diff --git a/kernel b/kernel
index 9fc8646..3e975bb 100644
--- a/kernel
+++ b/kernel
Binary files differ
diff --git a/keymaster/Android.mk b/keymaster/Android.mk
new file mode 100644
index 0000000..885812f
--- /dev/null
+++ b/keymaster/Android.mk
@@ -0,0 +1,43 @@
+# Copyright (C) 2011 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.
+
+ifeq ($(TARGET_BOARD_PLATFORM),omap4)
+ifeq ($(BOARD_USES_SECURE_SERVICES),true)
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := keystore.tuna
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
+
+LOCAL_SRC_FILES := \
+ keymaster_tuna.cpp
+
+LOCAL_C_INCLUDES := \
+ libcore/include \
+ external/openssl/include \
+ hardware/ti/omap4xxx/security/tf_sdk/include
+
+LOCAL_CFLAGS := -fvisibility=hidden -Wall -Werror
+
+LOCAL_SHARED_LIBRARIES := libcutils liblog libcrypto libtf_crypto_sst
+
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_SHARED_LIBRARY)
+
+endif # ifeq ($(BOARD_USES_SECURE_SERVICES),true)
+endif # ifeq ($(TARGET_BOARD_PLATFORM),omap4)
diff --git a/keymaster/keymaster_tuna.cpp b/keymaster/keymaster_tuna.cpp
new file mode 100644
index 0000000..fbc654f
--- /dev/null
+++ b/keymaster/keymaster_tuna.cpp
@@ -0,0 +1,966 @@
+/*
+ * Copyright (C) 2011 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 <errno.h>
+#include <string.h>
+#include <stdint.h>
+
+// For debugging
+#define LOG_NDEBUG 0
+
+// TEE is the Trusted Execution Environment
+#define LOG_TAG "TEEKeyMaster"
+#include <cutils/log.h>
+
+#include <hardware/hardware.h>
+#include <hardware/keymaster.h>
+
+#include <openssl/bn.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/rand.h>
+#include <openssl/x509.h>
+
+#include <cryptoki.h>
+#include <pkcs11.h>
+
+#include <UniquePtr.h>
+
+
+/** The size of a key ID in bytes */
+#define ID_LENGTH 32
+
+/** The current stored key version. */
+const static uint32_t KEY_VERSION = 1;
+
+
+struct EVP_PKEY_Delete {
+ void operator()(EVP_PKEY* p) const {
+ EVP_PKEY_free(p);
+ }
+};
+typedef UniquePtr<EVP_PKEY, EVP_PKEY_Delete> Unique_EVP_PKEY;
+
+struct RSA_Delete {
+ void operator()(RSA* p) const {
+ RSA_free(p);
+ }
+};
+typedef UniquePtr<RSA, RSA_Delete> Unique_RSA;
+
+struct PKCS8_PRIV_KEY_INFO_Delete {
+ void operator()(PKCS8_PRIV_KEY_INFO* p) const {
+ PKCS8_PRIV_KEY_INFO_free(p);
+ }
+};
+typedef UniquePtr<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_Delete> Unique_PKCS8_PRIV_KEY_INFO;
+
+typedef UniquePtr<keymaster_device_t> Unique_keymaster_device_t;
+
+typedef UniquePtr<CK_BYTE[]> Unique_CK_BYTE;
+
+typedef UniquePtr<CK_ATTRIBUTE[]> Unique_CK_ATTRIBUTE;
+
+class ByteArray {
+public:
+ ByteArray(CK_BYTE* array, size_t len) :
+ mArray(array), mLength(len) {
+ }
+
+ ByteArray(size_t len) :
+ mLength(len) {
+ mArray = new CK_BYTE[len];
+ }
+
+ ~ByteArray() {
+ if (mArray != NULL) {
+ delete[] mArray;
+ }
+ }
+
+ CK_BYTE* get() const {
+ return mArray;
+ }
+
+ size_t length() const {
+ return mLength;
+ }
+
+ CK_BYTE* release() {
+ CK_BYTE* array = mArray;
+ mArray = NULL;
+ return array;
+ }
+
+private:
+ CK_BYTE* mArray;
+ size_t mLength;
+};
+typedef UniquePtr<ByteArray> Unique_ByteArray;
+
+class CryptoSession {
+public:
+ CryptoSession(CK_SESSION_HANDLE masterHandle) :
+ mHandle(masterHandle), mSubsession(CK_INVALID_HANDLE) {
+ CK_SESSION_HANDLE subsessionHandle = mHandle;
+ CK_RV openSessionRV = C_OpenSession(CKV_TOKEN_USER,
+ CKF_SERIAL_SESSION | CKF_RW_SESSION | CKVF_OPEN_SUB_SESSION,
+ NULL,
+ NULL,
+ &subsessionHandle);
+
+ if (openSessionRV != CKR_OK || subsessionHandle == CK_INVALID_HANDLE) {
+ (void) C_Finalize(NULL_PTR);
+ ALOGE("Error opening secondary session with TEE: 0x%x", openSessionRV);
+ } else {
+ ALOGV("Opening subsession 0x%x", subsessionHandle);
+ mSubsession = subsessionHandle;
+ }
+ }
+
+ ~CryptoSession() {
+ if (mSubsession != CK_INVALID_HANDLE) {
+ CK_RV rv = C_CloseSession(mSubsession);
+ ALOGV("Closing subsession 0x%x: 0x%x", mSubsession, rv);
+ mSubsession = CK_INVALID_HANDLE;
+ }
+ }
+
+ CK_SESSION_HANDLE get() const {
+ return mSubsession;
+ }
+
+ CK_SESSION_HANDLE getPrimary() const {
+ return mHandle;
+ }
+
+private:
+ CK_SESSION_HANDLE mHandle;
+ CK_SESSION_HANDLE mSubsession;
+};
+
+class ObjectHandle {
+public:
+ ObjectHandle(const CryptoSession* session, CK_OBJECT_HANDLE handle = CK_INVALID_HANDLE) :
+ mSession(session), mHandle(handle) {
+ }
+
+ ~ObjectHandle() {
+ if (mHandle != CK_INVALID_HANDLE) {
+ CK_RV rv = C_CloseObjectHandle(mSession->getPrimary(), mHandle);
+ if (rv != CKR_OK) {
+ ALOGW("Couldn't close object handle 0x%x: 0x%x", mHandle, rv);
+ } else {
+ ALOGV("Closing object handle 0x%x", mHandle);
+ mHandle = CK_INVALID_HANDLE;
+ }
+ }
+ }
+
+ CK_OBJECT_HANDLE get() const {
+ return mHandle;
+ }
+
+ void reset(CK_OBJECT_HANDLE handle) {
+ mHandle = handle;
+ }
+
+private:
+ const CryptoSession* mSession;
+ CK_OBJECT_HANDLE mHandle;
+};
+
+
+/**
+ * Many OpenSSL APIs take ownership of an argument on success but don't free the argument
+ * on failure. This means we need to tell our scoped pointers when we've transferred ownership,
+ * without triggering a warning by not using the result of release().
+ */
+#define OWNERSHIP_TRANSFERRED(obj) \
+ typeof (obj.release()) _dummy __attribute__((unused)) = obj.release()
+
+
+/*
+ * Checks this thread's OpenSSL error queue and logs if
+ * necessary.
+ */
+static void logOpenSSLError(const char* location) {
+ int error = ERR_get_error();
+
+ if (error != 0) {
+ char message[256];
+ ERR_error_string_n(error, message, sizeof(message));
+ ALOGE("OpenSSL error in %s %d: %s", location, error, message);
+ }
+
+ ERR_clear_error();
+ ERR_remove_state(0);
+}
+
+
+/**
+ * Convert from OpenSSL's BIGNUM format to TEE's Big Integer format.
+ */
+static ByteArray* bignum_to_array(const BIGNUM* bn) {
+ const int bignumSize = BN_num_bytes(bn);
+
+ Unique_CK_BYTE bytes(new CK_BYTE[bignumSize]);
+
+ unsigned char* tmp = reinterpret_cast<unsigned char*>(bytes.get());
+ if (BN_bn2bin(bn, tmp) != bignumSize) {
+ ALOGE("public exponent size wasn't what was expected");
+ return NULL;
+ }
+
+ return new ByteArray(bytes.release(), bignumSize);
+}
+
+static void set_attribute(CK_ATTRIBUTE* attrib, CK_ATTRIBUTE_TYPE type, void* pValue,
+ CK_ULONG ulValueLen) {
+ attrib->type = type;
+ attrib->pValue = pValue;
+ attrib->ulValueLen = ulValueLen;
+}
+
+static ByteArray* generate_random_id() {
+ Unique_ByteArray id(new ByteArray(ID_LENGTH));
+ if (RAND_pseudo_bytes(reinterpret_cast<unsigned char*>(id->get()), id->length()) < 0) {
+ return NULL;
+ }
+
+ return id.release();
+}
+
+static int keyblob_save(ByteArray* objId, uint8_t** key_blob, size_t* key_blob_length) {
+ Unique_ByteArray handleBlob(new ByteArray(sizeof(uint32_t) + objId->length()));
+ if (handleBlob.get() == NULL) {
+ ALOGE("Could not allocate key blob");
+ return -1;
+ }
+ uint8_t* tmp = handleBlob->get();
+ for (size_t i = 0; i < sizeof(uint32_t); i++) {
+ *tmp++ = KEY_VERSION >> ((sizeof(uint32_t) - i - 1) * 8);
+ }
+ memcpy(tmp, objId->get(), objId->length());
+
+ *key_blob_length = handleBlob->length();
+ *key_blob = handleBlob->get();
+ ByteArray* unused __attribute__((unused)) = handleBlob.release();
+
+ return 0;
+}
+
+static int find_single_object(const uint8_t* obj_id, const size_t obj_id_length,
+ CK_OBJECT_CLASS obj_class, const CryptoSession* session, ObjectHandle* object) {
+
+ // Note that the CKA_ID attribute is never written, so we can cast away const here.
+ void* obj_id_ptr = reinterpret_cast<void*>(const_cast<uint8_t*>(obj_id));
+ CK_ATTRIBUTE attributes[] = {
+ { CKA_ID, obj_id_ptr, obj_id_length },
+ { CKA_CLASS, &obj_class, sizeof(obj_class) },
+ };
+
+ CK_RV rv = C_FindObjectsInit(session->get(), attributes,
+ sizeof(attributes) / sizeof(CK_ATTRIBUTE));
+ if (rv != CKR_OK) {
+ ALOGE("Error in C_FindObjectsInit: 0x%x", rv);
+ return -1;
+ }
+
+ CK_OBJECT_HANDLE tmpHandle;
+ CK_ULONG tmpCount;
+
+ rv = C_FindObjects(session->get(), &tmpHandle, 1, &tmpCount);
+ ALOGV("Found %d object 0x%x : class 0x%x", tmpCount, tmpHandle, obj_class);
+ if (rv != CKR_OK || tmpCount != 1) {
+ C_FindObjectsFinal(session->get());
+ ALOGE("Couldn't find key!");
+ return -1;
+ }
+ C_FindObjectsFinal(session->get());
+
+ object->reset(tmpHandle);
+ return 0;
+}
+
+static int keyblob_restore(const CryptoSession* session, const uint8_t* keyBlob,
+ const size_t keyBlobLength, ObjectHandle* public_key, ObjectHandle* private_key) {
+ if (keyBlob == NULL) {
+ ALOGE("key blob was null");
+ return -1;
+ }
+
+ if (keyBlobLength < (sizeof(KEY_VERSION) + ID_LENGTH)) {
+ ALOGE("key blob is not correct size");
+ return -1;
+ }
+
+ uint32_t keyVersion = 0;
+
+ const uint8_t* p = keyBlob;
+ for (size_t i = 0; i < sizeof(keyVersion); i++) {
+ keyVersion = (keyVersion << 8) | *p++;
+ }
+
+ if (keyVersion != 1) {
+ ALOGE("Invalid key version %d", keyVersion);
+ return -1;
+ }
+
+ return find_single_object(p, ID_LENGTH, CKO_PUBLIC_KEY, session, public_key)
+ || find_single_object(p, ID_LENGTH, CKO_PRIVATE_KEY, session, private_key);
+}
+
+static int tee_generate_keypair(const keymaster_device_t* dev,
+ const keymaster_keypair_t type, const void* key_params,
+ uint8_t** key_blob, size_t* key_blob_length) {
+ CK_BBOOL bTRUE = CK_TRUE;
+
+ if (type != TYPE_RSA) {
+ ALOGW("Unknown key type %d", type);
+ return -1;
+ }
+
+ if (key_params == NULL) {
+ ALOGW("generate_keypair params were NULL");
+ return -1;
+ }
+
+ keymaster_rsa_keygen_params_t* rsa_params = (keymaster_rsa_keygen_params_t*) key_params;
+
+ CK_MECHANISM mechanism = {
+ CKM_RSA_PKCS_KEY_PAIR_GEN, NULL, 0,
+ };
+ CK_ULONG modulusBits = (CK_ULONG) rsa_params->modulus_size;
+
+ /**
+ * Convert our unsigned 64-bit integer to the TEE Big Integer class. It's
+ * an unsigned array of bytes with MSB first.
+ */
+ CK_BYTE publicExponent[sizeof(uint64_t)];
+ const uint64_t exp = rsa_params->public_exponent;
+ size_t offset = sizeof(publicExponent) - 1;
+ for (size_t i = 0; i < sizeof(publicExponent); i++) {
+ publicExponent[offset--] = (exp >> (i * CHAR_BIT)) & 0xFF;
+ }
+
+ Unique_ByteArray objId(generate_random_id());
+ if (objId.get() == NULL) {
+ ALOGE("Couldn't generate random key ID");
+ return -1;
+ }
+
+ CK_ATTRIBUTE publicKeyTemplate[] = {
+ {CKA_ID, objId->get(), objId->length()},
+ {CKA_TOKEN, &bTRUE, sizeof(bTRUE)},
+ {CKA_ENCRYPT, &bTRUE, sizeof(bTRUE)},
+ {CKA_VERIFY, &bTRUE, sizeof(bTRUE)},
+ {CKA_MODULUS_BITS, &modulusBits, sizeof(modulusBits)},
+ {CKA_PUBLIC_EXPONENT, publicExponent, sizeof(publicExponent)},
+ };
+
+ CK_ATTRIBUTE privateKeyTemplate[] = {
+ {CKA_ID, objId->get(), objId->length()},
+ {CKA_TOKEN, &bTRUE, sizeof(bTRUE)},
+ {CKA_DECRYPT, &bTRUE, sizeof(bTRUE)},
+ {CKA_SIGN, &bTRUE, sizeof(bTRUE)},
+ };
+
+ CryptoSession session(reinterpret_cast<CK_SESSION_HANDLE>(dev->context));
+
+ CK_OBJECT_HANDLE hPublicKey, hPrivateKey;
+ CK_RV rv = C_GenerateKeyPair(session.get(),
+ &mechanism,
+ publicKeyTemplate,
+ sizeof(publicKeyTemplate)/sizeof(CK_ATTRIBUTE),
+ privateKeyTemplate,
+ sizeof(privateKeyTemplate)/sizeof(CK_ATTRIBUTE),
+ &hPublicKey,
+ &hPrivateKey);
+
+ if (rv != CKR_OK) {
+ ALOGE("Generate keypair failed: 0x%x", rv);
+ return -1;
+ }
+
+ ObjectHandle publicKey(&session, hPublicKey);
+ ObjectHandle privateKey(&session, hPrivateKey);
+ ALOGV("public handle = 0x%x, private handle = 0x%x", publicKey.get(), privateKey.get());
+
+ return keyblob_save(objId.get(), key_blob, key_blob_length);
+}
+
+static int tee_import_keypair(const keymaster_device_t* dev,
+ const uint8_t* key, const size_t key_length,
+ uint8_t** key_blob, size_t* key_blob_length) {
+ CK_RV rv;
+ CK_BBOOL bTRUE = CK_TRUE;
+
+ if (key == NULL) {
+ ALOGW("provided key is null");
+ return -1;
+ }
+
+ Unique_PKCS8_PRIV_KEY_INFO pkcs8(d2i_PKCS8_PRIV_KEY_INFO(NULL, &key, key_length));
+ if (pkcs8.get() == NULL) {
+ logOpenSSLError("tee_import_keypair");
+ return -1;
+ }
+
+ /* assign to EVP */
+ Unique_EVP_PKEY pkey(EVP_PKCS82PKEY(pkcs8.get()));
+ if (pkey.get() == NULL) {
+ logOpenSSLError("tee_import_keypair");
+ return -1;
+ }
+
+ if (EVP_PKEY_type(pkey->type) != EVP_PKEY_RSA) {
+ ALOGE("Unsupported key type: %d", EVP_PKEY_type(pkey->type));
+ return -1;
+ }
+
+ Unique_RSA rsa(EVP_PKEY_get1_RSA(pkey.get()));
+ if (rsa.get() == NULL) {
+ logOpenSSLError("tee_import_keypair");
+ return -1;
+ }
+
+ Unique_ByteArray modulus(bignum_to_array(rsa->n));
+ if (modulus.get() == NULL) {
+ ALOGW("Could not convert modulus to array");
+ return -1;
+ }
+
+ Unique_ByteArray publicExponent(bignum_to_array(rsa->e));
+ if (publicExponent.get() == NULL) {
+ ALOGW("Could not convert publicExponent to array");
+ return -1;
+ }
+
+ CK_KEY_TYPE rsaType = CKK_RSA;
+
+ CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY;
+
+ Unique_ByteArray objId(generate_random_id());
+ if (objId.get() == NULL) {
+ ALOGE("Couldn't generate random key ID");
+ return -1;
+ }
+
+ CK_ATTRIBUTE publicKeyTemplate[] = {
+ {CKA_ID, objId->get(), objId->length()},
+ {CKA_TOKEN, &bTRUE, sizeof(bTRUE)},
+ {CKA_CLASS, &pubClass, sizeof(pubClass)},
+ {CKA_KEY_TYPE, &rsaType, sizeof(rsaType)},
+ {CKA_ENCRYPT, &bTRUE, sizeof(bTRUE)},
+ {CKA_VERIFY, &bTRUE, sizeof(bTRUE)},
+ {CKA_MODULUS, modulus->get(), modulus->length()},
+ {CKA_PUBLIC_EXPONENT, publicExponent->get(), publicExponent->length()},
+ };
+
+ CryptoSession session(reinterpret_cast<CK_SESSION_HANDLE>(dev->context));
+
+ CK_OBJECT_HANDLE hPublicKey;
+ rv = C_CreateObject(session.get(),
+ publicKeyTemplate,
+ sizeof(publicKeyTemplate)/sizeof(CK_ATTRIBUTE),
+ &hPublicKey);
+ if (rv != CKR_OK) {
+ ALOGE("Creation of public key failed: 0x%x", rv);
+ return -1;
+ }
+ ObjectHandle publicKey(&session, hPublicKey);
+
+ Unique_ByteArray privateExponent(bignum_to_array(rsa->d));
+ if (privateExponent.get() == NULL) {
+ ALOGW("Could not convert private exponent");
+ return -1;
+ }
+
+
+ /*
+ * Normally we need:
+ * CKA_ID
+ * CKA_TOKEN
+ * CKA_CLASS
+ * CKA_KEY_TYPE
+ *
+ * CKA_DECRYPT
+ * CKA_SIGN
+ *
+ * CKA_MODULUS
+ * CKA_PUBLIC_EXPONENT
+ * CKA_PRIVATE_EXPONENT
+ */
+#define PRIV_ATTRIB_NORMAL_NUM (4 + 2 + 3)
+
+ /*
+ * For additional private key values:
+ * CKA_PRIME_1
+ * CKA_PRIME_2
+ *
+ * CKA_EXPONENT_1
+ * CKA_EXPONENT_2
+ *
+ * CKA_COEFFICIENT
+ */
+#define PRIV_ATTRIB_EXTENDED_NUM (PRIV_ATTRIB_NORMAL_NUM + 5)
+
+ /*
+ * If we have the prime, prime exponents, and coefficient, we can
+ * copy them in.
+ */
+ bool has_extra_data = (rsa->p != NULL) && (rsa->q != NULL) && (rsa->dmp1 != NULL) &&
+ (rsa->dmq1 != NULL) && (rsa->iqmp != NULL);
+
+ Unique_CK_ATTRIBUTE privateKeyTemplate(new CK_ATTRIBUTE[
+ has_extra_data ? PRIV_ATTRIB_EXTENDED_NUM : PRIV_ATTRIB_NORMAL_NUM]);
+
+ CK_OBJECT_CLASS privClass = CKO_PRIVATE_KEY;
+
+ size_t templateOffset = 0;
+
+ set_attribute(&privateKeyTemplate[templateOffset++], CKA_ID, objId->get(), objId->length());
+ set_attribute(&privateKeyTemplate[templateOffset++], CKA_TOKEN, &bTRUE, sizeof(bTRUE));
+ set_attribute(&privateKeyTemplate[templateOffset++], CKA_CLASS, &privClass, sizeof(privClass));
+ set_attribute(&privateKeyTemplate[templateOffset++], CKA_KEY_TYPE, &rsaType, sizeof(rsaType));
+
+ set_attribute(&privateKeyTemplate[templateOffset++], CKA_DECRYPT, &bTRUE, sizeof(bTRUE));
+ set_attribute(&privateKeyTemplate[templateOffset++], CKA_SIGN, &bTRUE, sizeof(bTRUE));
+
+ set_attribute(&privateKeyTemplate[templateOffset++], CKA_MODULUS, modulus->get(),
+ modulus->length());
+ set_attribute(&privateKeyTemplate[templateOffset++], CKA_PUBLIC_EXPONENT,
+ publicExponent->get(), publicExponent->length());
+ set_attribute(&privateKeyTemplate[templateOffset++], CKA_PRIVATE_EXPONENT,
+ privateExponent->get(), privateExponent->length());
+
+ Unique_ByteArray prime1, prime2, exp1, exp2, coeff;
+ if (has_extra_data) {
+ prime1.reset(bignum_to_array(rsa->p));
+ if (prime1->get() == NULL) {
+ ALOGW("Could not convert prime1");
+ return -1;
+ }
+ set_attribute(&privateKeyTemplate[templateOffset++], CKA_PRIME_1, prime1->get(),
+ prime1->length());
+
+ prime2.reset(bignum_to_array(rsa->q));
+ if (prime2->get() == NULL) {
+ ALOGW("Could not convert prime2");
+ return -1;
+ }
+ set_attribute(&privateKeyTemplate[templateOffset++], CKA_PRIME_2, prime2->get(),
+ prime2->length());
+
+ exp1.reset(bignum_to_array(rsa->dmp1));
+ if (exp1->get() == NULL) {
+ ALOGW("Could not convert exponent 1");
+ return -1;
+ }
+ set_attribute(&privateKeyTemplate[templateOffset++], CKA_EXPONENT_1, exp1->get(),
+ exp1->length());
+
+ exp2.reset(bignum_to_array(rsa->dmq1));
+ if (exp2->get() == NULL) {
+ ALOGW("Could not convert exponent 2");
+ return -1;
+ }
+ set_attribute(&privateKeyTemplate[templateOffset++], CKA_EXPONENT_2, exp2->get(),
+ exp2->length());
+
+ coeff.reset(bignum_to_array(rsa->iqmp));
+ if (coeff->get() == NULL) {
+ ALOGW("Could not convert coefficient");
+ return -1;
+ }
+ set_attribute(&privateKeyTemplate[templateOffset++], CKA_COEFFICIENT, coeff->get(),
+ coeff->length());
+ }
+
+ CK_OBJECT_HANDLE hPrivateKey;
+ rv = C_CreateObject(session.get(),
+ privateKeyTemplate.get(),
+ templateOffset,
+ &hPrivateKey);
+ if (rv != CKR_OK) {
+ ALOGE("Creation of private key failed: 0x%x", rv);
+ return -1;
+ }
+ ObjectHandle privateKey(&session, hPrivateKey);
+
+ ALOGV("public handle = 0x%x, private handle = 0x%x", publicKey.get(), privateKey.get());
+
+ return keyblob_save(objId.get(), key_blob, key_blob_length);
+}
+
+static int tee_get_keypair_public(const struct keymaster_device* dev,
+ const uint8_t* key_blob, const size_t key_blob_length,
+ uint8_t** x509_data, size_t* x509_data_length) {
+
+ CryptoSession session(reinterpret_cast<CK_SESSION_HANDLE>(dev->context));
+
+ ObjectHandle publicKey(&session);
+ ObjectHandle privateKey(&session);
+
+ if (keyblob_restore(&session, key_blob, key_blob_length, &publicKey, &privateKey)) {
+ return -1;
+ }
+
+ if (x509_data == NULL || x509_data_length == NULL) {
+ ALOGW("Provided destination variables were null");
+ return -1;
+ }
+
+ CK_ATTRIBUTE attributes[] = {
+ {CKA_MODULUS, NULL, 0},
+ {CKA_PUBLIC_EXPONENT, NULL, 0},
+ };
+
+ // Call first to get the sizes of the values.
+ CK_RV rv = C_GetAttributeValue(session.get(), publicKey.get(), attributes,
+ sizeof(attributes)/sizeof(CK_ATTRIBUTE));
+ if (rv != CKR_OK) {
+ ALOGW("Could not query attribute value sizes: 0x%02x", rv);
+ return -1;
+ }
+
+ ByteArray modulus(new CK_BYTE[attributes[0].ulValueLen], attributes[0].ulValueLen);
+ ByteArray exponent(new CK_BYTE[attributes[1].ulValueLen], attributes[1].ulValueLen);
+
+ attributes[0].pValue = modulus.get();
+ attributes[1].pValue = exponent.get();
+
+ rv = C_GetAttributeValue(session.get(), publicKey.get(), attributes,
+ sizeof(attributes) / sizeof(CK_ATTRIBUTE));
+ if (rv != CKR_OK) {
+ ALOGW("Could not query attribute values: 0x%02x", rv);
+ return -1;
+ }
+
+ ALOGV("modulus is %d, exponent is %d", modulus.length(), exponent.length());
+
+ Unique_RSA rsa(RSA_new());
+ if (rsa.get() == NULL) {
+ ALOGE("Could not allocate RSA structure");
+ return -1;
+ }
+
+ rsa->n = BN_bin2bn(reinterpret_cast<const unsigned char*>(modulus.get()), modulus.length(),
+ NULL);
+ if (rsa->n == NULL) {
+ logOpenSSLError("tee_get_keypair_public");
+ return -1;
+ }
+
+ rsa->e = BN_bin2bn(reinterpret_cast<const unsigned char*>(exponent.get()), exponent.length(),
+ NULL);
+ if (rsa->e == NULL) {
+ logOpenSSLError("tee_get_keypair_public");
+ return -1;
+ }
+
+ Unique_EVP_PKEY pkey(EVP_PKEY_new());
+ if (pkey.get() == NULL) {
+ ALOGE("Could not allocate EVP_PKEY structure");
+ return -1;
+ }
+ if (EVP_PKEY_assign_RSA(pkey.get(), rsa.get()) != 1) {
+ logOpenSSLError("tee_get_keypair_public");
+ return -1;
+ }
+ OWNERSHIP_TRANSFERRED(rsa);
+
+ int len = i2d_PUBKEY(pkey.get(), NULL);
+ if (len <= 0) {
+ logOpenSSLError("tee_get_keypair_public");
+ return -1;
+ }
+
+ UniquePtr<uint8_t> key(static_cast<uint8_t*>(malloc(len)));
+ if (key.get() == NULL) {
+ ALOGE("Could not allocate memory for public key data");
+ return -1;
+ }
+
+ unsigned char* tmp = reinterpret_cast<unsigned char*>(key.get());
+ if (i2d_PUBKEY(pkey.get(), &tmp) != len) {
+ logOpenSSLError("tee_get_keypair_public");
+ return -1;
+ }
+
+ ALOGV("Length of x509 data is %d", len);
+ *x509_data_length = len;
+ *x509_data = key.release();
+
+ return 0;
+}
+
+static int tee_delete_keypair(const struct keymaster_device* dev,
+ const uint8_t* key_blob, const size_t key_blob_length) {
+
+ CryptoSession session(reinterpret_cast<CK_SESSION_HANDLE>(dev->context));
+
+ ObjectHandle publicKey(&session);
+ ObjectHandle privateKey(&session);
+
+ if (keyblob_restore(&session, key_blob, key_blob_length, &publicKey, &privateKey)) {
+ return -1;
+ }
+
+ // Delete the private key.
+ CK_RV rv = C_DestroyObject(session.get(), privateKey.get());
+ if (rv != CKR_OK) {
+ ALOGW("Could destroy private key object: 0x%02x", rv);
+ return -1;
+ }
+
+ // Delete the public key.
+ rv = C_DestroyObject(session.get(), publicKey.get());
+ if (rv != CKR_OK) {
+ ALOGW("Could destroy public key object: 0x%02x", rv);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int tee_sign_data(const keymaster_device_t* dev,
+ const void* params,
+ const uint8_t* key_blob, const size_t key_blob_length,
+ const uint8_t* data, const size_t dataLength,
+ uint8_t** signedData, size_t* signedDataLength) {
+ ALOGV("tee_sign_data(%p, %p, %llu, %p, %llu, %p, %p)", dev, key_blob,
+ (unsigned long long) key_blob_length, data, (unsigned long long) dataLength, signedData,
+ signedDataLength);
+
+ if (params == NULL) {
+ ALOGW("Signing params were null");
+ return -1;
+ }
+
+ CryptoSession session(reinterpret_cast<CK_SESSION_HANDLE>(dev->context));
+
+ ObjectHandle publicKey(&session);
+ ObjectHandle privateKey(&session);
+
+ if (keyblob_restore(&session, key_blob, key_blob_length, &publicKey, &privateKey)) {
+ return -1;
+ }
+ ALOGV("public handle = 0x%x, private handle = 0x%x", publicKey.get(), privateKey.get());
+
+ keymaster_rsa_sign_params_t* sign_params = (keymaster_rsa_sign_params_t*) params;
+ if (sign_params->digest_type != DIGEST_NONE) {
+ ALOGW("Cannot handle digest type %d", sign_params->digest_type);
+ return -1;
+ } else if (sign_params->padding_type != PADDING_NONE) {
+ ALOGW("Cannot handle padding type %d", sign_params->padding_type);
+ return -1;
+ }
+
+ CK_MECHANISM rawRsaMechanism = {
+ CKM_RSA_X_509, NULL, 0
+ };
+
+ CK_RV rv = C_SignInit(session.get(), &rawRsaMechanism, privateKey.get());
+ if (rv != CKR_OK) {
+ ALOGV("C_SignInit failed: 0x%x", rv);
+ return -1;
+ }
+
+ CK_BYTE signature[1024];
+ CK_ULONG signatureLength = 1024;
+
+ rv = C_Sign(session.get(), data, dataLength, signature, &signatureLength);
+ if (rv != CKR_OK) {
+ ALOGV("C_SignFinal failed: 0x%x", rv);
+ return -1;
+ }
+
+ UniquePtr<uint8_t[]> finalSignature(new uint8_t[signatureLength]);
+ if (finalSignature.get() == NULL) {
+ ALOGE("Couldn't allocate memory to copy signature");
+ return -1;
+ }
+
+ memcpy(finalSignature.get(), signature, signatureLength);
+
+ *signedData = finalSignature.release();
+ *signedDataLength = static_cast<size_t>(signatureLength);
+
+ ALOGV("tee_sign_data(%p, %p, %llu, %p, %llu, %p, %p) => %p size %llu", dev, key_blob,
+ (unsigned long long) key_blob_length, data, (unsigned long long) dataLength, signedData,
+ signedDataLength, *signedData, (unsigned long long) *signedDataLength);
+
+ return 0;
+}
+
+static int tee_verify_data(const keymaster_device_t* dev,
+ const void* params,
+ const uint8_t* keyBlob, const size_t keyBlobLength,
+ const uint8_t* signedData, const size_t signedDataLength,
+ const uint8_t* signature, const size_t signatureLength) {
+ ALOGV("tee_verify_data(%p, %p, %llu, %p, %llu, %p, %llu)", dev, keyBlob,
+ (unsigned long long) keyBlobLength, signedData, (unsigned long long) signedDataLength,
+ signature, (unsigned long long) signatureLength);
+
+ if (params == NULL) {
+ ALOGW("Verification params were null");
+ return -1;
+ }
+
+ CryptoSession session(reinterpret_cast<CK_SESSION_HANDLE>(dev->context));
+
+ ObjectHandle publicKey(&session);
+ ObjectHandle privateKey(&session);
+
+ if (keyblob_restore(&session, keyBlob, keyBlobLength, &publicKey, &privateKey)) {
+ return -1;
+ }
+ ALOGV("public handle = 0x%x, private handle = 0x%x", publicKey.get(), privateKey.get());
+
+ keymaster_rsa_sign_params_t* sign_params = (keymaster_rsa_sign_params_t*) params;
+ if (sign_params->digest_type != DIGEST_NONE) {
+ ALOGW("Cannot handle digest type %d", sign_params->digest_type);
+ return -1;
+ } else if (sign_params->padding_type != PADDING_NONE) {
+ ALOGW("Cannot handle padding type %d", sign_params->padding_type);
+ return -1;
+ }
+
+ CK_MECHANISM rawRsaMechanism = {
+ CKM_RSA_X_509, NULL, 0
+ };
+
+ CK_RV rv = C_VerifyInit(session.get(), &rawRsaMechanism, publicKey.get());
+ if (rv != CKR_OK) {
+ ALOGV("C_VerifyInit failed: 0x%x", rv);
+ return -1;
+ }
+
+ // This is a bad prototype for this function. C_Verify should have only const args.
+ rv = C_Verify(session.get(), signedData, signedDataLength,
+ const_cast<unsigned char*>(signature), signatureLength);
+ if (rv != CKR_OK) {
+ ALOGV("C_Verify failed: 0x%x", rv);
+ return -1;
+ }
+
+ return 0;
+}
+
+/* Close an opened OpenSSL instance */
+static int tee_close(hw_device_t *dev) {
+ keymaster_device_t *keymaster_dev = (keymaster_device_t *) dev;
+ if (keymaster_dev != NULL) {
+ CK_SESSION_HANDLE handle = reinterpret_cast<CK_SESSION_HANDLE>(keymaster_dev->context);
+ if (handle != CK_INVALID_HANDLE) {
+ C_CloseSession(handle);
+ }
+ }
+
+ CK_RV finalizeRV = C_Finalize(NULL_PTR);
+ if (finalizeRV != CKR_OK) {
+ ALOGE("Error closing the TEE");
+ }
+ free(dev);
+
+ return 0;
+}
+
+/*
+ * Generic device handling
+ */
+static int tee_open(const hw_module_t* module, const char* name,
+ hw_device_t** device) {
+ if (strcmp(name, KEYSTORE_KEYMASTER) != 0)
+ return -EINVAL;
+
+ Unique_keymaster_device_t dev(new keymaster_device_t);
+ if (dev.get() == NULL)
+ return -ENOMEM;
+
+ dev->common.tag = HARDWARE_DEVICE_TAG;
+ dev->common.version = 1;
+ dev->common.module = (struct hw_module_t*) module;
+ dev->common.close = tee_close;
+
+ dev->generate_keypair = tee_generate_keypair;
+ dev->import_keypair = tee_import_keypair;
+ dev->get_keypair_public = tee_get_keypair_public;
+ dev->delete_keypair = tee_delete_keypair;
+ dev->sign_data = tee_sign_data;
+ dev->verify_data = tee_verify_data;
+
+ CK_RV initializeRV = C_Initialize(NULL);
+ if (initializeRV != CKR_OK) {
+ ALOGE("Error initializing TEE: 0x%x", initializeRV);
+ return -ENODEV;
+ }
+
+ CK_INFO info;
+ CK_RV infoRV = C_GetInfo(&info);
+ if (infoRV != CKR_OK) {
+ (void) C_Finalize(NULL_PTR);
+ ALOGE("Error getting information about TEE during initialization: 0x%x", infoRV);
+ return -ENODEV;
+ }
+
+ ALOGI("C_GetInfo cryptokiVer=%d.%d manufID=%s flags=%d libDesc=%s libVer=%d.%d\n",
+ info.cryptokiVersion.major, info.cryptokiVersion.minor,
+ info.manufacturerID, info.flags, info.libraryDescription,
+ info.libraryVersion.major, info.libraryVersion.minor);
+
+ CK_SESSION_HANDLE sessionHandle = CK_INVALID_HANDLE;
+
+ CK_RV openSessionRV = C_OpenSession(CKV_TOKEN_USER,
+ CKF_SERIAL_SESSION | CKF_RW_SESSION,
+ NULL,
+ NULL,
+ &sessionHandle);
+
+ if (openSessionRV != CKR_OK || sessionHandle == CK_INVALID_HANDLE) {
+ (void) C_Finalize(NULL_PTR);
+ ALOGE("Error opening primary session with TEE: 0x%x", openSessionRV);
+ return -1;
+ }
+
+ ERR_load_crypto_strings();
+ ERR_load_BIO_strings();
+
+ dev->context = reinterpret_cast<void*>(sessionHandle);
+ *device = reinterpret_cast<hw_device_t*>(dev.release());
+
+ return 0;
+}
+
+static struct hw_module_methods_t keystore_module_methods = {
+ open: tee_open,
+};
+
+struct keystore_module HAL_MODULE_INFO_SYM
+__attribute__ ((visibility ("default"))) = {
+ common: {
+ tag: HARDWARE_MODULE_TAG,
+ version_major: 1,
+ version_minor: 0,
+ id: KEYSTORE_HARDWARE_MODULE_ID,
+ name: "Keymaster TEE HAL",
+ author: "The Android Open Source Project",
+ methods: &keystore_module_methods,
+ dso: 0,
+ reserved: {},
+ },
+};
diff --git a/liblight/lights.c b/liblight/lights.c
index 8c675b2..1dfcd8b 100644
--- a/liblight/lights.c
+++ b/liblight/lights.c
@@ -54,7 +54,7 @@ static int write_int(char const *path, int value)
already_warned = 0;
- LOGV("write_int: path %s, value %d", path, value);
+ ALOGV("write_int: path %s, value %d", path, value);
fd = open(path, O_RDWR);
if (fd >= 0) {
@@ -65,7 +65,7 @@ static int write_int(char const *path, int value)
return amt == -1 ? -errno : 0;
} else {
if (already_warned == 0) {
- LOGE("write_int failed to open %s\n", path);
+ ALOGE("write_int failed to open %s\n", path);
already_warned = 1;
}
return -errno;
@@ -95,7 +95,7 @@ static int set_light_backlight(struct light_device_t *dev,
static int close_lights(struct light_device_t *dev)
{
- LOGV("close_light is called");
+ ALOGV("close_light is called");
if (dev)
free(dev);
@@ -115,15 +115,15 @@ static int write_leds(struct an30259a_pr_control *led)
if (fd >= 0) {
err = ioctl(fd, AN30259A_PR_SET_IMAX, &imax);
if (err)
- LOGE("failed to set imax");
+ ALOGE("failed to set imax");
err = ioctl(fd, AN30259A_PR_SET_LED, led);
if (err < 0)
- LOGE("failed to set leds!");
+ ALOGE("failed to set leds!");
close(fd);
} else {
- LOGE("failed to open %s!", LED_FILE);
+ ALOGE("failed to open %s!", LED_FILE);
err = -errno;
}
@@ -211,7 +211,7 @@ static struct hw_module_methods_t lights_module_methods = {
.open = open_lights,
};
-const struct hw_module_t HAL_MODULE_INFO_SYM = {
+struct hw_module_t HAL_MODULE_INFO_SYM = {
.tag = HARDWARE_MODULE_TAG,
.version_major = 1,
.version_minor = 0,
diff --git a/libsensors/SamsungSensorBase.cpp b/libsensors/SamsungSensorBase.cpp
index 0ec4915..fe3f14e 100644
--- a/libsensors/SamsungSensorBase.cpp
+++ b/libsensors/SamsungSensorBase.cpp
@@ -70,13 +70,13 @@ SamsungSensorBase::SamsungSensorBase(const char *dev_name,
return;
mInputSysfsEnable = makeSysfsName(input_name, "enable");
if (!mInputSysfsEnable) {
- LOGE("%s: unable to allocate mem for %s:enable", __func__,
+ ALOGE("%s: unable to allocate mem for %s:enable", __func__,
data_name);
return;
}
mInputSysfsPollDelay = makeSysfsName(input_name, "poll_delay");
if (!mInputSysfsPollDelay) {
- LOGE("%s: unable to allocate mem for %s:poll_delay", __func__,
+ ALOGE("%s: unable to allocate mem for %s:poll_delay", __func__,
data_name);
return;
}
diff --git a/libsensors/sensors.cpp b/libsensors/sensors.cpp
index 156f08d..2a33731 100644
--- a/libsensors/sensors.cpp
+++ b/libsensors/sensors.cpp
@@ -16,7 +16,7 @@
#define LOG_NDEBUG 0
#define LOG_TAG "Sensors"
-//#define FUNC_LOG LOGV("%s", __PRETTY_FUNCTION__)
+//#define FUNC_LOG ALOGV("%s", __PRETTY_FUNCTION__)
#define FUNC_LOG
#include <hardware/sensors.h>
@@ -215,7 +215,7 @@ sensors_poll_context_t::sensors_poll_context_t()
int wakeFds[2];
int result = pipe(wakeFds);
- LOGE_IF(result<0, "error creating wake pipe (%s)", strerror(errno));
+ ALOGE_IF(result<0, "error creating wake pipe (%s)", strerror(errno));
fcntl(wakeFds[0], F_SETFL, O_NONBLOCK);
fcntl(wakeFds[1], F_SETFL, O_NONBLOCK);
mWritePipeFd = wakeFds[1];
@@ -249,7 +249,7 @@ int sensors_poll_context_t::activate(int handle, int enabled)
if (!err) {
const char wakeMessage(WAKE_MESSAGE);
int result = write(mWritePipeFd, &wakeMessage, 1);
- LOGE_IF(result<0, "error sending wake message (%s)", strerror(errno));
+ ALOGE_IF(result<0, "error sending wake message (%s)", strerror(errno));
}
return err;
}
@@ -306,14 +306,14 @@ int sensors_poll_context_t::pollEvents(sensors_event_t* data, int count)
n = poll(mPollFds, numFds, nbEvents ? 0 : polltime);
} while (n < 0 && errno == EINTR);
if (n<0) {
- LOGE("poll() failed (%s)", strerror(errno));
+ ALOGE("poll() failed (%s)", strerror(errno));
return -errno;
}
if (mPollFds[wake].revents & POLLIN) {
char msg;
int result = read(mPollFds[wake].fd, &msg, 1);
- LOGE_IF(result<0, "error reading from wake pipe (%s)", strerror(errno));
- LOGE_IF(msg != WAKE_MESSAGE, "unknown message on wake queue (0x%02x)", int(msg));
+ ALOGE_IF(result<0, "error reading from wake pipe (%s)", strerror(errno));
+ ALOGE_IF(msg != WAKE_MESSAGE, "unknown message on wake queue (0x%02x)", int(msg));
mPollFds[wake].revents = 0;
}
if(mPollFds[mpl_power].revents & POLLIN) {
diff --git a/media_codecs.xml b/media_codecs.xml
new file mode 100644
index 0000000..af21aa4
--- /dev/null
+++ b/media_codecs.xml
@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!-- Copyright (C) 2012 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.
+-->
+
+<!--
+<!DOCTYPE MediaCodecs [
+<!ELEMENT MediaCodecs (Decoders,Encoders)>
+<!ELEMENT Decoders (MediaCodec*)>
+<!ELEMENT Encoders (MediaCodec*)>
+<!ELEMENT MediaCodec (Type*,Quirk*)>
+<!ATTLIST MediaCodec name CDATA #REQUIRED>
+<!ATTLIST MediaCodec type CDATA>
+<!ELEMENT Type EMPTY>
+<!ATTLIST Type name CDATA #REQUIRED>
+<!ELEMENT Quirk EMPTY>
+<!ATTLIST Quirk name CDATA #REQUIRED>
+]>
+
+There's a simple and a complex syntax to declare the availability of a
+media codec:
+
+A codec that properly follows the OpenMax spec and therefore doesn't have any
+quirks and that only supports a single content type can be declared like so:
+
+ <MediaCodec name="OMX.foo.bar" type="something/interesting" />
+
+If a codec has quirks OR supports multiple content types, the following syntax
+can be used:
+
+ <MediaCodec name="OMX.foo.bar" >
+ <Type name="something/interesting" />
+ <Type name="something/else" />
+ ...
+ <Quirk name="requires-allocate-on-input-ports" />
+ <Quirk name="requires-allocate-on-output-ports" />
+ <Quirk name="output-buffers-are-unreadable" />
+ </MediaCodec>
+
+Only the three quirks included above are recognized at this point:
+
+"requires-allocate-on-input-ports"
+ must be advertised if the component does not properly support specification
+ of input buffers using the OMX_UseBuffer(...) API but instead requires
+ OMX_AllocateBuffer to be used.
+
+"requires-allocate-on-output-ports"
+ must be advertised if the component does not properly support specification
+ of output buffers using the OMX_UseBuffer(...) API but instead requires
+ OMX_AllocateBuffer to be used.
+
+"output-buffers-are-unreadable"
+ must be advertised if the emitted output buffers of a decoder component
+ are not readable, i.e. use a custom format even though abusing one of
+ the official OMX colorspace constants.
+ Clients of such decoders will not be able to access the decoded data,
+ naturally making the component much less useful. The only use for
+ a component with this quirk is to render the output to the screen.
+ Audio decoders MUST NOT advertise this quirk.
+ Video decoders that advertise this quirk must be accompanied by a
+ corresponding color space converter for thumbnail extraction,
+ matching surfaceflinger support that can render the custom format to
+ a texture and possibly other code, so just DON'T USE THIS QUIRK.
+
+-->
+
+<MediaCodecs>
+ <Decoders>
+ <MediaCodec name="OMX.TI.DUCATI1.VIDEO.DECODER" >
+ <Type name="video/mp4v-es" />
+ <Type name="video/3gpp" />
+ <Type name="video/avc" />
+ <Quirk name="requires-allocate-on-input-ports" />
+ <Quirk name="requires-allocate-on-output-ports" />
+ </MediaCodec>
+
+ <MediaCodec name="OMX.google.mp3.decoder" type="audio/mpeg" />
+ <MediaCodec name="OMX.google.amrnb.decoder" type="audio/3gpp" />
+ <MediaCodec name="OMX.google.amrwb.decoder" type="audio/amr-wb" />
+ <MediaCodec name="OMX.google.aac.decoder" type="audio/mp4a-latm" />
+ <MediaCodec name="OMX.google.g711.alaw.decoder" type="audio/g711-alaw" />
+ <MediaCodec name="OMX.google.g711.mlaw.decoder" type="audio/g711-mlaw" />
+ <MediaCodec name="OMX.google.vorbis.decoder" type="audio/vorbis" />
+
+ <MediaCodec name="OMX.google.mpeg4.decoder" type="video/mp4v-es" />
+ <MediaCodec name="OMX.google.h263.decoder" type="video/3gpp" />
+ <MediaCodec name="OMX.google.h264.decoder" type="video/avc" />
+ <MediaCodec name="OMX.google.vpx.decoder" type="video/x-vnd.on2.vp8" />
+ </Decoders>
+
+ <Encoders>
+ <MediaCodec name="OMX.TI.DUCATI1.VIDEO.MPEG4E" >
+ <Type name="video/mp4v-es" />
+ <Type name="video/3gpp" />
+ <Quirk name="requires-allocate-on-input-ports" />
+ <Quirk name="requires-allocate-on-output-ports" />
+ </MediaCodec>
+
+ <MediaCodec name="OMX.TI.DUCATI1.VIDEO.H264E" type="video/avc" >
+ <Quirk name="requires-allocate-on-input-ports" />
+ <Quirk name="requires-allocate-on-output-ports" />
+ </MediaCodec>
+
+ <MediaCodec name="OMX.google.amrnb.encoder" type="audio/3gpp" />
+ <MediaCodec name="OMX.google.amrwb.encoder" type="audio/amr-wb" />
+ <MediaCodec name="OMX.google.aac.encoder" type="audio/mp4a-latm" />
+ </Encoders>
+</MediaCodecs>
diff --git a/media_profiles.xml b/media_profiles.xml
index 02058a5..5769e2b 100755
--- a/media_profiles.xml
+++ b/media_profiles.xml
@@ -149,11 +149,11 @@
channels="1" />
</EncoderProfile>
- <EncoderProfile quality="timelapseqcif" fileFormat="mp4" duration="30">
+ <EncoderProfile quality="timelapseqvga" fileFormat="mp4" duration="30">
<Video codec="h264"
bitRate="192000"
- width="176"
- height="144"
+ width="320"
+ height="240"
frameRate="30" />
<!-- audio setting is ignored -->
<Audio codec="amrnb"
@@ -271,11 +271,11 @@
channels="1" />
</EncoderProfile>
- <EncoderProfile quality="timelapseqcif" fileFormat="mp4" duration="30">
+ <EncoderProfile quality="timelapseqvga" fileFormat="mp4" duration="30">
<Video codec="h264"
bitRate="192000"
- width="176"
- height="144"
+ width="320"
+ height="240"
frameRate="30" />
<!-- audio setting is ignored -->
<Audio codec="amrnb"
@@ -367,7 +367,7 @@
minChannels="1" maxChannels="1" />
<AudioEncoderCap name="amrnb" enabled="true"
- minBitRate="5525" maxBitRate="12200"
+ minBitRate="4750" maxBitRate="12200"
minSampleRate="8000" maxSampleRate="8000"
minChannels="1" maxChannels="1" />
diff --git a/nfc/nfc_hw.c b/nfc/nfc_hw.c
index 99adc29..cd26be5 100644
--- a/nfc/nfc_hw.c
+++ b/nfc/nfc_hw.c
@@ -31,8 +31,6 @@ static uint8_t pn544_eedata_settings[][4] = {
,{0x00,0x9B,0xD6,0x1E} // GSP setting for this threshold
,{0x00,0x9B,0xDD,0x1C} // GSP setting for this threshold
,{0x00,0x9B,0x84,0x13} // ANACM2 setting
- ,{0x00,0x99,0x81,0x7F} // ANAVMID setting PCD
- ,{0x00,0x99,0x31,0x70} // ANAVMID setting PICC
#ifdef maguro
// Maguro load modulation settings
,{0x00,0x99,0x29,0xF4} // Type A load modulation amplitude fine tuning
@@ -86,8 +84,8 @@ static uint8_t pn544_eedata_settings[][4] = {
,{0x00,0x9C,0x12,0x00} //
,{0x00,0x9C,0x13,0x00} //
- //WTX for LLCP communication
- ,{0x00,0x98,0xA2,0x0E} // Max value: 14 (default value: 09)
+ // NFC-DEP Target Waiting Time (WT)
+ ,{0x00,0x98,0xA2,0x08} // Set to 0x08 as required by [digital] (default value: 09)
//SE GPIO
,{0x00, 0x98, 0x93, 0x40}
diff --git a/overlay/frameworks/base/core/res/res/values/config.xml b/overlay/frameworks/base/core/res/res/values/config.xml
index 1af8aad..5b1f566 100644
--- a/overlay/frameworks/base/core/res/res/values/config.xml
+++ b/overlay/frameworks/base/core/res/res/values/config.xml
@@ -41,10 +41,10 @@
<bool name="config_unplugTurnsOnScreen">true</bool>
<!-- Component name of the service providing network location support. -->
- <string name="config_networkLocationProvider">com.google.android.location.NetworkLocationProvider</string>
+ <string name="config_networkLocationProvider" translatable="false">com.google.android.location.NetworkLocationProvider</string>
<!-- Component name of the service providing geocoder API support. -->
- <string name="config_geocodeProvider">com.google.android.location.GeocodeProvider</string>
+ <string name="config_geocodeProvider" translatable="false">com.google.android.location.GeocodeProvider</string>
<!-- Flag indicating whether we should enable the automatic brightness in Settings.
config_hardware_automatic_brightness_available is not set, so we will use software implementation -->
@@ -239,17 +239,17 @@
<bool name="config_ui_enableFadingMarquee">false</bool>
<!-- Component name of the service providing network location support. -->
- <string name="config_networkLocationProvider">com.google.android.location.NetworkLocationProvider</string>
+ <string name="config_networkLocationProvider" translatable="false">com.google.android.location.NetworkLocationProvider</string>
<!-- Component name of the service providing geocoder API support. -->
- <string name="config_geocodeProvider">com.google.android.location.GeocodeProvider</string>
+ <string name="config_geocodeProvider" translatable="false">com.google.android.location.GeocodeProvider</string>
<!-- Is the notification LED intrusive? Used to decide if there should be a disable option -->
<bool name="config_intrusiveNotificationLed">true</bool>
<!-- Component name of the default wallpaper. This will be ImageWallpaper if not
specified -->
- <string name="default_wallpaper_component">com.android.phasebeam/.PhaseBeamWallpaper</string>
+ <string name="default_wallpaper_component" translatable="false">com.android.phasebeam/.PhaseBeamWallpaper</string>
<!-- Vibrator pattern for feedback about touching a virtual key -->
<integer-array name="config_virtualKeyVibePattern">
diff --git a/overlay/frameworks/base/core/res/res/xml/storage_list.xml b/overlay/frameworks/base/core/res/res/xml/storage_list.xml
index 043530d..0a03928 100644
--- a/overlay/frameworks/base/core/res/res/xml/storage_list.xml
+++ b/overlay/frameworks/base/core/res/res/xml/storage_list.xml
@@ -33,7 +33,7 @@
-->
<StorageList xmlns:android="http://schemas.android.com/apk/res/android">
- <storage android:mountPoint="/mnt/sdcard"
+ <storage android:mountPoint="/storage/sdcard0"
android:storageDescription="@string/storage_internal"
android:primary="true"
android:emulated="true"
diff --git a/overlay/packages/apps/Settings/res/values-pl/arrays.xml b/overlay/packages/apps/Settings/res/values-pl/arrays.xml
index 265da14..3028803 100644
--- a/overlay/packages/apps/Settings/res/values-pl/arrays.xml
+++ b/overlay/packages/apps/Settings/res/values-pl/arrays.xml
@@ -21,11 +21,11 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string-array name="screen_timeout_entries">
- <item msgid="5314770629356662739">"15 sekund"</item>
- <item msgid="8672738773876256432">"30 sekund"</item>
- <item msgid="465923292941002466">"1 minuta"</item>
- <item msgid="7955177189296850016">"2 minuty"</item>
- <item msgid="1244255986255344525">"5 minut"</item>
- <item msgid="294890536998091748">"10 minut"</item>
+ <item msgid="5314770629356662739">"15 sek."</item>
+ <item msgid="8672738773876256432">"30 sek."</item>
+ <item msgid="465923292941002466">"1 min."</item>
+ <item msgid="7955177189296850016">"2 min."</item>
+ <item msgid="1244255986255344525">"5 min."</item>
+ <item msgid="294890536998091748">"10 min."</item>
</string-array>
</resources>
diff --git a/overlay/packages/apps/Settings/res/values/bools.xml b/overlay/packages/apps/Settings/res/values/bools.xml
index b5e8b7b..711eb51 100644
--- a/overlay/packages/apps/Settings/res/values/bools.xml
+++ b/overlay/packages/apps/Settings/res/values/bools.xml
@@ -17,4 +17,6 @@
<resources>
<!-- Show dock settings when docked -->
<bool name="has_dock_settings">true</bool>
+ <!-- Enable user management -->
+ <bool name="enable_user_management">true</bool>
</resources>
diff --git a/power/Android.mk b/power/Android.mk
new file mode 100644
index 0000000..da60418
--- /dev/null
+++ b/power/Android.mk
@@ -0,0 +1,27 @@
+# Copyright (C) 2012 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.
+
+
+LOCAL_PATH := $(call my-dir)
+
+# HAL module implemenation stored in
+# hw/<POWERS_HARDWARE_MODULE_ID>.<ro.hardware>.so
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
+LOCAL_SHARED_LIBRARIES := liblog libcutils
+LOCAL_SRC_FILES := power_tuna.c
+LOCAL_MODULE := power.tuna
+LOCAL_MODULE_TAGS := optional
+include $(BUILD_SHARED_LIBRARY)
diff --git a/power/power_tuna.c b/power/power_tuna.c
new file mode 100644
index 0000000..eb38410
--- /dev/null
+++ b/power/power_tuna.c
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2012 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 <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#define LOG_TAG "Tuna PowerHAL"
+#include <utils/Log.h>
+
+#include <hardware/hardware.h>
+#include <hardware/power.h>
+
+/*
+ * Tuna uses the legacy interface for requesting early suspend and late resume.
+ */
+
+#define LEGACY_SYS_POWER_STATE "/sys/power/state"
+
+static int sPowerStatefd;
+static const char *pwr_states[] = { "mem", "on" };
+
+static void sysfs_write(char *path, char *s)
+{
+ char buf[80];
+ int len;
+ int fd = open(path, O_WRONLY);
+
+ if (fd < 0) {
+ strerror_r(errno, buf, sizeof(buf));
+ ALOGE("Error opening %s: %s\n", path, buf);
+ return;
+ }
+
+ len = write(fd, s, strlen(s));
+ if (len < 0) {
+ strerror_r(errno, buf, sizeof(buf));
+ ALOGE("Error writing to %s: %s\n", path, buf);
+ }
+
+ close(fd);
+}
+
+static void tuna_power_init(struct power_module *module)
+{
+ char buf[80];
+
+ sPowerStatefd = open(LEGACY_SYS_POWER_STATE, O_RDWR);
+
+ if (sPowerStatefd < 0) {
+ strerror_r(errno, buf, sizeof(buf));
+ ALOGE("Error opening %s: %s\n", LEGACY_SYS_POWER_STATE, buf);
+ }
+
+ /*
+ * cpufreq interactive governor: timer 20ms, min sample 100ms,
+ * hispeed 700MHz at load 40%
+ */
+
+ sysfs_write("/sys/devices/system/cpu/cpufreq/interactive/timer_rate",
+ "20000");
+ sysfs_write("/sys/devices/system/cpu/cpufreq/interactive/min_sample_time",
+ "100000");
+ sysfs_write("/sys/devices/system/cpu/cpufreq/interactive/hispeed_freq",
+ "700000");
+ sysfs_write("/sys/devices/system/cpu/cpufreq/interactive/go_hispeed_load",
+ "40");
+ sysfs_write("/sys/devices/system/cpu/cpufreq/interactive/above_hispeed_delay",
+ "100000");
+}
+
+static void tuna_power_set_interactive(struct power_module *module, int on)
+{
+ char buf[80];
+ int len;
+
+ /*
+ * Lower maximum frequency when screen is off. CPU 0 and 1 share a
+ * cpufreq policy.
+ */
+
+ sysfs_write("/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq",
+ on ? "1200000" : "700000");
+
+ len = write(sPowerStatefd, pwr_states[!!on], strlen(pwr_states[!!on]));
+ if (len < 0) {
+ strerror_r(errno, buf, sizeof(buf));
+ ALOGE("Error writing to %s: %s\n", LEGACY_SYS_POWER_STATE, buf);
+ }
+}
+
+
+static struct hw_module_methods_t power_module_methods = {
+ .open = NULL,
+};
+
+struct power_module HAL_MODULE_INFO_SYM = {
+ .common = {
+ .tag = HARDWARE_MODULE_TAG,
+ .version_major = 1,
+ .version_minor = 0,
+ .id = POWER_HARDWARE_MODULE_ID,
+ .name = "Tuna Power HAL",
+ .author = "The Android Open Source Project",
+ .methods = &power_module_methods,
+ },
+
+ .init = tuna_power_init,
+ .setInteractive = tuna_power_set_interactive,
+};
diff --git a/recovery/Android.mk b/recovery/Android.mk
index 2fc8313..770feee 100644
--- a/recovery/Android.mk
+++ b/recovery/Android.mk
@@ -5,7 +5,7 @@ include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := eng
LOCAL_C_INCLUDES += bootable/recovery
-LOCAL_SRC_FILES := recovery_ui.c
+LOCAL_SRC_FILES := recovery_ui.cpp
# should match TARGET_RECOVERY_UI_LIB set in BoardConfig.mk
LOCAL_MODULE := librecovery_ui_tuna
diff --git a/recovery/recovery_ui.c b/recovery/recovery_ui.c
deleted file mode 100644
index 50f8383..0000000
--- a/recovery/recovery_ui.c
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright (C) 2011 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 <linux/input.h>
-#include <sys/stat.h>
-#include <errno.h>
-#include <string.h>
-
-#include "recovery_ui.h"
-#include "common.h"
-
-char* MENU_HEADERS[] = { "Volume up/down to move highlight;",
- "power button to select.",
- "",
- NULL };
-
-char* MENU_ITEMS[] = { "reboot system now",
- "apply update from /cache",
- "wipe data/factory reset",
- "wipe cache partition",
- NULL };
-
-void device_ui_init(UIParameters* ui_parameters) {
-}
-
-int device_recovery_start() {
- // recovery can get started before the kernel has created the EMMC
- // devices, which will make the wipe_data operation fail (trying
- // to open a device that doesn't exist). Hold up the start of
- // recovery for up to 5 seconds waiting for the userdata partition
- // block device to exist.
-
- const char* fn = "/dev/block/platform/omap/omap_hsmmc.0/by-name/userdata";
-
- int tries = 0;
- int ret;
- struct stat buf;
- do {
- ++tries;
- ret = stat(fn, &buf);
- if (ret) {
- printf("try %d: %s\n", tries, strerror(errno));
- sleep(1);
- }
- } while (ret && tries < 5);
- if (!ret) {
- printf("stat() of %s succeeded on try %d\n", fn, tries);
- } else {
- printf("failed to stat %s\n", fn);
- }
-
- // We let recovery attempt to carry on even if the stat never
- // succeeded.
-
- return 0;
-}
-
-int device_toggle_display(volatile char* key_pressed, int key_code) {
- // hold power and press volume-up
- return key_pressed[KEY_POWER] && key_code == KEY_VOLUMEUP;
-}
-
-int device_reboot_now(volatile char* key_pressed, int key_code) {
- // Reboot if the power key is pressed five times in a row, with
- // no other keys in between.
- static int presses = 0;
- if (key_code == KEY_POWER) { // power button
- ++presses;
- return presses == 5;
- } else {
- presses = 0;
- return 0;
- }
-}
-
-int device_handle_key(int key_code, int visible) {
- if (visible) {
- switch (key_code) {
- case KEY_DOWN:
- case KEY_VOLUMEDOWN:
- return HIGHLIGHT_DOWN;
-
- case KEY_UP:
- case KEY_VOLUMEUP:
- return HIGHLIGHT_UP;
-
- case KEY_ENTER:
- case KEY_POWER: // crespo power
- return SELECT_ITEM;
- }
- }
-
- return NO_ACTION;
-}
-
-int device_perform_action(int which) {
- return which == 1 ? ITEM_APPLY_CACHE : which;
-}
-
-int device_wipe_data() {
- return 0;
-}
diff --git a/recovery/recovery_ui.cpp b/recovery/recovery_ui.cpp
new file mode 100644
index 0000000..0c8b8f9
--- /dev/null
+++ b/recovery/recovery_ui.cpp
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2011 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 <linux/input.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <string.h>
+
+#include "common.h"
+#include "device.h"
+#include "screen_ui.h"
+
+const char* HEADERS[] = { "Volume up/down to move highlight;",
+ "power button to select.",
+ "",
+ NULL };
+
+const char* ITEMS[] = { "reboot system now",
+ "apply update from ADB",
+ "apply update from USB drive",
+ "wipe data/factory reset",
+ "wipe cache partition",
+ NULL };
+
+class TunaUI : public ScreenRecoveryUI {
+ public:
+ TunaUI() :
+ consecutive_power_keys(0) {
+ }
+
+ virtual KeyAction CheckKey(int key) {
+ if (IsKeyPressed(KEY_POWER) && key == KEY_VOLUMEUP) {
+ return TOGGLE;
+ }
+ if (key == KEY_POWER) {
+ ++consecutive_power_keys;
+ if (consecutive_power_keys >= 7) {
+ return REBOOT;
+ }
+ } else {
+ consecutive_power_keys = 0;
+ }
+ return ENQUEUE;
+ }
+
+ private:
+ int consecutive_power_keys;
+};
+
+
+class TunaDevice : public Device {
+ public:
+ TunaDevice() :
+ ui(new TunaUI) {
+ }
+
+ RecoveryUI* GetUI() { return ui; }
+
+ int HandleMenuKey(int key_code, int visible) {
+ if (visible) {
+ switch (key_code) {
+ case KEY_DOWN:
+ case KEY_VOLUMEDOWN:
+ return kHighlightDown;
+
+ case KEY_UP:
+ case KEY_VOLUMEUP:
+ return kHighlightUp;
+
+ case KEY_POWER:
+ return kInvokeItem;
+ }
+ }
+
+ return kNoAction;
+ }
+
+ BuiltinAction InvokeMenuItem(int menu_position) {
+ switch (menu_position) {
+ case 0: return REBOOT;
+ case 1: return APPLY_ADB_SIDELOAD;
+ case 2: return APPLY_EXT;
+ case 3: return WIPE_DATA;
+ case 4: return WIPE_CACHE;
+ default: return NO_ACTION;
+ }
+ }
+
+ const char* const* GetMenuHeaders() { return HEADERS; }
+ const char* const* GetMenuItems() { return ITEMS; }
+
+ private:
+ RecoveryUI* ui;
+};
+
+Device* make_device() {
+ return new TunaDevice;
+}
diff --git a/sii9234_rcp.kcm b/sii9234_rcp.kcm
new file mode 100644
index 0000000..6fc2422
--- /dev/null
+++ b/sii9234_rcp.kcm
@@ -0,0 +1,15 @@
+# Copyright (C) 2012 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.
+
+type SPECIAL_FUNCTION
diff --git a/sii9234_rcp.kl b/sii9234_rcp.kl
new file mode 100644
index 0000000..12589f8
--- /dev/null
+++ b/sii9234_rcp.kl
@@ -0,0 +1,49 @@
+# Copyright (C) 2012 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.
+
+key 353 DPAD_CENTER
+key 103 DPAD_UP
+key 108 DPAD_DOWN
+key 105 DPAD_LEFT
+key 106 DPAD_RIGHT
+
+key 139 MENU
+
+key 174 BACK
+
+key 512 NUMPAD_0
+key 513 NUMPAD_1
+key 514 NUMPAD_2
+key 515 NUMPAD_3
+key 516 NUMPAD_4
+key 517 NUMPAD_5
+key 518 NUMPAD_6
+key 519 NUMPAD_7
+key 520 NUMPAD_8
+key 521 NUMPAD_9
+key 52 NUMPAD_DOT
+key 28 NUMPAD_ENTER
+key 355 CLEAR
+
+key 207 MEDIA_PLAY
+key 128 MEDIA_STOP
+key 164 MEDIA_PLAY_PAUSE
+
+key 168 MEDIA_REWIND
+key 208 MEDIA_FAST_FORWARD
+
+key 163 MEDIA_NEXT
+key 165 MEDIA_PREVIOUS
+
+key 119 MEDIA_PAUSE