upload android base code part6
This commit is contained in:
parent
421e214c7d
commit
4e516ec6ed
35396 changed files with 9188716 additions and 0 deletions
29
android/system/media/radio/Android.bp
Normal file
29
android/system/media/radio/Android.bp
Normal file
|
@ -0,0 +1,29 @@
|
|||
cc_library_shared {
|
||||
name: "libradio_metadata",
|
||||
vendor_available: true,
|
||||
vndk: {
|
||||
enabled: true,
|
||||
},
|
||||
|
||||
srcs: [
|
||||
"src/radio_metadata.c",
|
||||
"src/RadioMetadataWrapper.cpp",
|
||||
],
|
||||
|
||||
cflags: [
|
||||
"-Werror",
|
||||
"-Wall",
|
||||
"-fvisibility=hidden",
|
||||
],
|
||||
|
||||
header_libs: ["libsystem_headers"],
|
||||
export_header_lib_headers: ["libsystem_headers"],
|
||||
|
||||
local_include_dirs: ["include"],
|
||||
export_include_dirs: ["include"],
|
||||
|
||||
shared_libs: [
|
||||
"libcutils",
|
||||
"liblog",
|
||||
],
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
#ifndef ANDROID_RADIO_METADATA_WRAPPER_H
|
||||
#define ANDROID_RADIO_METADATA_WRAPPER_H
|
||||
|
||||
#include <system/radio_metadata.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
class ANDROID_API RadioMetadataWrapper
|
||||
{
|
||||
public:
|
||||
explicit RadioMetadataWrapper(radio_metadata_t **metadata);
|
||||
|
||||
virtual ~RadioMetadataWrapper();
|
||||
|
||||
private:
|
||||
radio_metadata_t **mMetadata;
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
|
||||
#endif // ANDROID_RADIO_METADATA_WRAPPER_H
|
310
android/system/media/radio/include/system/radio_metadata.h
Normal file
310
android/system/media/radio/include/system/radio_metadata.h
Normal file
|
@ -0,0 +1,310 @@
|
|||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef ANDROID_RADIO_METADATA_H
|
||||
#define ANDROID_RADIO_METADATA_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <cutils/compiler.h>
|
||||
#include <system/radio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* maximum length for text metadata including NUL terminator */
|
||||
#define RADIO_METADATA_TEXT_LEN_MAX 1024
|
||||
|
||||
/* radio meta data key values */
|
||||
enum {
|
||||
RADIO_METADATA_KEY_INVALID = -1,
|
||||
RADIO_METADATA_KEY_RDS_PI = 0, /* RDS PI - int */
|
||||
RADIO_METADATA_KEY_RDS_PS = 1, /* RDS PS - text */
|
||||
RADIO_METADATA_KEY_RDS_PTY = 2, /* RDS PTY - int */
|
||||
RADIO_METADATA_KEY_RBDS_PTY = 3, /* RBDS PTY - int */
|
||||
RADIO_METADATA_KEY_RDS_RT = 4, /* RDS RT - text */
|
||||
RADIO_METADATA_KEY_TITLE = 5, /* Song title - text */
|
||||
RADIO_METADATA_KEY_ARTIST = 6, /* Artist name - text */
|
||||
RADIO_METADATA_KEY_ALBUM = 7, /* Album name - text */
|
||||
RADIO_METADATA_KEY_GENRE = 8, /* Musical genre - text */
|
||||
RADIO_METADATA_KEY_ICON = 9, /* Station icon - raw */
|
||||
RADIO_METADATA_KEY_ART = 10, /* Album art - raw */
|
||||
RADIO_METADATA_KEY_CLOCK = 11, /* Clock - radio_metadata_clock_t */
|
||||
RADIO_METADATA_KEY_MIN = RADIO_METADATA_KEY_RDS_PI,
|
||||
RADIO_METADATA_KEY_MAX = RADIO_METADATA_KEY_CLOCK,
|
||||
};
|
||||
typedef int32_t radio_metadata_key_t;
|
||||
|
||||
enum {
|
||||
RADIO_METADATA_TYPE_INVALID = -1,
|
||||
RADIO_METADATA_TYPE_INT = 0, /* signed 32 bit integer */
|
||||
RADIO_METADATA_TYPE_TEXT = 1, /* text in UTF-8 format, NUL terminated.
|
||||
RADIO_METADATA_TEXT_LEN_MAX length including NUL. */
|
||||
RADIO_METADATA_TYPE_RAW = 2, /* raw binary data (icon or art) */
|
||||
RADIO_METADATA_TYPE_CLOCK = 3, /* clock data, see radio_metadata_clock_t */
|
||||
};
|
||||
typedef int32_t radio_metadata_type_t;
|
||||
|
||||
typedef struct radio_metadata_clock {
|
||||
uint64_t utc_seconds_since_epoch; /* Seconds since epoch at GMT + 0. */
|
||||
int32_t timezone_offset_in_minutes; /* Minutes offset from the GMT. */
|
||||
} radio_metadata_clock_t;
|
||||
|
||||
/*
|
||||
* Return the type of the meta data corresponding to the key specified
|
||||
*
|
||||
* arguments:
|
||||
* - key: the meta data key.
|
||||
*
|
||||
* returns:
|
||||
* the meta data type corresponding to the key or RADIO_METADATA_TYPE_INVALID
|
||||
*/
|
||||
ANDROID_API
|
||||
radio_metadata_type_t radio_metadata_type_of_key(const radio_metadata_key_t key);
|
||||
|
||||
/*
|
||||
* Allocate a meta data buffer for use by radio HAL callback for RADIO_EVENT_TUNED and
|
||||
* RADIO_EVENT_METADATA events.
|
||||
*
|
||||
* arguments:
|
||||
* - metadata: the address where the allocate meta data buffer should be returned.
|
||||
* - channel: channel (frequency) this meta data is associated with.
|
||||
* - sub_channel: sub channel this meta data is associated with.
|
||||
*
|
||||
* returns:
|
||||
* 0 if successfully allocated
|
||||
* -ENOMEM if meta data buffer cannot be allocated
|
||||
*/
|
||||
ANDROID_API
|
||||
int radio_metadata_allocate(radio_metadata_t **metadata,
|
||||
const uint32_t channel,
|
||||
const uint32_t sub_channel);
|
||||
|
||||
/*
|
||||
* De-allocate a meta data buffer.
|
||||
*
|
||||
* arguments:
|
||||
* - metadata: the meta data buffer to be de-allocated.
|
||||
*/
|
||||
ANDROID_API
|
||||
void radio_metadata_deallocate(radio_metadata_t *metadata);
|
||||
|
||||
/*
|
||||
* Add an integer meta data to the buffer.
|
||||
*
|
||||
* arguments:
|
||||
* - metadata: the address of the meta data buffer. I/O. the meta data can be modified if the
|
||||
* buffer is re-allocated
|
||||
* - key: the meta data key.
|
||||
* - value: the meta data value.
|
||||
*
|
||||
* returns:
|
||||
* 0 if successfully added
|
||||
* -EINVAL if the buffer passed is invalid or the key does not match an integer type
|
||||
* -ENOMEM if meta data buffer cannot be re-allocated
|
||||
*/
|
||||
ANDROID_API
|
||||
int radio_metadata_add_int(radio_metadata_t **metadata,
|
||||
const radio_metadata_key_t key,
|
||||
const int32_t value);
|
||||
|
||||
/*
|
||||
* Add an text meta data to the buffer.
|
||||
*
|
||||
* arguments:
|
||||
* - metadata: the address of the meta data buffer. I/O. the meta data can be modified if the
|
||||
* buffer is re-allocated
|
||||
* - key: the meta data key.
|
||||
* - value: the meta data value.
|
||||
*
|
||||
* returns:
|
||||
* 0 if successfully added
|
||||
* -EINVAL if the buffer passed is invalid or the key does not match a text type or text
|
||||
* is too long
|
||||
* -ENOMEM if meta data buffer cannot be re-allocated
|
||||
*/
|
||||
ANDROID_API
|
||||
int radio_metadata_add_text(radio_metadata_t **metadata,
|
||||
const radio_metadata_key_t key,
|
||||
const char *value);
|
||||
|
||||
/*
|
||||
* Add an raw meta data to the buffer.
|
||||
*
|
||||
* arguments:
|
||||
* - metadata: the address of the meta data buffer. I/O. the meta data can be modified if the
|
||||
* buffer is re-allocated
|
||||
* - key: the meta data key.
|
||||
* - value: the meta data value.
|
||||
*
|
||||
* returns:
|
||||
* 0 if successfully added
|
||||
* -EINVAL if the buffer passed is invalid or the key does not match a raw type
|
||||
* -ENOMEM if meta data buffer cannot be re-allocated
|
||||
*/
|
||||
ANDROID_API
|
||||
int radio_metadata_add_raw(radio_metadata_t **metadata,
|
||||
const radio_metadata_key_t key,
|
||||
const unsigned char *value,
|
||||
const size_t size);
|
||||
|
||||
/*
|
||||
* Add a clock meta data to the buffer.
|
||||
*
|
||||
* arguments:
|
||||
* - metadata: the address of the meta data buffer. I/O. the meta data can be modified if the
|
||||
* buffer is re-allocated.
|
||||
* - key: the meta data key.
|
||||
* - value: the meta data value.
|
||||
*
|
||||
* returns:
|
||||
* 0 if successfully added
|
||||
* - EINVAL if the buffer passed is invalid or the key does not match a raw type
|
||||
* - ENOMEM if meta data buffer cannot be re-allocated
|
||||
*/
|
||||
ANDROID_API
|
||||
int radio_metadata_add_clock(radio_metadata_t **metadata,
|
||||
const radio_metadata_key_t key,
|
||||
const radio_metadata_clock_t *clock);
|
||||
|
||||
/*
|
||||
* add all meta data in source buffer to destinaiton buffer.
|
||||
*
|
||||
* arguments:
|
||||
* - dst_metadata: the address of the destination meta data buffer. if *dst_metadata is NULL,
|
||||
* a new buffer is created.
|
||||
* - src_metadata: the source meta data buffer.
|
||||
*
|
||||
* returns:
|
||||
* 0 if successfully added
|
||||
* -ENOMEM if meta data buffer cannot be re-allocated
|
||||
*/
|
||||
ANDROID_API
|
||||
int radio_metadata_add_metadata(radio_metadata_t **dst_metadata,
|
||||
radio_metadata_t *src_metadata);
|
||||
|
||||
/*
|
||||
* Perform sanity check on a meta data buffer.
|
||||
*
|
||||
* arguments:
|
||||
* - metadata: the meta data buffer.
|
||||
*
|
||||
* returns:
|
||||
* 0 if no error found
|
||||
* -EINVAL if a consistency problem is found in the meta data buffer
|
||||
*/
|
||||
ANDROID_API
|
||||
int radio_metadata_check(const radio_metadata_t *metadata);
|
||||
|
||||
/*
|
||||
* Return the total size used by the meta data buffer.
|
||||
* No sanity check is performed on the meta data buffer.
|
||||
*
|
||||
* arguments:
|
||||
* - metadata: the meta data buffer.
|
||||
*
|
||||
* returns:
|
||||
* 0 if an invalid meta data buffer is passed
|
||||
* the size in bytes otherwise
|
||||
*/
|
||||
ANDROID_API
|
||||
size_t radio_metadata_get_size(const radio_metadata_t *metadata);
|
||||
|
||||
/*
|
||||
* Return the number of meta data entries in the buffer.
|
||||
* No sanity check is performed on the meta data buffer.
|
||||
*
|
||||
* arguments:
|
||||
* - metadata: the meta data buffer.
|
||||
*
|
||||
* returns:
|
||||
* -EINVAL if an invalid meta data buffer is passed
|
||||
* the number of entries otherwise
|
||||
*/
|
||||
ANDROID_API
|
||||
int radio_metadata_get_count(const radio_metadata_t *metadata);
|
||||
|
||||
/*
|
||||
* Get a meta data at a specified index. Used to parse a meta data buffer.
|
||||
* No sanity check is performed on the meta data buffer.
|
||||
*
|
||||
* arguments:
|
||||
* - metadata: the meta data buffer.
|
||||
* - index: the index to read from
|
||||
* - key: where the meta data key should be returned
|
||||
* - type: where the meta data type should be returned
|
||||
* - value: where the address of the meta data value should be returned
|
||||
* - size: where the size of the meta data value should be returned
|
||||
*
|
||||
* returns:
|
||||
* -EINVAL if an invalid argument is passed
|
||||
* 0 otherwise
|
||||
*/
|
||||
ANDROID_API
|
||||
int radio_metadata_get_at_index(const radio_metadata_t *metadata,
|
||||
const uint32_t index,
|
||||
radio_metadata_key_t *key,
|
||||
radio_metadata_type_t *type,
|
||||
void **value,
|
||||
size_t *size);
|
||||
|
||||
/*
|
||||
* Get a meta data with the specified key.
|
||||
* No sanity check is performed on the meta data buffer.
|
||||
* This will return the first meta data found with the matching key.
|
||||
*
|
||||
* arguments:
|
||||
* - metadata: the meta data buffer.
|
||||
* - index: the index to read from
|
||||
* - key: the meta data key to look for
|
||||
* - type: where the meta data type should be returned
|
||||
* - value: where the address of the meta data value should be returned
|
||||
* - size: where the size of the meta data value should be returned
|
||||
*
|
||||
* returns:
|
||||
* -EINVAL if an invalid argument is passed
|
||||
* -ENOENT if no entry with the specified key is found
|
||||
* 0 otherwise
|
||||
*/
|
||||
ANDROID_API
|
||||
int radio_metadata_get_from_key(const radio_metadata_t *metadata,
|
||||
const radio_metadata_key_t key,
|
||||
radio_metadata_type_t *type,
|
||||
void **value,
|
||||
size_t *size);
|
||||
|
||||
/*
|
||||
* Get channel and sub channel associated with metadata.
|
||||
*
|
||||
* arguments:
|
||||
* - metadata: the meta data buffer
|
||||
* - channel: address where to return the channel.
|
||||
* - sub_channel: address where to return the sub channel.
|
||||
*
|
||||
* returns:
|
||||
* 0 if successfully added
|
||||
* -EINVAL if the buffer passed is invalid
|
||||
*/
|
||||
ANDROID_API
|
||||
int radio_metadata_get_channel(radio_metadata_t *metadata,
|
||||
uint32_t *channel,
|
||||
uint32_t *sub_channel);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // ANDROID_RADIO_METADATA_H
|
26
android/system/media/radio/src/RadioMetadataWrapper.cpp
Normal file
26
android/system/media/radio/src/RadioMetadataWrapper.cpp
Normal file
|
@ -0,0 +1,26 @@
|
|||
#define LOG_TAG "RadioMetadataWrapper"
|
||||
//#define LOG_NDEBUG 0
|
||||
|
||||
#include <system/RadioMetadataWrapper.h>
|
||||
#include <log/log.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
RadioMetadataWrapper::RadioMetadataWrapper(radio_metadata_t **metadata)
|
||||
: mMetadata(metadata)
|
||||
{
|
||||
*mMetadata = nullptr;
|
||||
|
||||
auto status = radio_metadata_allocate(mMetadata, 0, 0);
|
||||
if (status != 0) {
|
||||
// *mMetadata remains NULL if allocation fails
|
||||
ALOGE("Failed to allocate metadata buffer");
|
||||
}
|
||||
}
|
||||
|
||||
RadioMetadataWrapper::~RadioMetadataWrapper()
|
||||
{
|
||||
radio_metadata_deallocate(*mMetadata);
|
||||
}
|
||||
|
||||
} // namespace android
|
444
android/system/media/radio/src/radio_metadata.c
Normal file
444
android/system/media/radio/src/radio_metadata.c
Normal file
|
@ -0,0 +1,444 @@
|
|||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "radio_metadata"
|
||||
/*#define LOG_NDEBUG 0*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <log/log.h>
|
||||
|
||||
#include <system/radio.h>
|
||||
#include <system/radio_metadata.h>
|
||||
#include "radio_metadata_hidden.h"
|
||||
|
||||
const radio_metadata_type_t metadata_key_type_table[] =
|
||||
{
|
||||
RADIO_METADATA_TYPE_INT,
|
||||
RADIO_METADATA_TYPE_TEXT,
|
||||
RADIO_METADATA_TYPE_INT,
|
||||
RADIO_METADATA_TYPE_INT,
|
||||
RADIO_METADATA_TYPE_TEXT,
|
||||
RADIO_METADATA_TYPE_TEXT,
|
||||
RADIO_METADATA_TYPE_TEXT,
|
||||
RADIO_METADATA_TYPE_TEXT,
|
||||
RADIO_METADATA_TYPE_TEXT,
|
||||
RADIO_METADATA_TYPE_RAW,
|
||||
RADIO_METADATA_TYPE_RAW,
|
||||
RADIO_METADATA_TYPE_CLOCK,
|
||||
};
|
||||
|
||||
/**
|
||||
* private functions
|
||||
*/
|
||||
|
||||
bool is_valid_metadata_key(const radio_metadata_key_t key)
|
||||
{
|
||||
if (key < RADIO_METADATA_KEY_MIN || key > RADIO_METADATA_KEY_MAX) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int check_size(radio_metadata_buffer_t **metadata_ptr, const uint32_t size_int)
|
||||
{
|
||||
radio_metadata_buffer_t *metadata = *metadata_ptr;
|
||||
uint32_t index_offset = metadata->size_int - metadata->count - 1;
|
||||
uint32_t data_offset = *((uint32_t *)metadata + index_offset);
|
||||
uint32_t req_size_int;
|
||||
uint32_t new_size_int;
|
||||
|
||||
LOG_ALWAYS_FATAL_IF(metadata->size_int < (metadata->count + 1),
|
||||
"%s: invalid size %u", __func__, metadata->size_int);
|
||||
if (size_int == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
req_size_int = data_offset + metadata->count + 1 + 1 + size_int;
|
||||
/* do not grow buffer if it can accommodate the new entry plus an additional index entry */
|
||||
|
||||
if (req_size_int <= metadata->size_int) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (req_size_int > RADIO_METADATA_MAX_SIZE || metadata->size_int >= RADIO_METADATA_MAX_SIZE) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
/* grow meta data buffer by a factor of 2 until new data fits */
|
||||
new_size_int = metadata->size_int;
|
||||
while (new_size_int < req_size_int)
|
||||
new_size_int *= 2;
|
||||
|
||||
ALOGV("%s growing from %u to %u", __func__, metadata->size_int, new_size_int);
|
||||
metadata = realloc(metadata, new_size_int * sizeof(uint32_t));
|
||||
/* move index table */
|
||||
memmove((uint32_t *)metadata + new_size_int - (metadata->count + 1),
|
||||
(uint32_t *)metadata + metadata->size_int - (metadata->count + 1),
|
||||
(metadata->count + 1) * sizeof(uint32_t));
|
||||
metadata->size_int = new_size_int;
|
||||
|
||||
*metadata_ptr = metadata;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* checks on size and key validity are done before calling this function */
|
||||
int add_metadata(radio_metadata_buffer_t **metadata_ptr,
|
||||
const radio_metadata_key_t key,
|
||||
const radio_metadata_type_t type,
|
||||
const void *value,
|
||||
const size_t size)
|
||||
{
|
||||
uint32_t entry_size_int;
|
||||
int ret;
|
||||
radio_metadata_entry_t *entry;
|
||||
uint32_t index_offset;
|
||||
uint32_t data_offset;
|
||||
radio_metadata_buffer_t *metadata = *metadata_ptr;
|
||||
|
||||
entry_size_int = (uint32_t)(size + sizeof(radio_metadata_entry_t));
|
||||
entry_size_int = (entry_size_int + sizeof(uint32_t) - 1) / sizeof(uint32_t);
|
||||
|
||||
ret = check_size(metadata_ptr, entry_size_int);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
metadata = *metadata_ptr;
|
||||
index_offset = metadata->size_int - metadata->count - 1;
|
||||
data_offset = *((uint32_t *)metadata + index_offset);
|
||||
|
||||
entry = (radio_metadata_entry_t *)((uint32_t *)metadata + data_offset);
|
||||
entry->key = key;
|
||||
entry->type = type;
|
||||
entry->size = (uint32_t)size;
|
||||
memcpy(entry->data, value, size);
|
||||
|
||||
data_offset += entry_size_int;
|
||||
*((uint32_t *)metadata + index_offset -1) = data_offset;
|
||||
metadata->count++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
radio_metadata_entry_t *get_entry_at_index(
|
||||
const radio_metadata_buffer_t *metadata,
|
||||
const unsigned index,
|
||||
bool check)
|
||||
{
|
||||
uint32_t index_offset = metadata->size_int - index - 1;
|
||||
uint32_t data_offset = *((uint32_t *)metadata + index_offset);
|
||||
|
||||
LOG_ALWAYS_FATAL_IF(metadata->size_int < (index + 1),
|
||||
"%s: invalid size %u", __func__, metadata->size_int);
|
||||
if (check) {
|
||||
if (index >= metadata->count) {
|
||||
return NULL;
|
||||
}
|
||||
uint32_t min_offset;
|
||||
uint32_t max_offset;
|
||||
uint32_t min_entry_size_int;
|
||||
min_offset = (sizeof(radio_metadata_buffer_t) + sizeof(uint32_t) - 1) /
|
||||
sizeof(uint32_t);
|
||||
if (data_offset < min_offset) {
|
||||
return NULL;
|
||||
}
|
||||
min_entry_size_int = 1 + sizeof(radio_metadata_entry_t);
|
||||
min_entry_size_int = (min_entry_size_int + sizeof(uint32_t) - 1) / sizeof(uint32_t);
|
||||
|
||||
LOG_ALWAYS_FATAL_IF(metadata->size_int < (metadata->count + 1),
|
||||
"%s: invalid size %u vs count %u", __func__,
|
||||
metadata->size_int, metadata->count);
|
||||
|
||||
max_offset = metadata->size_int - metadata->count - 1 - min_entry_size_int;
|
||||
if (data_offset > max_offset) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return (radio_metadata_entry_t *)((uint32_t *)metadata + data_offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* metadata API functions
|
||||
*/
|
||||
|
||||
radio_metadata_type_t radio_metadata_type_of_key(const radio_metadata_key_t key)
|
||||
{
|
||||
if (!is_valid_metadata_key(key)) {
|
||||
return RADIO_METADATA_TYPE_INVALID;
|
||||
}
|
||||
return metadata_key_type_table[key - RADIO_METADATA_KEY_MIN];
|
||||
}
|
||||
|
||||
int radio_metadata_allocate(radio_metadata_t **metadata,
|
||||
const uint32_t channel,
|
||||
const uint32_t sub_channel)
|
||||
{
|
||||
radio_metadata_buffer_t *metadata_buf =
|
||||
(radio_metadata_buffer_t *)calloc(RADIO_METADATA_DEFAULT_SIZE, sizeof(uint32_t));
|
||||
if (metadata_buf == NULL) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
metadata_buf->channel = channel;
|
||||
metadata_buf->sub_channel = sub_channel;
|
||||
metadata_buf->size_int = RADIO_METADATA_DEFAULT_SIZE;
|
||||
*((uint32_t *)metadata_buf + RADIO_METADATA_DEFAULT_SIZE - 1) =
|
||||
(sizeof(radio_metadata_buffer_t) + sizeof(uint32_t) - 1) /
|
||||
sizeof(uint32_t);
|
||||
*metadata = (radio_metadata_t *)metadata_buf;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void radio_metadata_deallocate(radio_metadata_t *metadata)
|
||||
{
|
||||
free(metadata);
|
||||
}
|
||||
|
||||
int radio_metadata_add_int(radio_metadata_t **metadata,
|
||||
const radio_metadata_key_t key,
|
||||
const int32_t value)
|
||||
{
|
||||
radio_metadata_type_t type = radio_metadata_type_of_key(key);
|
||||
if (metadata == NULL || *metadata == NULL || type != RADIO_METADATA_TYPE_INT) {
|
||||
return -EINVAL;
|
||||
}
|
||||
return add_metadata((radio_metadata_buffer_t **)metadata,
|
||||
key, type, &value, sizeof(int32_t));
|
||||
}
|
||||
|
||||
int radio_metadata_add_text(radio_metadata_t **metadata,
|
||||
const radio_metadata_key_t key,
|
||||
const char *value)
|
||||
{
|
||||
radio_metadata_type_t type = radio_metadata_type_of_key(key);
|
||||
if (metadata == NULL || *metadata == NULL || type != RADIO_METADATA_TYPE_TEXT ||
|
||||
value == NULL || strlen(value) >= RADIO_METADATA_TEXT_LEN_MAX) {
|
||||
return -EINVAL;
|
||||
}
|
||||
return add_metadata((radio_metadata_buffer_t **)metadata, key, type, value, strlen(value) + 1);
|
||||
}
|
||||
|
||||
int radio_metadata_add_raw(radio_metadata_t **metadata,
|
||||
const radio_metadata_key_t key,
|
||||
const unsigned char *value,
|
||||
const size_t size)
|
||||
{
|
||||
radio_metadata_type_t type = radio_metadata_type_of_key(key);
|
||||
if (metadata == NULL || *metadata == NULL || type != RADIO_METADATA_TYPE_RAW || value == NULL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
return add_metadata((radio_metadata_buffer_t **)metadata, key, type, value, size);
|
||||
}
|
||||
|
||||
int radio_metadata_add_clock(radio_metadata_t **metadata,
|
||||
const radio_metadata_key_t key,
|
||||
const radio_metadata_clock_t *clock) {
|
||||
radio_metadata_type_t type = radio_metadata_type_of_key(key);
|
||||
if (metadata == NULL || *metadata == NULL || type != RADIO_METADATA_TYPE_CLOCK ||
|
||||
clock == NULL || clock->timezone_offset_in_minutes < (-12 * 60) ||
|
||||
clock->timezone_offset_in_minutes > (14 * 60)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
return add_metadata(
|
||||
(radio_metadata_buffer_t **)metadata, key, type, clock, sizeof(radio_metadata_clock_t));
|
||||
}
|
||||
|
||||
int radio_metadata_add_metadata(radio_metadata_t **dst_metadata,
|
||||
radio_metadata_t *src_metadata)
|
||||
{
|
||||
radio_metadata_buffer_t *src_metadata_buf = (radio_metadata_buffer_t *)src_metadata;
|
||||
radio_metadata_buffer_t *dst_metadata_buf;
|
||||
int status;
|
||||
uint32_t index;
|
||||
|
||||
if (dst_metadata == NULL || src_metadata == NULL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
if (*dst_metadata == NULL) {
|
||||
status = radio_metadata_allocate(dst_metadata, src_metadata_buf->channel,
|
||||
src_metadata_buf->sub_channel);
|
||||
if (status != 0) {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
dst_metadata_buf = (radio_metadata_buffer_t *)*dst_metadata;
|
||||
dst_metadata_buf->channel = src_metadata_buf->channel;
|
||||
dst_metadata_buf->sub_channel = src_metadata_buf->sub_channel;
|
||||
|
||||
for (index = 0; index < src_metadata_buf->count; index++) {
|
||||
radio_metadata_key_t key;
|
||||
radio_metadata_type_t type;
|
||||
void *value;
|
||||
size_t size;
|
||||
status = radio_metadata_get_at_index(src_metadata, index, &key, &type, &value, &size);
|
||||
if (status != 0)
|
||||
continue;
|
||||
status = add_metadata((radio_metadata_buffer_t **)dst_metadata, key, type, value, size);
|
||||
if (status != 0)
|
||||
break;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
int radio_metadata_check(const radio_metadata_t *metadata)
|
||||
{
|
||||
radio_metadata_buffer_t *metadata_buf =
|
||||
(radio_metadata_buffer_t *)metadata;
|
||||
uint32_t count;
|
||||
uint32_t min_entry_size_int;
|
||||
|
||||
if (metadata_buf == NULL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (metadata_buf->size_int > RADIO_METADATA_MAX_SIZE) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* sanity check on entry count versus buffer size */
|
||||
min_entry_size_int = 1 + sizeof(radio_metadata_entry_t);
|
||||
min_entry_size_int = (min_entry_size_int + sizeof(uint32_t) - 1) /
|
||||
sizeof(uint32_t);
|
||||
if ((metadata_buf->count * min_entry_size_int + metadata_buf->count + 1 +
|
||||
(sizeof(radio_metadata_buffer_t) + sizeof(uint32_t) - 1) / sizeof(uint32_t)) >
|
||||
metadata_buf->size_int) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* sanity check on each entry */
|
||||
for (count = 0; count < metadata_buf->count; count++) {
|
||||
radio_metadata_entry_t *entry = get_entry_at_index(metadata_buf, count, true);
|
||||
radio_metadata_entry_t *next_entry;
|
||||
if (entry == NULL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
if (!is_valid_metadata_key(entry->key)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
if (entry->type != radio_metadata_type_of_key(entry->key)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* do not request check because next entry can be the free slot */
|
||||
next_entry = get_entry_at_index(metadata_buf, count + 1, false);
|
||||
if ((char *)entry->data + entry->size > (char *)next_entry) {
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t radio_metadata_get_size(const radio_metadata_t *metadata)
|
||||
{
|
||||
radio_metadata_buffer_t *metadata_buf =
|
||||
(radio_metadata_buffer_t *)metadata;
|
||||
|
||||
if (metadata_buf == NULL) {
|
||||
return 0;
|
||||
}
|
||||
return metadata_buf->size_int * sizeof(uint32_t);
|
||||
}
|
||||
|
||||
int radio_metadata_get_count(const radio_metadata_t *metadata)
|
||||
{
|
||||
radio_metadata_buffer_t *metadata_buf =
|
||||
(radio_metadata_buffer_t *)metadata;
|
||||
|
||||
if (metadata_buf == NULL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
return (int)metadata_buf->count;
|
||||
}
|
||||
|
||||
int radio_metadata_get_at_index(const radio_metadata_t *metadata,
|
||||
const uint32_t index,
|
||||
radio_metadata_key_t *key,
|
||||
radio_metadata_type_t *type,
|
||||
void **value,
|
||||
size_t *size)
|
||||
{
|
||||
radio_metadata_entry_t *entry;
|
||||
radio_metadata_buffer_t *metadata_buf =
|
||||
(radio_metadata_buffer_t *)metadata;
|
||||
|
||||
if (metadata_buf == NULL || key == NULL || type == NULL ||
|
||||
value == NULL || size == NULL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
if (index >= metadata_buf->count) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
entry = get_entry_at_index(metadata_buf, index, false);
|
||||
*key = entry->key;
|
||||
*type = entry->type;
|
||||
*value = (void *)entry->data;
|
||||
*size = (size_t)entry->size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int radio_metadata_get_from_key(const radio_metadata_t *metadata,
|
||||
const radio_metadata_key_t key,
|
||||
radio_metadata_type_t *type,
|
||||
void **value,
|
||||
size_t *size)
|
||||
{
|
||||
uint32_t count;
|
||||
radio_metadata_entry_t *entry = NULL;
|
||||
radio_metadata_buffer_t *metadata_buf =
|
||||
(radio_metadata_buffer_t *)metadata;
|
||||
|
||||
if (metadata_buf == NULL || type == NULL || value == NULL || size == NULL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
if (!is_valid_metadata_key(key)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (count = 0; count < metadata_buf->count; entry = NULL, count++) {
|
||||
entry = get_entry_at_index(metadata_buf, count, false);
|
||||
if (entry->key == key) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (entry == NULL) {
|
||||
return -ENOENT;
|
||||
}
|
||||
*type = entry->type;
|
||||
*value = (void *)entry->data;
|
||||
*size = (size_t)entry->size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int radio_metadata_get_channel(radio_metadata_t *metadata,
|
||||
uint32_t *channel,
|
||||
uint32_t *sub_channel)
|
||||
{
|
||||
radio_metadata_buffer_t *metadata_buf =
|
||||
(radio_metadata_buffer_t *)metadata;
|
||||
|
||||
if (metadata_buf == NULL || channel == NULL || sub_channel == NULL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
*channel = metadata_buf->channel;
|
||||
*sub_channel = metadata_buf->sub_channel;
|
||||
return 0;
|
||||
}
|
86
android/system/media/radio/src/radio_metadata_hidden.h
Normal file
86
android/system/media/radio/src/radio_metadata_hidden.h
Normal file
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef ANDROID_RADIO_METADATA_HIDDEN_H
|
||||
#define ANDROID_RADIO_METADATA_HIDDEN_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <system/radio.h>
|
||||
#include <system/radio_metadata.h>
|
||||
|
||||
/* default size allocated for a metadata buffer in 32 bits units */
|
||||
#define RADIO_METADATA_DEFAULT_SIZE 64
|
||||
/* maximum size allocated for a metadata buffer in 32 bits units */
|
||||
#define RADIO_METADATA_MAX_SIZE (RADIO_METADATA_DEFAULT_SIZE << 12)
|
||||
|
||||
/* meta data entry in a meta data buffer */
|
||||
typedef struct radio_metadata_entry {
|
||||
radio_metadata_key_t key;
|
||||
radio_metadata_type_t type;
|
||||
uint32_t size;
|
||||
uint8_t data[];
|
||||
} radio_metadata_entry_t;
|
||||
|
||||
|
||||
/**
|
||||
* meta data buffer layout:
|
||||
*
|
||||
* | <--- 32 bit ---> |
|
||||
* |---------------------------|
|
||||
* | channel |
|
||||
* |---------------------------|
|
||||
* | sub_channel |
|
||||
* |---------------------------|
|
||||
* | size_int | total size in 32 bit units including header and index
|
||||
* |---------------------------|
|
||||
* | count | number of entries
|
||||
* |---------------------------|<--+
|
||||
* | first entry | |
|
||||
* | | |
|
||||
* |---------------------------|<+ |
|
||||
* | second entry | | |
|
||||
* | | | |
|
||||
* | | | |
|
||||
* |---------------------------| | |
|
||||
* | : | | |
|
||||
* |---------------------------| | | \
|
||||
* | offset of next free space | | | |
|
||||
* |---------------------------| | | |
|
||||
* | : | | | |
|
||||
* |---------------------------| | | > index
|
||||
* | offset of second entry |-+ | |
|
||||
* |---------------------------| | |
|
||||
* | offset of first entry |---+ |
|
||||
* |---------------------------| /
|
||||
*
|
||||
* A radio meta data buffer is allocated with radio_metadata_allocate() and released with
|
||||
* radio_metadata_deallocate().
|
||||
* Meta data entries are added with radio_metadata_add_xxx() where xxx is int, text or raw.
|
||||
* The buffer is allocated with a default size (RADIO_METADATA_DEFAULT_SIZE entries)
|
||||
* by radio_metadata_allocate() and reallocated if needed by radio_metadata_add_xxx()
|
||||
*/
|
||||
|
||||
/* Radio meta data buffer header */
|
||||
typedef struct radio_metadata_buffer {
|
||||
uint32_t channel; /* channel (frequency) this meta data is associated with */
|
||||
uint32_t sub_channel; /* sub channel this meta data is associated with */
|
||||
uint32_t size_int; /* Total size in 32 bit word units */
|
||||
uint32_t count; /* number of meta data entries */
|
||||
} radio_metadata_buffer_t;
|
||||
|
||||
|
||||
|
||||
#endif // ANDROID_RADIO_METADATA_HIDDEN_H
|
Loading…
Add table
Add a link
Reference in a new issue