diff options
-rw-r--r-- | fastboot/fastboot.cpp | 45 | ||||
-rw-r--r-- | fs_mgr/fs_mgr_fstab.c | 6 | ||||
-rw-r--r-- | fs_mgr/fs_mgr_priv.h | 1 | ||||
-rw-r--r-- | fs_mgr/include/fs_mgr.h | 1 | ||||
-rw-r--r-- | healthd/healthd.cpp | 1 | ||||
-rw-r--r-- | healthd/healthd.h | 1 | ||||
-rw-r--r-- | healthd/healthd_mode_charger.cpp | 23 | ||||
-rw-r--r-- | include/netutils/dhcp.h | 32 | ||||
-rw-r--r-- | include/system/audio.h | 1373 | ||||
-rw-r--r-- | include/system/audio_policy.h | 103 | ||||
-rw-r--r-- | include/system/camera.h | 7 | ||||
-rw-r--r-- | include/system/graphics.h | 58 | ||||
-rw-r--r-- | include/system/radio.h | 247 | ||||
-rw-r--r-- | include/system/sound_trigger.h | 223 | ||||
-rw-r--r-- | include/sysutils/NetlinkEvent.h | 32 | ||||
-rw-r--r-- | include/utils/Looper.h | 26 | ||||
-rw-r--r-- | libion/ion.c | 14 | ||||
-rw-r--r-- | libnetutils/dhcp_utils.c | 112 | ||||
-rw-r--r-- | libsysutils/src/NetlinkEvent.cpp | 38 | ||||
-rw-r--r-- | libsysutils/src/SocketListener.cpp | 2 | ||||
-rw-r--r-- | libutils/Looper.cpp | 229 | ||||
-rw-r--r-- | logwrapper/logwrap.c | 2 | ||||
-rw-r--r-- | rootdir/init.environ.rc.in | 2 | ||||
-rw-r--r-- | rootdir/init.rc | 57 | ||||
-rw-r--r-- | sdcard/sdcard.c | 66 |
25 files changed, 702 insertions, 1999 deletions
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp index e139bcd..e35cc70 100644 --- a/fastboot/fastboot.cpp +++ b/fastboot/fastboot.cpp @@ -285,9 +285,8 @@ void usage(void) " Can override the fs type and/or\n" " size the bootloader reports.\n" " getvar <variable> display a bootloader variable\n" - " boot <kernel> [ <ramdisk> [ <second> ] ] download and boot kernel\n" - " flash:raw boot <kernel> [ <ramdisk> [ <second> ] ] create bootimage and \n" - " flash it\n" + " boot <kernel> [ <ramdisk> ] download and boot kernel\n" + " flash:raw boot <kernel> [ <ramdisk> ] create bootimage and flash it\n" " devices list all connected devices\n" " continue continue with autoboot\n" " reboot [bootloader] reboot device, optionally into bootloader\n" @@ -315,11 +314,10 @@ void usage(void) } void *load_bootable_image(const char *kernel, const char *ramdisk, - const char *secondstage, unsigned *sz, - const char *cmdline) + unsigned *sz, const char *cmdline) { - void *kdata = 0, *rdata = 0, *sdata = 0; - unsigned ksize = 0, rsize = 0, ssize = 0; + void *kdata = 0, *rdata = 0; + unsigned ksize = 0, rsize = 0; void *bdata; unsigned bsize; @@ -355,18 +353,10 @@ void *load_bootable_image(const char *kernel, const char *ramdisk, } } - if (secondstage) { - sdata = load_file(secondstage, &ssize); - if(sdata == 0) { - fprintf(stderr,"cannot load '%s': %s\n", secondstage, strerror(errno)); - return 0; - } - } - fprintf(stderr,"creating boot image...\n"); bdata = mkbootimg(kdata, ksize, kernel_offset, rdata, rsize, ramdisk_offset, - sdata, ssize, second_offset, + 0, 0, second_offset, page_size, base_addr, tags_offset, &bsize); if(bdata == 0) { fprintf(stderr,"failed to create boot.img\n"); @@ -1134,7 +1124,6 @@ int main(int argc, char **argv) } else if(!strcmp(*argv, "boot")) { char *kname = 0; char *rname = 0; - char *sname = 0; skip(1); if (argc > 0) { kname = argv[0]; @@ -1144,11 +1133,7 @@ int main(int argc, char **argv) rname = argv[0]; skip(1); } - if (argc > 0) { - sname = argv[0]; - skip(1); - } - data = load_bootable_image(kname, rname, sname, &sz, cmdline); + data = load_bootable_image(kname, rname, &sz, cmdline); if (data == 0) return 1; fb_queue_download("boot.img", data, sz); fb_queue_command("boot", "booting"); @@ -1172,18 +1157,14 @@ int main(int argc, char **argv) char *pname = argv[1]; char *kname = argv[2]; char *rname = 0; - char *sname = 0; require(3); - skip(3); - if (argc > 0) { - rname = argv[0]; - skip(1); - } - if (argc > 0) { - sname = argv[0]; - skip(1); + if(argc > 3) { + rname = argv[3]; + skip(4); + } else { + skip(3); } - data = load_bootable_image(kname, rname, sname, &sz, cmdline); + data = load_bootable_image(kname, rname, &sz, cmdline); if (data == 0) die("cannot load bootable image"); fb_queue_flash(pname, data, sz); } else if(!strcmp(*argv, "flashall")) { diff --git a/fs_mgr/fs_mgr_fstab.c b/fs_mgr/fs_mgr_fstab.c index 8b0f714..4451b82 100644 --- a/fs_mgr/fs_mgr_fstab.c +++ b/fs_mgr/fs_mgr_fstab.c @@ -70,6 +70,7 @@ static struct flag_list fs_mgr_flags[] = { { "zramsize=", MF_ZRAMSIZE }, { "verify", MF_VERIFY }, { "noemulatedsd", MF_NOEMULATEDSD }, + { "notrim", MF_NOTRIM }, { "defaults", 0 }, { 0, 0 }, }; @@ -448,3 +449,8 @@ int fs_mgr_is_noemulatedsd(const struct fstab_rec *fstab) { return fstab->fs_mgr_flags & MF_NOEMULATEDSD; } + +int fs_mgr_is_notrim(struct fstab_rec *fstab) +{ + return fstab->fs_mgr_flags & MF_NOTRIM; +} diff --git a/fs_mgr/fs_mgr_priv.h b/fs_mgr/fs_mgr_priv.h index d56111a..ee944c1 100644 --- a/fs_mgr/fs_mgr_priv.h +++ b/fs_mgr/fs_mgr_priv.h @@ -76,6 +76,7 @@ #define MF_FORCECRYPT 0x400 #define MF_NOEMULATEDSD 0x800 /* no emulated sdcard daemon, sd card is the only external storage */ +#define MF_NOTRIM 0x1000 #define MF_FILEENCRYPTION 0x2000 #define DM_BUF_SIZE 4096 diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h index c58a888..a1fdf55 100644 --- a/fs_mgr/include/fs_mgr.h +++ b/fs_mgr/include/fs_mgr.h @@ -103,6 +103,7 @@ int fs_mgr_is_verified(const struct fstab_rec *fstab); int fs_mgr_is_encryptable(const struct fstab_rec *fstab); int fs_mgr_is_file_encrypted(const struct fstab_rec *fstab); int fs_mgr_is_noemulatedsd(const struct fstab_rec *fstab); +int fs_mgr_is_notrim(struct fstab_rec *fstab); int fs_mgr_swapon_all(struct fstab *fstab); #ifdef __cplusplus } diff --git a/healthd/healthd.cpp b/healthd/healthd.cpp index 1fee855..b0002cc 100644 --- a/healthd/healthd.cpp +++ b/healthd/healthd.cpp @@ -53,6 +53,7 @@ static struct healthd_config healthd_config = { .batteryCurrentAvgPath = String8(String8::kEmptyString), .batteryChargeCounterPath = String8(String8::kEmptyString), .energyCounter = NULL, + .boot_min_cap = 0, .screen_on = NULL, }; diff --git a/healthd/healthd.h b/healthd/healthd.h index 4704f0b..84b6d76 100644 --- a/healthd/healthd.h +++ b/healthd/healthd.h @@ -67,6 +67,7 @@ struct healthd_config { android::String8 batteryChargeCounterPath; int (*energyCounter)(int64_t *); + int boot_min_cap; bool (*screen_on)(android::BatteryProperties *props); }; diff --git a/healthd/healthd_mode_charger.cpp b/healthd/healthd_mode_charger.cpp index 9ed5944..352510b 100644 --- a/healthd/healthd_mode_charger.cpp +++ b/healthd/healthd_mode_charger.cpp @@ -116,6 +116,7 @@ struct charger { struct animation *batt_anim; gr_surface surf_unknown; + int boot_min_cap; }; static struct frame batt_anim_frames[] = { @@ -520,19 +521,29 @@ static void process_key(struct charger *charger, int code, int64_t now) LOGW("[%" PRId64 "] booting from charger mode\n", now); property_set("sys.boot_from_charger_mode", "1"); } else { - LOGW("[%" PRId64 "] rebooting\n", now); - android_reboot(ANDROID_RB_RESTART, 0, 0); + if (charger->batt_anim->capacity >= charger->boot_min_cap) { + LOGW("[%" PRId64 "] rebooting\n", now); + android_reboot(ANDROID_RB_RESTART, 0, 0); + } else { + LOGV("[%" PRId64 "] ignore power-button press, battery level " + "less than minimum\n", now); + } } } else { /* if the key is pressed but timeout hasn't expired, * make sure we wake up at the right-ish time to check */ set_next_key_check(charger, key, POWER_ON_KEY_TIME); + + /* Turn on the display and kick animation on power-key press + * rather than on key release + */ + kick_animation(charger->batt_anim); + request_suspend(false); } } else { /* if the power key got released, force screen state cycle */ if (key->pending) { - request_suspend(false); kick_animation(charger->batt_anim); } } @@ -555,6 +566,11 @@ static void handle_power_supply_state(struct charger *charger, int64_t now) return; if (!charger->charger_connected) { + + /* Last cycle would have stopped at the extreme top of battery-icon + * Need to show the correct level corresponding to capacity. + */ + kick_animation(charger->batt_anim); request_suspend(false); if (charger->next_pwr_check == -1) { charger->next_pwr_check = now + UNPLUGGED_SHUTDOWN_TIME; @@ -705,4 +721,5 @@ void healthd_mode_charger_init(struct healthd_config* config) charger->next_key_check = -1; charger->next_pwr_check = -1; healthd_config = config; + charger->boot_min_cap = config->boot_min_cap; } diff --git a/include/netutils/dhcp.h b/include/netutils/dhcp.h index de6bc82..008dbd8 100644 --- a/include/netutils/dhcp.h +++ b/include/netutils/dhcp.h @@ -23,26 +23,18 @@ __BEGIN_DECLS extern int do_dhcp(char *iname); -extern int dhcp_do_request(const char *ifname, - char *ipaddr, - char *gateway, - uint32_t *prefixLength, - char *dns[], - char *server, - uint32_t *lease, - char *vendorInfo, - char *domain, - char *mtu); -extern int dhcp_do_request_renew(const char *ifname, - char *ipaddr, - char *gateway, - uint32_t *prefixLength, - char *dns[], - char *server, - uint32_t *lease, - char *vendorInfo, - char *domain, - char *mtu); +extern int dhcp_start(const char *ifname); +extern int dhcp_start_renew(const char *ifname); +extern int dhcp_get_results(const char *ifname, + char *ipaddr, + char *gateway, + uint32_t *prefixLength, + char *dns[], + char *server, + uint32_t *lease, + char *vendorInfo, + char *domain, + char *mtu); extern int dhcp_stop(const char *ifname); extern int dhcp_release_lease(const char *ifname); extern char *dhcp_get_errmsg(); diff --git a/include/system/audio.h b/include/system/audio.h deleted file mode 100644 index 181a171..0000000 --- a/include/system/audio.h +++ /dev/null @@ -1,1373 +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. - */ - - -#ifndef ANDROID_AUDIO_CORE_H -#define ANDROID_AUDIO_CORE_H - -#include <stdbool.h> -#include <stdint.h> -#include <stdio.h> -#include <sys/cdefs.h> -#include <sys/types.h> - -#include <cutils/bitops.h> - -__BEGIN_DECLS - -/* The enums were moved here mostly from - * frameworks/base/include/media/AudioSystem.h - */ - -/* device address used to refer to the standard remote submix */ -#define AUDIO_REMOTE_SUBMIX_DEVICE_ADDRESS "0" - -/* AudioFlinger and AudioPolicy services use I/O handles to identify audio sources and sinks */ -typedef int audio_io_handle_t; -#define AUDIO_IO_HANDLE_NONE 0 - -/* Audio stream types */ -typedef enum { - /* These values must kept in sync with - * frameworks/base/media/java/android/media/AudioSystem.java - */ - AUDIO_STREAM_DEFAULT = -1, - AUDIO_STREAM_MIN = 0, - AUDIO_STREAM_VOICE_CALL = 0, - AUDIO_STREAM_SYSTEM = 1, - AUDIO_STREAM_RING = 2, - AUDIO_STREAM_MUSIC = 3, - AUDIO_STREAM_ALARM = 4, - AUDIO_STREAM_NOTIFICATION = 5, - AUDIO_STREAM_BLUETOOTH_SCO = 6, - AUDIO_STREAM_ENFORCED_AUDIBLE = 7, /* Sounds that cannot be muted by user - * and must be routed to speaker - */ - AUDIO_STREAM_DTMF = 8, - AUDIO_STREAM_TTS = 9, /* Transmitted Through Speaker. - * Plays over speaker only, silent on other devices. - */ - AUDIO_STREAM_ACCESSIBILITY = 10, /* For accessibility talk back prompts */ - AUDIO_STREAM_REROUTING = 11, /* For dynamic policy output mixes */ - AUDIO_STREAM_PATCH = 12, /* For internal audio flinger tracks. Fixed volume */ - AUDIO_STREAM_PUBLIC_CNT = AUDIO_STREAM_TTS + 1, - AUDIO_STREAM_CNT = AUDIO_STREAM_PATCH + 1, -} audio_stream_type_t; - -/* Do not change these values without updating their counterparts - * in frameworks/base/media/java/android/media/AudioAttributes.java - */ -typedef enum { - AUDIO_CONTENT_TYPE_UNKNOWN = 0, - AUDIO_CONTENT_TYPE_SPEECH = 1, - AUDIO_CONTENT_TYPE_MUSIC = 2, - AUDIO_CONTENT_TYPE_MOVIE = 3, - AUDIO_CONTENT_TYPE_SONIFICATION = 4, - - AUDIO_CONTENT_TYPE_CNT, - AUDIO_CONTENT_TYPE_MAX = AUDIO_CONTENT_TYPE_CNT - 1, -} audio_content_type_t; - -/* Do not change these values without updating their counterparts - * in frameworks/base/media/java/android/media/AudioAttributes.java - */ -typedef enum { - AUDIO_USAGE_UNKNOWN = 0, - AUDIO_USAGE_MEDIA = 1, - AUDIO_USAGE_VOICE_COMMUNICATION = 2, - AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING = 3, - AUDIO_USAGE_ALARM = 4, - AUDIO_USAGE_NOTIFICATION = 5, - AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE = 6, - AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST = 7, - AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT = 8, - AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED = 9, - AUDIO_USAGE_NOTIFICATION_EVENT = 10, - AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY = 11, - AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE = 12, - AUDIO_USAGE_ASSISTANCE_SONIFICATION = 13, - AUDIO_USAGE_GAME = 14, - AUDIO_USAGE_VIRTUAL_SOURCE = 15, - - AUDIO_USAGE_CNT, - AUDIO_USAGE_MAX = AUDIO_USAGE_CNT - 1, -} audio_usage_t; - -typedef uint32_t audio_flags_mask_t; - -/* Do not change these values without updating their counterparts - * in frameworks/base/media/java/android/media/AudioAttributes.java - */ -enum { - AUDIO_FLAG_AUDIBILITY_ENFORCED = 0x1, - AUDIO_FLAG_SECURE = 0x2, - AUDIO_FLAG_SCO = 0x4, - AUDIO_FLAG_BEACON = 0x8, - AUDIO_FLAG_HW_AV_SYNC = 0x10, - AUDIO_FLAG_HW_HOTWORD = 0x20, -}; - -/* Do not change these values without updating their counterparts - * in frameworks/base/media/java/android/media/MediaRecorder.java, - * frameworks/av/services/audiopolicy/AudioPolicyService.cpp, - * and system/media/audio_effects/include/audio_effects/audio_effects_conf.h! - */ -typedef enum { - AUDIO_SOURCE_DEFAULT = 0, - AUDIO_SOURCE_MIC = 1, - AUDIO_SOURCE_VOICE_UPLINK = 2, - AUDIO_SOURCE_VOICE_DOWNLINK = 3, - AUDIO_SOURCE_VOICE_CALL = 4, - AUDIO_SOURCE_CAMCORDER = 5, - AUDIO_SOURCE_VOICE_RECOGNITION = 6, - AUDIO_SOURCE_VOICE_COMMUNICATION = 7, - AUDIO_SOURCE_REMOTE_SUBMIX = 8, /* Source for the mix to be presented remotely. */ - /* An example of remote presentation is Wifi Display */ - /* where a dongle attached to a TV can be used to */ - /* play the mix captured by this audio source. */ - AUDIO_SOURCE_CNT, - AUDIO_SOURCE_MAX = AUDIO_SOURCE_CNT - 1, - AUDIO_SOURCE_FM_TUNER = 1998, - AUDIO_SOURCE_HOTWORD = 1999, /* A low-priority, preemptible audio source for - for background software hotword detection. - Same tuning as AUDIO_SOURCE_VOICE_RECOGNITION. - Used only internally to the framework. Not exposed - at the audio HAL. */ -} audio_source_t; - -/* Audio attributes */ -#define AUDIO_ATTRIBUTES_TAGS_MAX_SIZE 256 -typedef struct { - audio_content_type_t content_type; - audio_usage_t usage; - audio_source_t source; - audio_flags_mask_t flags; - char tags[AUDIO_ATTRIBUTES_TAGS_MAX_SIZE]; /* UTF8 */ -} audio_attributes_t; - -/* special audio session values - * (XXX: should this be living in the audio effects land?) - */ -typedef enum { - /* session for effects attached to a particular output stream - * (value must be less than 0) - */ - AUDIO_SESSION_OUTPUT_STAGE = -1, - - /* session for effects applied to output mix. These effects can - * be moved by audio policy manager to another output stream - * (value must be 0) - */ - AUDIO_SESSION_OUTPUT_MIX = 0, - - /* application does not specify an explicit session ID to be used, - * and requests a new session ID to be allocated - * TODO use unique values for AUDIO_SESSION_OUTPUT_MIX and AUDIO_SESSION_ALLOCATE, - * after all uses have been updated from 0 to the appropriate symbol, and have been tested. - */ - AUDIO_SESSION_ALLOCATE = 0, -} audio_session_t; - -/* a unique ID allocated by AudioFlinger for use as a audio_io_handle_t or audio_session_t */ -typedef int audio_unique_id_t; - -#define AUDIO_UNIQUE_ID_ALLOCATE AUDIO_SESSION_ALLOCATE - -/* Audio sub formats (see enum audio_format). */ - -/* PCM sub formats */ -typedef enum { - /* All of these are in native byte order */ - AUDIO_FORMAT_PCM_SUB_16_BIT = 0x1, /* DO NOT CHANGE - PCM signed 16 bits */ - AUDIO_FORMAT_PCM_SUB_8_BIT = 0x2, /* DO NOT CHANGE - PCM unsigned 8 bits */ - AUDIO_FORMAT_PCM_SUB_32_BIT = 0x3, /* PCM signed .31 fixed point */ - AUDIO_FORMAT_PCM_SUB_8_24_BIT = 0x4, /* PCM signed 7.24 fixed point */ - AUDIO_FORMAT_PCM_SUB_FLOAT = 0x5, /* PCM single-precision floating point */ - AUDIO_FORMAT_PCM_SUB_24_BIT_PACKED = 0x6, /* PCM signed .23 fixed point packed in 3 bytes */ -} audio_format_pcm_sub_fmt_t; - -/* The audio_format_*_sub_fmt_t declarations are not currently used */ - -/* MP3 sub format field definition : can use 11 LSBs in the same way as MP3 - * frame header to specify bit rate, stereo mode, version... - */ -typedef enum { - AUDIO_FORMAT_MP3_SUB_NONE = 0x0, -} audio_format_mp3_sub_fmt_t; - -/* AMR NB/WB sub format field definition: specify frame block interleaving, - * bandwidth efficient or octet aligned, encoding mode for recording... - */ -typedef enum { - AUDIO_FORMAT_AMR_SUB_NONE = 0x0, -} audio_format_amr_sub_fmt_t; - -/* AAC sub format field definition: specify profile or bitrate for recording... */ -typedef enum { - AUDIO_FORMAT_AAC_SUB_MAIN = 0x1, - AUDIO_FORMAT_AAC_SUB_LC = 0x2, - AUDIO_FORMAT_AAC_SUB_SSR = 0x4, - AUDIO_FORMAT_AAC_SUB_LTP = 0x8, - AUDIO_FORMAT_AAC_SUB_HE_V1 = 0x10, - AUDIO_FORMAT_AAC_SUB_SCALABLE = 0x20, - AUDIO_FORMAT_AAC_SUB_ERLC = 0x40, - AUDIO_FORMAT_AAC_SUB_LD = 0x80, - AUDIO_FORMAT_AAC_SUB_HE_V2 = 0x100, - AUDIO_FORMAT_AAC_SUB_ELD = 0x200, -} audio_format_aac_sub_fmt_t; - -/* VORBIS sub format field definition: specify quality for recording... */ -typedef enum { - AUDIO_FORMAT_VORBIS_SUB_NONE = 0x0, -} audio_format_vorbis_sub_fmt_t; - -/* Audio format consists of a main format field (upper 8 bits) and a sub format - * field (lower 24 bits). - * - * The main format indicates the main codec type. The sub format field - * indicates options and parameters for each format. The sub format is mainly - * used for record to indicate for instance the requested bitrate or profile. - * It can also be used for certain formats to give informations not present in - * the encoded audio stream (e.g. octet alignement for AMR). - */ -typedef enum { - AUDIO_FORMAT_INVALID = 0xFFFFFFFFUL, - AUDIO_FORMAT_DEFAULT = 0, - AUDIO_FORMAT_PCM = 0x00000000UL, /* DO NOT CHANGE */ - AUDIO_FORMAT_MP3 = 0x01000000UL, - AUDIO_FORMAT_AMR_NB = 0x02000000UL, - AUDIO_FORMAT_AMR_WB = 0x03000000UL, - AUDIO_FORMAT_AAC = 0x04000000UL, - AUDIO_FORMAT_HE_AAC_V1 = 0x05000000UL, /* Deprecated, Use AUDIO_FORMAT_AAC_HE_V1*/ - AUDIO_FORMAT_HE_AAC_V2 = 0x06000000UL, /* Deprecated, Use AUDIO_FORMAT_AAC_HE_V2*/ - AUDIO_FORMAT_VORBIS = 0x07000000UL, - AUDIO_FORMAT_OPUS = 0x08000000UL, - AUDIO_FORMAT_AC3 = 0x09000000UL, - AUDIO_FORMAT_E_AC3 = 0x0A000000UL, - AUDIO_FORMAT_MAIN_MASK = 0xFF000000UL, - AUDIO_FORMAT_SUB_MASK = 0x00FFFFFFUL, - - /* Aliases */ - /* note != AudioFormat.ENCODING_PCM_16BIT */ - AUDIO_FORMAT_PCM_16_BIT = (AUDIO_FORMAT_PCM | - AUDIO_FORMAT_PCM_SUB_16_BIT), - /* note != AudioFormat.ENCODING_PCM_8BIT */ - AUDIO_FORMAT_PCM_8_BIT = (AUDIO_FORMAT_PCM | - AUDIO_FORMAT_PCM_SUB_8_BIT), - AUDIO_FORMAT_PCM_32_BIT = (AUDIO_FORMAT_PCM | - AUDIO_FORMAT_PCM_SUB_32_BIT), - AUDIO_FORMAT_PCM_8_24_BIT = (AUDIO_FORMAT_PCM | - AUDIO_FORMAT_PCM_SUB_8_24_BIT), - AUDIO_FORMAT_PCM_FLOAT = (AUDIO_FORMAT_PCM | - AUDIO_FORMAT_PCM_SUB_FLOAT), - AUDIO_FORMAT_PCM_24_BIT_PACKED = (AUDIO_FORMAT_PCM | - AUDIO_FORMAT_PCM_SUB_24_BIT_PACKED), - AUDIO_FORMAT_AAC_MAIN = (AUDIO_FORMAT_AAC | - AUDIO_FORMAT_AAC_SUB_MAIN), - AUDIO_FORMAT_AAC_LC = (AUDIO_FORMAT_AAC | - AUDIO_FORMAT_AAC_SUB_LC), - AUDIO_FORMAT_AAC_SSR = (AUDIO_FORMAT_AAC | - AUDIO_FORMAT_AAC_SUB_SSR), - AUDIO_FORMAT_AAC_LTP = (AUDIO_FORMAT_AAC | - AUDIO_FORMAT_AAC_SUB_LTP), - AUDIO_FORMAT_AAC_HE_V1 = (AUDIO_FORMAT_AAC | - AUDIO_FORMAT_AAC_SUB_HE_V1), - AUDIO_FORMAT_AAC_SCALABLE = (AUDIO_FORMAT_AAC | - AUDIO_FORMAT_AAC_SUB_SCALABLE), - AUDIO_FORMAT_AAC_ERLC = (AUDIO_FORMAT_AAC | - AUDIO_FORMAT_AAC_SUB_ERLC), - AUDIO_FORMAT_AAC_LD = (AUDIO_FORMAT_AAC | - AUDIO_FORMAT_AAC_SUB_LD), - AUDIO_FORMAT_AAC_HE_V2 = (AUDIO_FORMAT_AAC | - AUDIO_FORMAT_AAC_SUB_HE_V2), - AUDIO_FORMAT_AAC_ELD = (AUDIO_FORMAT_AAC | - AUDIO_FORMAT_AAC_SUB_ELD), -} audio_format_t; - -/* For the channel mask for position assignment representation */ -enum { - -/* These can be a complete audio_channel_mask_t. */ - - AUDIO_CHANNEL_NONE = 0x0, - AUDIO_CHANNEL_INVALID = 0xC0000000, - -/* These can be the bits portion of an audio_channel_mask_t - * with representation AUDIO_CHANNEL_REPRESENTATION_POSITION. - * Using these bits as a complete audio_channel_mask_t is deprecated. - */ - - /* output channels */ - AUDIO_CHANNEL_OUT_FRONT_LEFT = 0x1, - AUDIO_CHANNEL_OUT_FRONT_RIGHT = 0x2, - AUDIO_CHANNEL_OUT_FRONT_CENTER = 0x4, - AUDIO_CHANNEL_OUT_LOW_FREQUENCY = 0x8, - AUDIO_CHANNEL_OUT_BACK_LEFT = 0x10, - AUDIO_CHANNEL_OUT_BACK_RIGHT = 0x20, - AUDIO_CHANNEL_OUT_FRONT_LEFT_OF_CENTER = 0x40, - AUDIO_CHANNEL_OUT_FRONT_RIGHT_OF_CENTER = 0x80, - AUDIO_CHANNEL_OUT_BACK_CENTER = 0x100, - AUDIO_CHANNEL_OUT_SIDE_LEFT = 0x200, - AUDIO_CHANNEL_OUT_SIDE_RIGHT = 0x400, - AUDIO_CHANNEL_OUT_TOP_CENTER = 0x800, - AUDIO_CHANNEL_OUT_TOP_FRONT_LEFT = 0x1000, - AUDIO_CHANNEL_OUT_TOP_FRONT_CENTER = 0x2000, - AUDIO_CHANNEL_OUT_TOP_FRONT_RIGHT = 0x4000, - AUDIO_CHANNEL_OUT_TOP_BACK_LEFT = 0x8000, - AUDIO_CHANNEL_OUT_TOP_BACK_CENTER = 0x10000, - AUDIO_CHANNEL_OUT_TOP_BACK_RIGHT = 0x20000, - -/* TODO: should these be considered complete channel masks, or only bits? */ - - AUDIO_CHANNEL_OUT_MONO = AUDIO_CHANNEL_OUT_FRONT_LEFT, - AUDIO_CHANNEL_OUT_STEREO = (AUDIO_CHANNEL_OUT_FRONT_LEFT | - AUDIO_CHANNEL_OUT_FRONT_RIGHT), - AUDIO_CHANNEL_OUT_QUAD = (AUDIO_CHANNEL_OUT_FRONT_LEFT | - AUDIO_CHANNEL_OUT_FRONT_RIGHT | - AUDIO_CHANNEL_OUT_BACK_LEFT | - AUDIO_CHANNEL_OUT_BACK_RIGHT), - AUDIO_CHANNEL_OUT_QUAD_BACK = AUDIO_CHANNEL_OUT_QUAD, - /* like AUDIO_CHANNEL_OUT_QUAD_BACK with *_SIDE_* instead of *_BACK_* */ - AUDIO_CHANNEL_OUT_QUAD_SIDE = (AUDIO_CHANNEL_OUT_FRONT_LEFT | - AUDIO_CHANNEL_OUT_FRONT_RIGHT | - AUDIO_CHANNEL_OUT_SIDE_LEFT | - AUDIO_CHANNEL_OUT_SIDE_RIGHT), - AUDIO_CHANNEL_OUT_5POINT1 = (AUDIO_CHANNEL_OUT_FRONT_LEFT | - AUDIO_CHANNEL_OUT_FRONT_RIGHT | - AUDIO_CHANNEL_OUT_FRONT_CENTER | - AUDIO_CHANNEL_OUT_LOW_FREQUENCY | - AUDIO_CHANNEL_OUT_BACK_LEFT | - AUDIO_CHANNEL_OUT_BACK_RIGHT), - AUDIO_CHANNEL_OUT_5POINT1_BACK = AUDIO_CHANNEL_OUT_5POINT1, - /* like AUDIO_CHANNEL_OUT_5POINT1_BACK with *_SIDE_* instead of *_BACK_* */ - AUDIO_CHANNEL_OUT_5POINT1_SIDE = (AUDIO_CHANNEL_OUT_FRONT_LEFT | - AUDIO_CHANNEL_OUT_FRONT_RIGHT | - AUDIO_CHANNEL_OUT_FRONT_CENTER | - AUDIO_CHANNEL_OUT_LOW_FREQUENCY | - AUDIO_CHANNEL_OUT_SIDE_LEFT | - AUDIO_CHANNEL_OUT_SIDE_RIGHT), - // matches the correct AudioFormat.CHANNEL_OUT_7POINT1_SURROUND definition for 7.1 - AUDIO_CHANNEL_OUT_7POINT1 = (AUDIO_CHANNEL_OUT_FRONT_LEFT | - AUDIO_CHANNEL_OUT_FRONT_RIGHT | - AUDIO_CHANNEL_OUT_FRONT_CENTER | - AUDIO_CHANNEL_OUT_LOW_FREQUENCY | - AUDIO_CHANNEL_OUT_BACK_LEFT | - AUDIO_CHANNEL_OUT_BACK_RIGHT | - AUDIO_CHANNEL_OUT_SIDE_LEFT | - AUDIO_CHANNEL_OUT_SIDE_RIGHT), - AUDIO_CHANNEL_OUT_ALL = (AUDIO_CHANNEL_OUT_FRONT_LEFT | - AUDIO_CHANNEL_OUT_FRONT_RIGHT | - AUDIO_CHANNEL_OUT_FRONT_CENTER | - AUDIO_CHANNEL_OUT_LOW_FREQUENCY | - AUDIO_CHANNEL_OUT_BACK_LEFT | - AUDIO_CHANNEL_OUT_BACK_RIGHT | - AUDIO_CHANNEL_OUT_FRONT_LEFT_OF_CENTER | - AUDIO_CHANNEL_OUT_FRONT_RIGHT_OF_CENTER | - AUDIO_CHANNEL_OUT_BACK_CENTER| - AUDIO_CHANNEL_OUT_SIDE_LEFT| - AUDIO_CHANNEL_OUT_SIDE_RIGHT| - AUDIO_CHANNEL_OUT_TOP_CENTER| - AUDIO_CHANNEL_OUT_TOP_FRONT_LEFT| - AUDIO_CHANNEL_OUT_TOP_FRONT_CENTER| - AUDIO_CHANNEL_OUT_TOP_FRONT_RIGHT| - AUDIO_CHANNEL_OUT_TOP_BACK_LEFT| - AUDIO_CHANNEL_OUT_TOP_BACK_CENTER| - AUDIO_CHANNEL_OUT_TOP_BACK_RIGHT), - -/* These are bits only, not complete values */ - - /* input channels */ - AUDIO_CHANNEL_IN_LEFT = 0x4, - AUDIO_CHANNEL_IN_RIGHT = 0x8, - AUDIO_CHANNEL_IN_FRONT = 0x10, - AUDIO_CHANNEL_IN_BACK = 0x20, - AUDIO_CHANNEL_IN_LEFT_PROCESSED = 0x40, - AUDIO_CHANNEL_IN_RIGHT_PROCESSED = 0x80, - AUDIO_CHANNEL_IN_FRONT_PROCESSED = 0x100, - AUDIO_CHANNEL_IN_BACK_PROCESSED = 0x200, - AUDIO_CHANNEL_IN_PRESSURE = 0x400, - AUDIO_CHANNEL_IN_X_AXIS = 0x800, - AUDIO_CHANNEL_IN_Y_AXIS = 0x1000, - AUDIO_CHANNEL_IN_Z_AXIS = 0x2000, - AUDIO_CHANNEL_IN_VOICE_UPLINK = 0x4000, - AUDIO_CHANNEL_IN_VOICE_DNLINK = 0x8000, - -/* TODO: should these be considered complete channel masks, or only bits, or deprecated? */ - - AUDIO_CHANNEL_IN_MONO = AUDIO_CHANNEL_IN_FRONT, - AUDIO_CHANNEL_IN_STEREO = (AUDIO_CHANNEL_IN_LEFT | AUDIO_CHANNEL_IN_RIGHT), - AUDIO_CHANNEL_IN_FRONT_BACK = (AUDIO_CHANNEL_IN_FRONT | AUDIO_CHANNEL_IN_BACK), - AUDIO_CHANNEL_IN_ALL = (AUDIO_CHANNEL_IN_LEFT | - AUDIO_CHANNEL_IN_RIGHT | - AUDIO_CHANNEL_IN_FRONT | - AUDIO_CHANNEL_IN_BACK| - AUDIO_CHANNEL_IN_LEFT_PROCESSED | - AUDIO_CHANNEL_IN_RIGHT_PROCESSED | - AUDIO_CHANNEL_IN_FRONT_PROCESSED | - AUDIO_CHANNEL_IN_BACK_PROCESSED| - AUDIO_CHANNEL_IN_PRESSURE | - AUDIO_CHANNEL_IN_X_AXIS | - AUDIO_CHANNEL_IN_Y_AXIS | - AUDIO_CHANNEL_IN_Z_AXIS | - AUDIO_CHANNEL_IN_VOICE_UPLINK | - AUDIO_CHANNEL_IN_VOICE_DNLINK), -}; - -/* A channel mask per se only defines the presence or absence of a channel, not the order. - * But see AUDIO_INTERLEAVE_* below for the platform convention of order. - * - * audio_channel_mask_t is an opaque type and its internal layout should not - * be assumed as it may change in the future. - * Instead, always use the functions declared in this header to examine. - * - * These are the current representations: - * - * AUDIO_CHANNEL_REPRESENTATION_POSITION - * is a channel mask representation for position assignment. - * Each low-order bit corresponds to the spatial position of a transducer (output), - * or interpretation of channel (input). - * The user of a channel mask needs to know the context of whether it is for output or input. - * The constants AUDIO_CHANNEL_OUT_* or AUDIO_CHANNEL_IN_* apply to the bits portion. - * It is not permitted for no bits to be set. - * - * AUDIO_CHANNEL_REPRESENTATION_INDEX - * is a channel mask representation for index assignment. - * Each low-order bit corresponds to a selected channel. - * There is no platform interpretation of the various bits. - * There is no concept of output or input. - * It is not permitted for no bits to be set. - * - * All other representations are reserved for future use. - * - * Warning: current representation distinguishes between input and output, but this will not the be - * case in future revisions of the platform. Wherever there is an ambiguity between input and output - * that is currently resolved by checking the channel mask, the implementer should look for ways to - * fix it with additional information outside of the mask. - */ -typedef uint32_t audio_channel_mask_t; - -/* Maximum number of channels for all representations */ -#define AUDIO_CHANNEL_COUNT_MAX 30 - -/* log(2) of maximum number of representations, not part of public API */ -#define AUDIO_CHANNEL_REPRESENTATION_LOG2 2 - -/* Representations */ -typedef enum { - AUDIO_CHANNEL_REPRESENTATION_POSITION = 0, // must be zero for compatibility - // 1 is reserved for future use - AUDIO_CHANNEL_REPRESENTATION_INDEX = 2, - // 3 is reserved for future use -} audio_channel_representation_t; - -/* The return value is undefined if the channel mask is invalid. */ -static inline uint32_t audio_channel_mask_get_bits(audio_channel_mask_t channel) -{ - return channel & ((1 << AUDIO_CHANNEL_COUNT_MAX) - 1); -} - -/* The return value is undefined if the channel mask is invalid. */ -static inline audio_channel_representation_t audio_channel_mask_get_representation( - audio_channel_mask_t channel) -{ - // The right shift should be sufficient, but also "and" for safety in case mask is not 32 bits - return (audio_channel_representation_t) - ((channel >> AUDIO_CHANNEL_COUNT_MAX) & ((1 << AUDIO_CHANNEL_REPRESENTATION_LOG2) - 1)); -} - -/* Returns true if the channel mask is valid, - * or returns false for AUDIO_CHANNEL_NONE, AUDIO_CHANNEL_INVALID, and other invalid values. - * This function is unable to determine whether a channel mask for position assignment - * is invalid because an output mask has an invalid output bit set, - * or because an input mask has an invalid input bit set. - * All other APIs that take a channel mask assume that it is valid. - */ -static inline bool audio_channel_mask_is_valid(audio_channel_mask_t channel) -{ - uint32_t bits = audio_channel_mask_get_bits(channel); - audio_channel_representation_t representation = audio_channel_mask_get_representation(channel); - switch (representation) { - case AUDIO_CHANNEL_REPRESENTATION_POSITION: - case AUDIO_CHANNEL_REPRESENTATION_INDEX: - break; - default: - bits = 0; - break; - } - return bits != 0; -} - -/* Not part of public API */ -static inline audio_channel_mask_t audio_channel_mask_from_representation_and_bits( - audio_channel_representation_t representation, uint32_t bits) -{ - return (audio_channel_mask_t) ((representation << AUDIO_CHANNEL_COUNT_MAX) | bits); -} - -/* Expresses the convention when stereo audio samples are stored interleaved - * in an array. This should improve readability by allowing code to use - * symbolic indices instead of hard-coded [0] and [1]. - * - * For multi-channel beyond stereo, the platform convention is that channels - * are interleaved in order from least significant channel mask bit - * to most significant channel mask bit, with unused bits skipped. - * Any exceptions to this convention will be noted at the appropriate API. - */ -enum { - AUDIO_INTERLEAVE_LEFT = 0, - AUDIO_INTERLEAVE_RIGHT = 1, -}; - -typedef enum { - AUDIO_MODE_INVALID = -2, - AUDIO_MODE_CURRENT = -1, - AUDIO_MODE_NORMAL = 0, - AUDIO_MODE_RINGTONE = 1, - AUDIO_MODE_IN_CALL = 2, - AUDIO_MODE_IN_COMMUNICATION = 3, - - AUDIO_MODE_CNT, - AUDIO_MODE_MAX = AUDIO_MODE_CNT - 1, -} audio_mode_t; - -/* This enum is deprecated */ -typedef enum { - AUDIO_IN_ACOUSTICS_NONE = 0, - AUDIO_IN_ACOUSTICS_AGC_ENABLE = 0x0001, - AUDIO_IN_ACOUSTICS_AGC_DISABLE = 0, - AUDIO_IN_ACOUSTICS_NS_ENABLE = 0x0002, - AUDIO_IN_ACOUSTICS_NS_DISABLE = 0, - AUDIO_IN_ACOUSTICS_TX_IIR_ENABLE = 0x0004, - AUDIO_IN_ACOUSTICS_TX_DISABLE = 0, -} audio_in_acoustics_t; - -enum { - AUDIO_DEVICE_NONE = 0x0, - /* reserved bits */ - AUDIO_DEVICE_BIT_IN = 0x80000000, - AUDIO_DEVICE_BIT_DEFAULT = 0x40000000, - /* output devices */ - AUDIO_DEVICE_OUT_EARPIECE = 0x1, - AUDIO_DEVICE_OUT_SPEAKER = 0x2, - AUDIO_DEVICE_OUT_WIRED_HEADSET = 0x4, - AUDIO_DEVICE_OUT_WIRED_HEADPHONE = 0x8, - AUDIO_DEVICE_OUT_BLUETOOTH_SCO = 0x10, - AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET = 0x20, - AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT = 0x40, - AUDIO_DEVICE_OUT_BLUETOOTH_A2DP = 0x80, - AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES = 0x100, - AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER = 0x200, - AUDIO_DEVICE_OUT_AUX_DIGITAL = 0x400, - AUDIO_DEVICE_OUT_HDMI = AUDIO_DEVICE_OUT_AUX_DIGITAL, - /* uses an analog connection (multiplexed over the USB connector pins for instance) */ - AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET = 0x800, - AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET = 0x1000, - /* USB accessory mode: your Android device is a USB device and the dock is a USB host */ - AUDIO_DEVICE_OUT_USB_ACCESSORY = 0x2000, - /* USB host mode: your Android device is a USB host and the dock is a USB device */ - AUDIO_DEVICE_OUT_USB_DEVICE = 0x4000, - AUDIO_DEVICE_OUT_REMOTE_SUBMIX = 0x8000, - /* Telephony voice TX path */ - AUDIO_DEVICE_OUT_TELEPHONY_TX = 0x10000, - /* Analog jack with line impedance detected */ - AUDIO_DEVICE_OUT_LINE = 0x20000, - /* HDMI Audio Return Channel */ - AUDIO_DEVICE_OUT_HDMI_ARC = 0x40000, - /* S/PDIF out */ - AUDIO_DEVICE_OUT_SPDIF = 0x80000, - /* FM transmitter out */ - AUDIO_DEVICE_OUT_FM = 0x100000, - /* Line out for av devices */ - AUDIO_DEVICE_OUT_AUX_LINE = 0x200000, - /* limited-output speaker device for acoustic safety */ - AUDIO_DEVICE_OUT_SPEAKER_SAFE = 0x400000, - AUDIO_DEVICE_OUT_DEFAULT = AUDIO_DEVICE_BIT_DEFAULT, - AUDIO_DEVICE_OUT_ALL = (AUDIO_DEVICE_OUT_EARPIECE | - AUDIO_DEVICE_OUT_SPEAKER | - AUDIO_DEVICE_OUT_WIRED_HEADSET | - AUDIO_DEVICE_OUT_WIRED_HEADPHONE | - AUDIO_DEVICE_OUT_BLUETOOTH_SCO | - AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET | - AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT | - AUDIO_DEVICE_OUT_BLUETOOTH_A2DP | - AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES | - AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER | - AUDIO_DEVICE_OUT_HDMI | - AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET | - AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET | - AUDIO_DEVICE_OUT_USB_ACCESSORY | - AUDIO_DEVICE_OUT_USB_DEVICE | - AUDIO_DEVICE_OUT_REMOTE_SUBMIX | - AUDIO_DEVICE_OUT_TELEPHONY_TX | - AUDIO_DEVICE_OUT_LINE | - AUDIO_DEVICE_OUT_HDMI_ARC | - AUDIO_DEVICE_OUT_SPDIF | - AUDIO_DEVICE_OUT_FM | - AUDIO_DEVICE_OUT_AUX_LINE | - AUDIO_DEVICE_OUT_SPEAKER_SAFE | - AUDIO_DEVICE_OUT_DEFAULT), - AUDIO_DEVICE_OUT_ALL_A2DP = (AUDIO_DEVICE_OUT_BLUETOOTH_A2DP | - AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES | - AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER), - AUDIO_DEVICE_OUT_ALL_SCO = (AUDIO_DEVICE_OUT_BLUETOOTH_SCO | - AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET | - AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT), - AUDIO_DEVICE_OUT_ALL_USB = (AUDIO_DEVICE_OUT_USB_ACCESSORY | - AUDIO_DEVICE_OUT_USB_DEVICE), - - /* input devices */ - AUDIO_DEVICE_IN_COMMUNICATION = AUDIO_DEVICE_BIT_IN | 0x1, - AUDIO_DEVICE_IN_AMBIENT = AUDIO_DEVICE_BIT_IN | 0x2, - AUDIO_DEVICE_IN_BUILTIN_MIC = AUDIO_DEVICE_BIT_IN | 0x4, - AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET = AUDIO_DEVICE_BIT_IN | 0x8, - AUDIO_DEVICE_IN_WIRED_HEADSET = AUDIO_DEVICE_BIT_IN | 0x10, - AUDIO_DEVICE_IN_AUX_DIGITAL = AUDIO_DEVICE_BIT_IN | 0x20, - AUDIO_DEVICE_IN_HDMI = AUDIO_DEVICE_IN_AUX_DIGITAL, - /* Telephony voice RX path */ - AUDIO_DEVICE_IN_VOICE_CALL = AUDIO_DEVICE_BIT_IN | 0x40, - AUDIO_DEVICE_IN_TELEPHONY_RX = AUDIO_DEVICE_IN_VOICE_CALL, - AUDIO_DEVICE_IN_BACK_MIC = AUDIO_DEVICE_BIT_IN | 0x80, - AUDIO_DEVICE_IN_REMOTE_SUBMIX = AUDIO_DEVICE_BIT_IN | 0x100, - AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET = AUDIO_DEVICE_BIT_IN | 0x200, - AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET = AUDIO_DEVICE_BIT_IN | 0x400, - AUDIO_DEVICE_IN_USB_ACCESSORY = AUDIO_DEVICE_BIT_IN | 0x800, - AUDIO_DEVICE_IN_USB_DEVICE = AUDIO_DEVICE_BIT_IN | 0x1000, - /* FM tuner input */ - AUDIO_DEVICE_IN_FM_TUNER = AUDIO_DEVICE_BIT_IN | 0x2000, - /* TV tuner input */ - AUDIO_DEVICE_IN_TV_TUNER = AUDIO_DEVICE_BIT_IN | 0x4000, - /* Analog jack with line impedance detected */ - AUDIO_DEVICE_IN_LINE = AUDIO_DEVICE_BIT_IN | 0x8000, - /* S/PDIF in */ - AUDIO_DEVICE_IN_SPDIF = AUDIO_DEVICE_BIT_IN | 0x10000, - AUDIO_DEVICE_IN_BLUETOOTH_A2DP = AUDIO_DEVICE_BIT_IN | 0x20000, - AUDIO_DEVICE_IN_LOOPBACK = AUDIO_DEVICE_BIT_IN | 0x40000, - AUDIO_DEVICE_IN_DEFAULT = AUDIO_DEVICE_BIT_IN | AUDIO_DEVICE_BIT_DEFAULT, - - AUDIO_DEVICE_IN_ALL = (AUDIO_DEVICE_IN_COMMUNICATION | - AUDIO_DEVICE_IN_AMBIENT | - AUDIO_DEVICE_IN_BUILTIN_MIC | - AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET | - AUDIO_DEVICE_IN_WIRED_HEADSET | - AUDIO_DEVICE_IN_HDMI | - AUDIO_DEVICE_IN_TELEPHONY_RX | - AUDIO_DEVICE_IN_BACK_MIC | - AUDIO_DEVICE_IN_REMOTE_SUBMIX | - AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET | - AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET | - AUDIO_DEVICE_IN_USB_ACCESSORY | - AUDIO_DEVICE_IN_USB_DEVICE | - AUDIO_DEVICE_IN_FM_TUNER | - AUDIO_DEVICE_IN_TV_TUNER | - AUDIO_DEVICE_IN_LINE | - AUDIO_DEVICE_IN_SPDIF | - AUDIO_DEVICE_IN_BLUETOOTH_A2DP | - AUDIO_DEVICE_IN_LOOPBACK | - AUDIO_DEVICE_IN_DEFAULT), - AUDIO_DEVICE_IN_ALL_SCO = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, - AUDIO_DEVICE_IN_ALL_USB = (AUDIO_DEVICE_IN_USB_ACCESSORY | - AUDIO_DEVICE_IN_USB_DEVICE), -}; - -typedef uint32_t audio_devices_t; - -/* the audio output flags serve two purposes: - * - when an AudioTrack is created they indicate a "wish" to be connected to an - * output stream with attributes corresponding to the specified flags - * - when present in an output profile descriptor listed for a particular audio - * hardware module, they indicate that an output stream can be opened that - * supports the attributes indicated by the flags. - * the audio policy manager will try to match the flags in the request - * (when getOuput() is called) to an available output stream. - */ -typedef enum { - AUDIO_OUTPUT_FLAG_NONE = 0x0, // no attributes - AUDIO_OUTPUT_FLAG_DIRECT = 0x1, // this output directly connects a track - // to one output stream: no software mixer - AUDIO_OUTPUT_FLAG_PRIMARY = 0x2, // this output is the primary output of - // the device. It is unique and must be - // present. It is opened by default and - // receives routing, audio mode and volume - // controls related to voice calls. - AUDIO_OUTPUT_FLAG_FAST = 0x4, // output supports "fast tracks", - // defined elsewhere - AUDIO_OUTPUT_FLAG_DEEP_BUFFER = 0x8, // use deep audio buffers - AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD = 0x10, // offload playback of compressed - // streams to hardware codec - AUDIO_OUTPUT_FLAG_NON_BLOCKING = 0x20, // use non-blocking write - AUDIO_OUTPUT_FLAG_HW_AV_SYNC = 0x40 // output uses a hardware A/V synchronization source -} audio_output_flags_t; - -/* The audio input flags are analogous to audio output flags. - * Currently they are used only when an AudioRecord is created, - * to indicate a preference to be connected to an input stream with - * attributes corresponding to the specified flags. - */ -typedef enum { - AUDIO_INPUT_FLAG_NONE = 0x0, // no attributes - AUDIO_INPUT_FLAG_FAST = 0x1, // prefer an input that supports "fast tracks" - AUDIO_INPUT_FLAG_HW_HOTWORD = 0x2, // prefer an input that captures from hw hotword source -} audio_input_flags_t; - -/* Additional information about compressed streams offloaded to - * hardware playback - * The version and size fields must be initialized by the caller by using - * one of the constants defined here. - */ -typedef struct { - uint16_t version; // version of the info structure - uint16_t size; // total size of the structure including version and size - uint32_t sample_rate; // sample rate in Hz - audio_channel_mask_t channel_mask; // channel mask - audio_format_t format; // audio format - audio_stream_type_t stream_type; // stream type - uint32_t bit_rate; // bit rate in bits per second - int64_t duration_us; // duration in microseconds, -1 if unknown - bool has_video; // true if stream is tied to a video stream - bool is_streaming; // true if streaming, false if local playback -} audio_offload_info_t; - -#define AUDIO_MAKE_OFFLOAD_INFO_VERSION(maj,min) \ - ((((maj) & 0xff) << 8) | ((min) & 0xff)) - -#define AUDIO_OFFLOAD_INFO_VERSION_0_1 AUDIO_MAKE_OFFLOAD_INFO_VERSION(0, 1) -#define AUDIO_OFFLOAD_INFO_VERSION_CURRENT AUDIO_OFFLOAD_INFO_VERSION_0_1 - -static const audio_offload_info_t AUDIO_INFO_INITIALIZER = { - version: AUDIO_OFFLOAD_INFO_VERSION_CURRENT, - size: sizeof(audio_offload_info_t), - sample_rate: 0, - channel_mask: 0, - format: AUDIO_FORMAT_DEFAULT, - stream_type: AUDIO_STREAM_VOICE_CALL, - bit_rate: 0, - duration_us: 0, - has_video: false, - is_streaming: false -}; - -/* common audio stream configuration parameters - * You should memset() the entire structure to zero before use to - * ensure forward compatibility - */ -struct audio_config { - uint32_t sample_rate; - audio_channel_mask_t channel_mask; - audio_format_t format; - audio_offload_info_t offload_info; - size_t frame_count; -}; -typedef struct audio_config audio_config_t; - -static const audio_config_t AUDIO_CONFIG_INITIALIZER = { - sample_rate: 0, - channel_mask: AUDIO_CHANNEL_NONE, - format: AUDIO_FORMAT_DEFAULT, - offload_info: { - version: AUDIO_OFFLOAD_INFO_VERSION_CURRENT, - size: sizeof(audio_offload_info_t), - sample_rate: 0, - channel_mask: 0, - format: AUDIO_FORMAT_DEFAULT, - stream_type: AUDIO_STREAM_VOICE_CALL, - bit_rate: 0, - duration_us: 0, - has_video: false, - is_streaming: false - }, - frame_count: 0, -}; - - -/* audio hw module handle functions or structures referencing a module */ -typedef int audio_module_handle_t; - -/****************************** - * Volume control - *****************************/ - -/* If the audio hardware supports gain control on some audio paths, - * the platform can expose them in the audio_policy.conf file. The audio HAL - * will then implement gain control functions that will use the following data - * structures. */ - -/* Type of gain control exposed by an audio port */ -#define AUDIO_GAIN_MODE_JOINT 0x1 /* supports joint channel gain control */ -#define AUDIO_GAIN_MODE_CHANNELS 0x2 /* supports separate channel gain control */ -#define AUDIO_GAIN_MODE_RAMP 0x4 /* supports gain ramps */ - -typedef uint32_t audio_gain_mode_t; - - -/* An audio_gain struct is a representation of a gain stage. - * A gain stage is always attached to an audio port. */ -struct audio_gain { - audio_gain_mode_t mode; /* e.g. AUDIO_GAIN_MODE_JOINT */ - audio_channel_mask_t channel_mask; /* channels which gain an be controlled. - N/A if AUDIO_GAIN_MODE_CHANNELS is not supported */ - int min_value; /* minimum gain value in millibels */ - int max_value; /* maximum gain value in millibels */ - int default_value; /* default gain value in millibels */ - unsigned int step_value; /* gain step in millibels */ - unsigned int min_ramp_ms; /* minimum ramp duration in ms */ - unsigned int max_ramp_ms; /* maximum ramp duration in ms */ -}; - -/* The gain configuration structure is used to get or set the gain values of a - * given port */ -struct audio_gain_config { - int index; /* index of the corresponding audio_gain in the - audio_port gains[] table */ - audio_gain_mode_t mode; /* mode requested for this command */ - audio_channel_mask_t channel_mask; /* channels which gain value follows. - N/A in joint mode */ - int values[sizeof(audio_channel_mask_t) * 8]; /* gain values in millibels - for each channel ordered from LSb to MSb in - channel mask. The number of values is 1 in joint - mode or popcount(channel_mask) */ - unsigned int ramp_duration_ms; /* ramp duration in ms */ -}; - -/****************************** - * Routing control - *****************************/ - -/* Types defined here are used to describe an audio source or sink at internal - * framework interfaces (audio policy, patch panel) or at the audio HAL. - * Sink and sources are grouped in a concept of “audio port” representing an - * audio end point at the edge of the system managed by the module exposing - * the interface. */ - -/* Audio port role: either source or sink */ -typedef enum { - AUDIO_PORT_ROLE_NONE, - AUDIO_PORT_ROLE_SOURCE, - AUDIO_PORT_ROLE_SINK, -} audio_port_role_t; - -/* Audio port type indicates if it is a session (e.g AudioTrack), - * a mix (e.g PlaybackThread output) or a physical device - * (e.g AUDIO_DEVICE_OUT_SPEAKER) */ -typedef enum { - AUDIO_PORT_TYPE_NONE, - AUDIO_PORT_TYPE_DEVICE, - AUDIO_PORT_TYPE_MIX, - AUDIO_PORT_TYPE_SESSION, -} audio_port_type_t; - -/* Each port has a unique ID or handle allocated by policy manager */ -typedef int audio_port_handle_t; -#define AUDIO_PORT_HANDLE_NONE 0 - - -/* maximum audio device address length */ -#define AUDIO_DEVICE_MAX_ADDRESS_LEN 32 - -/* extension for audio port configuration structure when the audio port is a - * hardware device */ -struct audio_port_config_device_ext { - audio_module_handle_t hw_module; /* module the device is attached to */ - audio_devices_t type; /* device type (e.g AUDIO_DEVICE_OUT_SPEAKER) */ - char address[AUDIO_DEVICE_MAX_ADDRESS_LEN]; /* device address. "" if N/A */ -}; - -/* extension for audio port configuration structure when the audio port is a - * sub mix */ -struct audio_port_config_mix_ext { - audio_module_handle_t hw_module; /* module the stream is attached to */ - audio_io_handle_t handle; /* I/O handle of the input/output stream */ - union { - //TODO: change use case for output streams: use strategy and mixer attributes - audio_stream_type_t stream; - audio_source_t source; - } usecase; -}; - -/* extension for audio port configuration structure when the audio port is an - * audio session */ -struct audio_port_config_session_ext { - audio_session_t session; /* audio session */ -}; - -/* Flags indicating which fields are to be considered in struct audio_port_config */ -#define AUDIO_PORT_CONFIG_SAMPLE_RATE 0x1 -#define AUDIO_PORT_CONFIG_CHANNEL_MASK 0x2 -#define AUDIO_PORT_CONFIG_FORMAT 0x4 -#define AUDIO_PORT_CONFIG_GAIN 0x8 -#define AUDIO_PORT_CONFIG_ALL (AUDIO_PORT_CONFIG_SAMPLE_RATE | \ - AUDIO_PORT_CONFIG_CHANNEL_MASK | \ - AUDIO_PORT_CONFIG_FORMAT | \ - AUDIO_PORT_CONFIG_GAIN) - -/* audio port configuration structure used to specify a particular configuration of - * an audio port */ -struct audio_port_config { - audio_port_handle_t id; /* port unique ID */ - audio_port_role_t role; /* sink or source */ - audio_port_type_t type; /* device, mix ... */ - unsigned int config_mask; /* e.g AUDIO_PORT_CONFIG_ALL */ - unsigned int sample_rate; /* sampling rate in Hz */ - audio_channel_mask_t channel_mask; /* channel mask if applicable */ - audio_format_t format; /* format if applicable */ - struct audio_gain_config gain; /* gain to apply if applicable */ - union { - struct audio_port_config_device_ext device; /* device specific info */ - struct audio_port_config_mix_ext mix; /* mix specific info */ - struct audio_port_config_session_ext session; /* session specific info */ - } ext; -}; - - -/* max number of sampling rates in audio port */ -#define AUDIO_PORT_MAX_SAMPLING_RATES 16 -/* max number of channel masks in audio port */ -#define AUDIO_PORT_MAX_CHANNEL_MASKS 16 -/* max number of audio formats in audio port */ -#define AUDIO_PORT_MAX_FORMATS 16 -/* max number of gain controls in audio port */ -#define AUDIO_PORT_MAX_GAINS 16 - -/* extension for audio port structure when the audio port is a hardware device */ -struct audio_port_device_ext { - audio_module_handle_t hw_module; /* module the device is attached to */ - audio_devices_t type; /* device type (e.g AUDIO_DEVICE_OUT_SPEAKER) */ - char address[AUDIO_DEVICE_MAX_ADDRESS_LEN]; -}; - -/* Latency class of the audio mix */ -typedef enum { - AUDIO_LATENCY_LOW, - AUDIO_LATENCY_NORMAL, -} audio_mix_latency_class_t; - -/* extension for audio port structure when the audio port is a sub mix */ -struct audio_port_mix_ext { - audio_module_handle_t hw_module; /* module the stream is attached to */ - audio_io_handle_t handle; /* I/O handle of the input.output stream */ - audio_mix_latency_class_t latency_class; /* latency class */ - // other attributes: routing strategies -}; - -/* extension for audio port structure when the audio port is an audio session */ -struct audio_port_session_ext { - audio_session_t session; /* audio session */ -}; - - -struct audio_port { - audio_port_handle_t id; /* port unique ID */ - audio_port_role_t role; /* sink or source */ - audio_port_type_t type; /* device, mix ... */ - unsigned int num_sample_rates; /* number of sampling rates in following array */ - unsigned int sample_rates[AUDIO_PORT_MAX_SAMPLING_RATES]; - unsigned int num_channel_masks; /* number of channel masks in following array */ - audio_channel_mask_t channel_masks[AUDIO_PORT_MAX_CHANNEL_MASKS]; - unsigned int num_formats; /* number of formats in following array */ - audio_format_t formats[AUDIO_PORT_MAX_FORMATS]; - unsigned int num_gains; /* number of gains in following array */ - struct audio_gain gains[AUDIO_PORT_MAX_GAINS]; - struct audio_port_config active_config; /* current audio port configuration */ - union { - struct audio_port_device_ext device; - struct audio_port_mix_ext mix; - struct audio_port_session_ext session; - } ext; -}; - -/* An audio patch represents a connection between one or more source ports and - * one or more sink ports. Patches are connected and disconnected by audio policy manager or by - * applications via framework APIs. - * Each patch is identified by a handle at the interface used to create that patch. For instance, - * when a patch is created by the audio HAL, the HAL allocates and returns a handle. - * This handle is unique to a given audio HAL hardware module. - * But the same patch receives another system wide unique handle allocated by the framework. - * This unique handle is used for all transactions inside the framework. - */ -typedef int audio_patch_handle_t; -#define AUDIO_PATCH_HANDLE_NONE 0 - -#define AUDIO_PATCH_PORTS_MAX 16 - -struct audio_patch { - audio_patch_handle_t id; /* patch unique ID */ - unsigned int num_sources; /* number of sources in following array */ - struct audio_port_config sources[AUDIO_PATCH_PORTS_MAX]; - unsigned int num_sinks; /* number of sinks in following array */ - struct audio_port_config sinks[AUDIO_PATCH_PORTS_MAX]; -}; - - - -/* a HW synchronization source returned by the audio HAL */ -typedef uint32_t audio_hw_sync_t; - -/* an invalid HW synchronization source indicating an error */ -#define AUDIO_HW_SYNC_INVALID 0 - -static inline bool audio_is_output_device(audio_devices_t device) -{ - if (((device & AUDIO_DEVICE_BIT_IN) == 0) && - (popcount(device) == 1) && ((device & ~AUDIO_DEVICE_OUT_ALL) == 0)) - return true; - else - return false; -} - -static inline bool audio_is_input_device(audio_devices_t device) -{ - if ((device & AUDIO_DEVICE_BIT_IN) != 0) { - device &= ~AUDIO_DEVICE_BIT_IN; - if ((popcount(device) == 1) && ((device & ~AUDIO_DEVICE_IN_ALL) == 0)) - return true; - } - return false; -} - -static inline bool audio_is_output_devices(audio_devices_t device) -{ - return (device & AUDIO_DEVICE_BIT_IN) == 0; -} - -static inline bool audio_is_a2dp_in_device(audio_devices_t device) -{ - if ((device & AUDIO_DEVICE_BIT_IN) != 0) { - device &= ~AUDIO_DEVICE_BIT_IN; - if ((popcount(device) == 1) && (device & AUDIO_DEVICE_IN_BLUETOOTH_A2DP)) - return true; - } - return false; -} - -static inline bool audio_is_a2dp_out_device(audio_devices_t device) -{ - if ((popcount(device) == 1) && (device & AUDIO_DEVICE_OUT_ALL_A2DP)) - return true; - else - return false; -} - -// Deprecated - use audio_is_a2dp_out_device() instead -static inline bool audio_is_a2dp_device(audio_devices_t device) -{ - return audio_is_a2dp_out_device(device); -} - -static inline bool audio_is_bluetooth_sco_device(audio_devices_t device) -{ - if ((device & AUDIO_DEVICE_BIT_IN) == 0) { - if ((popcount(device) == 1) && ((device & ~AUDIO_DEVICE_OUT_ALL_SCO) == 0)) - return true; - } else { - device &= ~AUDIO_DEVICE_BIT_IN; - if ((popcount(device) == 1) && ((device & ~AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) == 0)) - return true; - } - - return false; -} - -static inline bool audio_is_usb_out_device(audio_devices_t device) -{ - return ((popcount(device) == 1) && (device & AUDIO_DEVICE_OUT_ALL_USB)); -} - -static inline bool audio_is_usb_in_device(audio_devices_t device) -{ - if ((device & AUDIO_DEVICE_BIT_IN) != 0) { - device &= ~AUDIO_DEVICE_BIT_IN; - if (popcount(device) == 1 && (device & AUDIO_DEVICE_IN_ALL_USB) != 0) - return true; - } - return false; -} - -/* OBSOLETE - use audio_is_usb_out_device() instead. */ -static inline bool audio_is_usb_device(audio_devices_t device) -{ - return audio_is_usb_out_device(device); -} - -static inline bool audio_is_remote_submix_device(audio_devices_t device) -{ - if ((device & AUDIO_DEVICE_OUT_REMOTE_SUBMIX) == AUDIO_DEVICE_OUT_REMOTE_SUBMIX - || (device & AUDIO_DEVICE_IN_REMOTE_SUBMIX) == AUDIO_DEVICE_IN_REMOTE_SUBMIX) - return true; - else - return false; -} - -/* Returns true if: - * representation is valid, and - * there is at least one channel bit set which _could_ correspond to an input channel, and - * there are no channel bits set which could _not_ correspond to an input channel. - * Otherwise returns false. - */ -static inline bool audio_is_input_channel(audio_channel_mask_t channel) -{ - uint32_t bits = audio_channel_mask_get_bits(channel); - switch (audio_channel_mask_get_representation(channel)) { - case AUDIO_CHANNEL_REPRESENTATION_POSITION: - if (bits & ~AUDIO_CHANNEL_IN_ALL) { - bits = 0; - } - // fall through - case AUDIO_CHANNEL_REPRESENTATION_INDEX: - return bits != 0; - default: - return false; - } -} - -/* Returns true if: - * representation is valid, and - * there is at least one channel bit set which _could_ correspond to an output channel, and - * there are no channel bits set which could _not_ correspond to an output channel. - * Otherwise returns false. - */ -static inline bool audio_is_output_channel(audio_channel_mask_t channel) -{ - uint32_t bits = audio_channel_mask_get_bits(channel); - switch (audio_channel_mask_get_representation(channel)) { - case AUDIO_CHANNEL_REPRESENTATION_POSITION: - if (bits & ~AUDIO_CHANNEL_OUT_ALL) { - bits = 0; - } - // fall through - case AUDIO_CHANNEL_REPRESENTATION_INDEX: - return bits != 0; - default: - return false; - } -} - -/* Returns the number of channels from an input channel mask, - * used in the context of audio input or recording. - * If a channel bit is set which could _not_ correspond to an input channel, - * it is excluded from the count. - * Returns zero if the representation is invalid. - */ -static inline uint32_t audio_channel_count_from_in_mask(audio_channel_mask_t channel) -{ - uint32_t bits = audio_channel_mask_get_bits(channel); - switch (audio_channel_mask_get_representation(channel)) { - case AUDIO_CHANNEL_REPRESENTATION_POSITION: - // TODO: We can now merge with from_out_mask and remove anding - bits &= AUDIO_CHANNEL_IN_ALL; - // fall through - case AUDIO_CHANNEL_REPRESENTATION_INDEX: - return popcount(bits); - default: - return 0; - } -} - -/* Returns the number of channels from an output channel mask, - * used in the context of audio output or playback. - * If a channel bit is set which could _not_ correspond to an output channel, - * it is excluded from the count. - * Returns zero if the representation is invalid. - */ -static inline uint32_t audio_channel_count_from_out_mask(audio_channel_mask_t channel) -{ - uint32_t bits = audio_channel_mask_get_bits(channel); - switch (audio_channel_mask_get_representation(channel)) { - case AUDIO_CHANNEL_REPRESENTATION_POSITION: - // TODO: We can now merge with from_in_mask and remove anding - bits &= AUDIO_CHANNEL_OUT_ALL; - // fall through - case AUDIO_CHANNEL_REPRESENTATION_INDEX: - return popcount(bits); - default: - return 0; - } -} - -/* Derive an output channel mask for position assignment from a channel count. - * This is to be used when the content channel mask is unknown. The 1, 2, 4, 5, 6, 7 and 8 channel - * cases are mapped to the standard game/home-theater layouts, but note that 4 is mapped to quad, - * and not stereo + FC + mono surround. A channel count of 3 is arbitrarily mapped to stereo + FC - * for continuity with stereo. - * Returns the matching channel mask, - * or AUDIO_CHANNEL_NONE if the channel count is zero, - * or AUDIO_CHANNEL_INVALID if the channel count exceeds that of the - * configurations for which a default output channel mask is defined. - */ -static inline audio_channel_mask_t audio_channel_out_mask_from_count(uint32_t channel_count) -{ - uint32_t bits; - switch (channel_count) { - case 0: - return AUDIO_CHANNEL_NONE; - case 1: - bits = AUDIO_CHANNEL_OUT_MONO; - break; - case 2: - bits = AUDIO_CHANNEL_OUT_STEREO; - break; - case 3: - bits = AUDIO_CHANNEL_OUT_STEREO | AUDIO_CHANNEL_OUT_FRONT_CENTER; - break; - case 4: // 4.0 - bits = AUDIO_CHANNEL_OUT_QUAD; - break; - case 5: // 5.0 - bits = AUDIO_CHANNEL_OUT_QUAD | AUDIO_CHANNEL_OUT_FRONT_CENTER; - break; - case 6: // 5.1 - bits = AUDIO_CHANNEL_OUT_5POINT1; - break; - case 7: // 6.1 - bits = AUDIO_CHANNEL_OUT_5POINT1 | AUDIO_CHANNEL_OUT_BACK_CENTER; - break; - case 8: - bits = AUDIO_CHANNEL_OUT_7POINT1; - break; - default: - return AUDIO_CHANNEL_INVALID; - } - return audio_channel_mask_from_representation_and_bits( - AUDIO_CHANNEL_REPRESENTATION_POSITION, bits); -} - -/* Derive an input channel mask for position assignment from a channel count. - * Currently handles only mono and stereo. - * Returns the matching channel mask, - * or AUDIO_CHANNEL_NONE if the channel count is zero, - * or AUDIO_CHANNEL_INVALID if the channel count exceeds that of the - * configurations for which a default input channel mask is defined. - */ -static inline audio_channel_mask_t audio_channel_in_mask_from_count(uint32_t channel_count) -{ - uint32_t bits; - switch (channel_count) { - case 0: - return AUDIO_CHANNEL_NONE; - case 1: - bits = AUDIO_CHANNEL_IN_MONO; - break; - case 2: - bits = AUDIO_CHANNEL_IN_STEREO; - break; - default: - return AUDIO_CHANNEL_INVALID; - } - return audio_channel_mask_from_representation_and_bits( - AUDIO_CHANNEL_REPRESENTATION_POSITION, bits); -} - -/* Derive a channel mask for index assignment from a channel count. - * Returns the matching channel mask, - * or AUDIO_CHANNEL_NONE if the channel count is zero, - * or AUDIO_CHANNEL_INVALID if the channel count exceeds AUDIO_CHANNEL_COUNT_MAX. - */ -static inline audio_channel_mask_t audio_channel_mask_for_index_assignment_from_count( - uint32_t channel_count) -{ - if (channel_count == 0) { - return AUDIO_CHANNEL_NONE; - } - if (channel_count > AUDIO_CHANNEL_COUNT_MAX) { - return AUDIO_CHANNEL_INVALID; - } - uint32_t bits = (1 << channel_count) - 1; - return audio_channel_mask_from_representation_and_bits( - AUDIO_CHANNEL_REPRESENTATION_INDEX, bits); -} - -static inline bool audio_is_valid_format(audio_format_t format) -{ - switch (format & AUDIO_FORMAT_MAIN_MASK) { - case AUDIO_FORMAT_PCM: - switch (format) { - case AUDIO_FORMAT_PCM_16_BIT: - case AUDIO_FORMAT_PCM_8_BIT: - case AUDIO_FORMAT_PCM_32_BIT: - case AUDIO_FORMAT_PCM_8_24_BIT: - case AUDIO_FORMAT_PCM_FLOAT: - case AUDIO_FORMAT_PCM_24_BIT_PACKED: - return true; - default: - return false; - } - /* not reached */ - case AUDIO_FORMAT_MP3: - case AUDIO_FORMAT_AMR_NB: - case AUDIO_FORMAT_AMR_WB: - case AUDIO_FORMAT_AAC: - case AUDIO_FORMAT_HE_AAC_V1: - case AUDIO_FORMAT_HE_AAC_V2: - case AUDIO_FORMAT_VORBIS: - case AUDIO_FORMAT_OPUS: - case AUDIO_FORMAT_AC3: - case AUDIO_FORMAT_E_AC3: - return true; - default: - return false; - } -} - -static inline bool audio_is_linear_pcm(audio_format_t format) -{ - return ((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM); -} - -static inline size_t audio_bytes_per_sample(audio_format_t format) -{ - size_t size = 0; - - switch (format) { - case AUDIO_FORMAT_PCM_32_BIT: - case AUDIO_FORMAT_PCM_8_24_BIT: - size = sizeof(int32_t); - break; - case AUDIO_FORMAT_PCM_24_BIT_PACKED: - size = sizeof(uint8_t) * 3; - break; - case AUDIO_FORMAT_PCM_16_BIT: - size = sizeof(int16_t); - break; - case AUDIO_FORMAT_PCM_8_BIT: - size = sizeof(uint8_t); - break; - case AUDIO_FORMAT_PCM_FLOAT: - size = sizeof(float); - break; - default: - break; - } - return size; -} - -/* converts device address to string sent to audio HAL via set_parameters */ -static char *audio_device_address_to_parameter(audio_devices_t device, const char *address) -{ - const size_t kSize = AUDIO_DEVICE_MAX_ADDRESS_LEN + sizeof("a2dp_sink_address="); - char param[kSize]; - - if (device & AUDIO_DEVICE_OUT_ALL_A2DP) - snprintf(param, kSize, "%s=%s", "a2dp_sink_address", address); - else if (device & AUDIO_DEVICE_OUT_REMOTE_SUBMIX) - snprintf(param, kSize, "%s=%s", "mix", address); - else - snprintf(param, kSize, "%s", address); - - return strdup(param); -} - - -__END_DECLS - -#endif // ANDROID_AUDIO_CORE_H diff --git a/include/system/audio_policy.h b/include/system/audio_policy.h deleted file mode 100644 index 2881104..0000000 --- a/include/system/audio_policy.h +++ /dev/null @@ -1,103 +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. - */ - - -#ifndef ANDROID_AUDIO_POLICY_CORE_H -#define ANDROID_AUDIO_POLICY_CORE_H - -#include <stdint.h> -#include <sys/cdefs.h> -#include <sys/types.h> - -#include <cutils/bitops.h> - -__BEGIN_DECLS - -/* The enums were moved here mostly from - * frameworks/base/include/media/AudioSystem.h - */ - -/* device categories used for audio_policy->set_force_use() */ -typedef enum { - AUDIO_POLICY_FORCE_NONE, - AUDIO_POLICY_FORCE_SPEAKER, - AUDIO_POLICY_FORCE_HEADPHONES, - AUDIO_POLICY_FORCE_BT_SCO, - AUDIO_POLICY_FORCE_BT_A2DP, - AUDIO_POLICY_FORCE_WIRED_ACCESSORY, - AUDIO_POLICY_FORCE_BT_CAR_DOCK, - AUDIO_POLICY_FORCE_BT_DESK_DOCK, - AUDIO_POLICY_FORCE_ANALOG_DOCK, - AUDIO_POLICY_FORCE_DIGITAL_DOCK, - AUDIO_POLICY_FORCE_NO_BT_A2DP, /* A2DP sink is not preferred to speaker or wired HS */ - AUDIO_POLICY_FORCE_SYSTEM_ENFORCED, - AUDIO_POLICY_FORCE_HDMI_SYSTEM_AUDIO_ENFORCED, - - AUDIO_POLICY_FORCE_CFG_CNT, - AUDIO_POLICY_FORCE_CFG_MAX = AUDIO_POLICY_FORCE_CFG_CNT - 1, - - AUDIO_POLICY_FORCE_DEFAULT = AUDIO_POLICY_FORCE_NONE, -} audio_policy_forced_cfg_t; - -/* usages used for audio_policy->set_force_use() */ -typedef enum { - AUDIO_POLICY_FORCE_FOR_COMMUNICATION, - AUDIO_POLICY_FORCE_FOR_MEDIA, - AUDIO_POLICY_FORCE_FOR_RECORD, - AUDIO_POLICY_FORCE_FOR_DOCK, - AUDIO_POLICY_FORCE_FOR_SYSTEM, - AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO, - - AUDIO_POLICY_FORCE_USE_CNT, - AUDIO_POLICY_FORCE_USE_MAX = AUDIO_POLICY_FORCE_USE_CNT - 1, -} audio_policy_force_use_t; - -/* device connection states used for audio_policy->set_device_connection_state() - */ -typedef enum { - AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE, - AUDIO_POLICY_DEVICE_STATE_AVAILABLE, - - AUDIO_POLICY_DEVICE_STATE_CNT, - AUDIO_POLICY_DEVICE_STATE_MAX = AUDIO_POLICY_DEVICE_STATE_CNT - 1, -} audio_policy_dev_state_t; - -typedef enum { - /* Used to generate a tone to notify the user of a - * notification/alarm/ringtone while they are in a call. */ - AUDIO_POLICY_TONE_IN_CALL_NOTIFICATION = 0, - - AUDIO_POLICY_TONE_CNT, - AUDIO_POLICY_TONE_MAX = AUDIO_POLICY_TONE_CNT - 1, -} audio_policy_tone_t; - - -static inline bool audio_is_low_visibility(audio_stream_type_t stream) -{ - switch (stream) { - case AUDIO_STREAM_SYSTEM: - case AUDIO_STREAM_NOTIFICATION: - case AUDIO_STREAM_RING: - return true; - default: - return false; - } -} - - -__END_DECLS - -#endif // ANDROID_AUDIO_POLICY_CORE_H diff --git a/include/system/camera.h b/include/system/camera.h index 7a4dd53..09c915d 100644 --- a/include/system/camera.h +++ b/include/system/camera.h @@ -194,7 +194,12 @@ enum { /** The facing of the camera is opposite to that of the screen. */ CAMERA_FACING_BACK = 0, /** The facing of the camera is the same as that of the screen. */ - CAMERA_FACING_FRONT = 1 + CAMERA_FACING_FRONT = 1, + /** + * The facing of the camera is not fixed relative to the screen. + * The cameras with this facing are external cameras, e.g. USB cameras. + */ + CAMERA_FACING_EXTERNAL = 2 }; enum { diff --git a/include/system/graphics.h b/include/system/graphics.h index efd48cb..c0f03fa 100644 --- a/include/system/graphics.h +++ b/include/system/graphics.h @@ -58,11 +58,6 @@ enum { HAL_PIXEL_FORMAT_RGB_565 = 4, HAL_PIXEL_FORMAT_BGRA_8888 = 5, - // Deprecated sRGB formats for source code compatibility - // Not for use in new code - HAL_PIXEL_FORMAT_sRGB_A_8888 = 0xC, - HAL_PIXEL_FORMAT_sRGB_X_8888 = 0xD, - /* * 0x100 - 0x1FF * @@ -194,9 +189,6 @@ enum { */ HAL_PIXEL_FORMAT_RAW16 = 0x20, - // Temporary alias for source code compatibility; do not use in new code - HAL_PIXEL_FORMAT_RAW_SENSOR = HAL_PIXEL_FORMAT_RAW16, - /* * Android RAW10 format: * @@ -252,6 +244,56 @@ enum { HAL_PIXEL_FORMAT_RAW10 = 0x25, /* + * Android RAW12 format: + * + * This format is exposed outside of camera HAL to applications. + * + * RAW12 is a single-channel, 12-bit per pixel, densely packed in each row, + * unprocessed format, usually representing raw Bayer-pattern images coming from + * an image sensor. + * + * In an image buffer with this format, starting from the first pixel of each + * row, each two consecutive pixels are packed into 3 bytes (24 bits). The first + * and second byte contains the top 8 bits of first and second pixel. The third + * byte contains the 4 least significant bits of the two pixels, the exact layout + * data for each two consecutive pixels is illustrated below (Pi[j] stands for + * the jth bit of the ith pixel): + * + * bit 7 bit 0 + * ======|======|======|======|======|======|======|======| + * Byte 0: |P0[11]|P0[10]|P0[ 9]|P0[ 8]|P0[ 7]|P0[ 6]|P0[ 5]|P0[ 4]| + * |------|------|------|------|------|------|------|------| + * Byte 1: |P1[11]|P1[10]|P1[ 9]|P1[ 8]|P1[ 7]|P1[ 6]|P1[ 5]|P1[ 4]| + * |------|------|------|------|------|------|------|------| + * Byte 2: |P1[ 3]|P1[ 2]|P1[ 1]|P1[ 0]|P0[ 3]|P0[ 2]|P0[ 1]|P0[ 0]| + * ======================================================= + * + * This format assumes: + * - a width multiple of 4 pixels + * - an even height + * - a vertical stride equal to the height + * - strides are specified in bytes, not in pixels + * + * size = stride * height + * + * When stride is equal to width * (12 / 8), there will be no padding bytes at + * the end of each row, the entire image data is densely packed. When stride is + * larger than width * (12 / 8), padding bytes will be present at the end of + * each row (including the last row). + * + * This format must be accepted by the gralloc module when used with the + * following usage flags: + * - GRALLOC_USAGE_HW_CAMERA_* + * - GRALLOC_USAGE_SW_* + * - GRALLOC_USAGE_RENDERSCRIPT + * + * When used with ANativeWindow, the dataSpace field should be + * HAL_DATASPACE_ARBITRARY, as raw image sensor buffers require substantial + * extra metadata to define. + */ + HAL_PIXEL_FORMAT_RAW12 = 0x26, + + /* * Android opaque RAW format: * * This format is exposed outside of the camera HAL to applications. diff --git a/include/system/radio.h b/include/system/radio.h new file mode 100644 index 0000000..a088526 --- /dev/null +++ b/include/system/radio.h @@ -0,0 +1,247 @@ +/* + * 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_H +#define ANDROID_RADIO_H + +#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> +#include <sys/cdefs.h> +#include <sys/types.h> + + +#define RADIO_NUM_BANDS_MAX 16 +#define RADIO_NUM_SPACINGS_MAX 16 +#define RADIO_STRING_LEN_MAX 128 + +/* + * Radio hardware module class. A given radio hardware module HAL is of one class + * only. The platform can not have more than one hardware module of each class. + * Current version of the framework only supports RADIO_CLASS_AM_FM. + */ +typedef enum { + RADIO_CLASS_AM_FM = 0, /* FM (including HD radio) and AM */ + RADIO_CLASS_SAT = 1, /* Satellite Radio */ + RADIO_CLASS_DT = 2, /* Digital Radio (DAB) */ +} radio_class_t; + +/* value for field "type" of radio band described in struct radio_hal_band_config */ +typedef enum { + RADIO_BAND_AM = 0, /* Amplitude Modulation band: LW, MW, SW */ + RADIO_BAND_FM = 1, /* Frequency Modulation band: FM */ + RADIO_BAND_FM_HD = 2, /* FM HD Radio / DRM (IBOC) */ + RADIO_BAND_AM_HD = 3, /* AM HD Radio / DRM (IBOC) */ +} radio_band_t; + +/* RDS variant implemented. A struct radio_hal_fm_band_config can list none or several. */ +enum { + RADIO_RDS_NONE = 0x0, + RADIO_RDS_WORLD = 0x01, + RADIO_RDS_US = 0x02, +}; +typedef unsigned int radio_rds_t; + +/* FM deemphasis variant implemented. A struct radio_hal_fm_band_config can list one or more. */ +enum { + RADIO_DEEMPHASIS_50 = 0x1, + RADIO_DEEMPHASIS_75 = 0x2, +}; +typedef unsigned int radio_deemphasis_t; + +/* Region a particular radio band configuration corresponds to. Not used at the HAL. + * Derived by the framework when converting the band descriptors retrieved from the HAL to + * individual band descriptors for each supported region. */ +typedef enum { + RADIO_REGION_NONE = -1, + RADIO_REGION_ITU_1 = 0, + RADIO_REGION_ITU_2 = 1, + RADIO_REGION_OIRT = 2, + RADIO_REGION_JAPAN = 3, + RADIO_REGION_KOREA = 4, +} radio_region_t; + +/* scanning direction for scan() and step() tuner APIs */ +typedef enum { + RADIO_DIRECTION_UP, + RADIO_DIRECTION_DOWN +} radio_direction_t; + +/* unique handle allocated to a radio module */ +typedef unsigned int radio_handle_t; + +/* Opaque meta data structure used by radio meta data API (see system/radio_metadata.h) */ +typedef struct radio_medtadata radio_metadata_t; + + +/* Additional attributes for an FM band configuration */ +typedef struct radio_hal_fm_band_config { + radio_deemphasis_t deemphasis; /* deemphasis variant */ + bool stereo; /* stereo supported */ + radio_rds_t rds; /* RDS variants supported */ + bool ta; /* Traffic Announcement supported */ + bool af; /* Alternate Frequency supported */ +} radio_hal_fm_band_config_t; + +/* Additional attributes for an AM band configuration */ +typedef struct radio_hal_am_band_config { + bool stereo; /* stereo supported */ +} radio_hal_am_band_config_t; + +/* Radio band configuration. Describes a given band supported by the radio module. + * The HAL can expose only one band per type with the the maximum range supported and all options. + * THe framework will derive the actual regions were this module can operate and expose separate + * band configurations for applications to chose from. */ +typedef struct radio_hal_band_config { + radio_band_t type; + bool antenna_connected; + unsigned int lower_limit; + unsigned int upper_limit; + unsigned int num_spacings; + unsigned int spacings[RADIO_NUM_SPACINGS_MAX]; + union { + radio_hal_fm_band_config_t fm; + radio_hal_am_band_config_t am; + }; +} radio_hal_band_config_t; + +/* Used internally by the framework to represent a band for s specific region */ +typedef struct radio_band_config { + radio_region_t region; + radio_hal_band_config_t band; +} radio_band_config_t; + + +/* Exposes properties of a given hardware radio module. + * NOTE: current framework implementation supports only one audio source (num_audio_sources = 1). + * The source corresponds to AUDIO_DEVICE_IN_FM_TUNER. + * If more than one tuner is supported (num_tuners > 1), only one can be connected to the audio + * source. */ +typedef struct radio_hal_properties { + radio_class_t class_id; /* Class of this module. E.g RADIO_CLASS_AM_FM */ + char implementor[RADIO_STRING_LEN_MAX]; /* implementor name */ + char product[RADIO_STRING_LEN_MAX]; /* product name */ + char version[RADIO_STRING_LEN_MAX]; /* product version */ + char serial[RADIO_STRING_LEN_MAX]; /* serial number (for subscription services) */ + unsigned int num_tuners; /* number of tuners controllable independently */ + unsigned int num_audio_sources; /* number of audio sources driven simultaneously */ + bool supports_capture; /* the hardware supports capture of audio source audio HAL */ + unsigned int num_bands; /* number of band descriptors */ + radio_hal_band_config_t bands[RADIO_NUM_BANDS_MAX]; /* band descriptors */ +} radio_hal_properties_t; + +/* Used internally by the framework. Same information as in struct radio_hal_properties plus a + * unique handle and one band configuration per region. */ +typedef struct radio_properties { + radio_handle_t handle; + radio_class_t class_id; + char implementor[RADIO_STRING_LEN_MAX]; + char product[RADIO_STRING_LEN_MAX]; + char version[RADIO_STRING_LEN_MAX]; + char serial[RADIO_STRING_LEN_MAX]; + unsigned int num_tuners; + unsigned int num_audio_sources; + bool supports_capture; + unsigned int num_bands; + radio_band_config_t bands[RADIO_NUM_BANDS_MAX]; +} radio_properties_t; + +/* Radio program information. Returned by the HAL with event RADIO_EVENT_TUNED. + * Contains information on currently tuned channel. + */ +typedef struct radio_program_info { + unsigned int channel; /* current channel. (e.g kHz for band type RADIO_BAND_FM) */ + unsigned int sub_channel; /* current sub channel. (used for RADIO_BAND_FM_HD) */ + bool tuned; /* tuned to a program or not */ + bool stereo; /* program is stereo or not */ + bool digital; /* digital program or not (e.g HD Radio program) */ + unsigned int signal_strength; /* signal strength from 0 to 100 */ + radio_metadata_t *metadata; /* non null if meta data are present (e.g PTY, song title ...) */ +} radio_program_info_t; + + +/* Events sent to the framework via the HAL callback. An event can notify the completion of an + * asynchronous command (configuration, tune, scan ...) or a spontaneous change (antenna connection, + * failure, AF switching, meta data reception... */ +enum { + RADIO_EVENT_HW_FAILURE = 0, /* hardware module failure. Requires reopening the tuner */ + RADIO_EVENT_CONFIG = 1, /* configuration change completed */ + RADIO_EVENT_ANTENNA = 2, /* Antenna connected, disconnected */ + RADIO_EVENT_TUNED = 3, /* tune, step, scan completed */ + RADIO_EVENT_METADATA = 4, /* New meta data received */ + RADIO_EVENT_TA = 5, /* Traffic announcement start or stop */ + RADIO_EVENT_AF_SWITCH = 6, /* Switch to Alternate Frequency */ + // begin framework only events + RADIO_EVENT_CONTROL = 100, /* loss/gain of tuner control */ + RADIO_EVENT_SERVER_DIED = 101, /* radio service died */ +}; +typedef unsigned int radio_event_type_t; + +/* Event passed to the framework by the HAL callback */ +typedef struct radio_hal_event { + radio_event_type_t type; /* event type */ + int status; /* used by RADIO_EVENT_CONFIG, RADIO_EVENT_TUNED */ + union { + bool on; /* RADIO_EVENT_ANTENNA, RADIO_EVENT_TA */ + radio_hal_band_config_t config; /* RADIO_EVENT_CONFIG */ + radio_program_info_t info; /* RADIO_EVENT_TUNED, RADIO_EVENT_AF_SWITCH */ + radio_metadata_t *metadata; /* RADIO_EVENT_METADATA */ + }; +} radio_hal_event_t; + +/* Used internally by the framework. Same information as in struct radio_hal_event */ +typedef struct radio_event { + radio_event_type_t type; + int status; + union { + bool on; + radio_band_config_t config; + radio_program_info_t info; + radio_metadata_t *metadata; /* offset from start of struct when in shared memory */ + }; +} radio_event_t; + + +static radio_rds_t radio_rds_for_region(bool rds, radio_region_t region) { + if (!rds) + return RADIO_RDS_NONE; + switch(region) { + case RADIO_REGION_ITU_1: + case RADIO_REGION_OIRT: + case RADIO_REGION_JAPAN: + case RADIO_REGION_KOREA: + return RADIO_RDS_WORLD; + case RADIO_REGION_ITU_2: + return RADIO_RDS_US; + default: + return RADIO_REGION_NONE; + } +} + +static radio_deemphasis_t radio_demephasis_for_region(radio_region_t region) { + switch(region) { + case RADIO_REGION_KOREA: + case RADIO_REGION_ITU_2: + return RADIO_DEEMPHASIS_75; + case RADIO_REGION_ITU_1: + case RADIO_REGION_OIRT: + case RADIO_REGION_JAPAN: + default: + return RADIO_DEEMPHASIS_50; + } +} + +#endif // ANDROID_RADIO_H diff --git a/include/system/sound_trigger.h b/include/system/sound_trigger.h deleted file mode 100644 index 773e4f7..0000000 --- a/include/system/sound_trigger.h +++ /dev/null @@ -1,223 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_SOUND_TRIGGER_H -#define ANDROID_SOUND_TRIGGER_H - -#include <stdbool.h> -#include <system/audio.h> - -#define SOUND_TRIGGER_MAX_STRING_LEN 64 /* max length of strings in properties or - descriptor structs */ -#define SOUND_TRIGGER_MAX_LOCALE_LEN 6 /* max length of locale string. e.g en_US */ -#define SOUND_TRIGGER_MAX_USERS 10 /* max number of concurrent users */ -#define SOUND_TRIGGER_MAX_PHRASES 10 /* max number of concurrent phrases */ - -typedef enum { - SOUND_TRIGGER_STATE_NO_INIT = -1, /* The sound trigger service is not initialized */ - SOUND_TRIGGER_STATE_ENABLED = 0, /* The sound trigger service is enabled */ - SOUND_TRIGGER_STATE_DISABLED = 1 /* The sound trigger service is disabled */ -} sound_trigger_service_state_t; - -#define RECOGNITION_MODE_VOICE_TRIGGER 0x1 /* simple voice trigger */ -#define RECOGNITION_MODE_USER_IDENTIFICATION 0x2 /* trigger only if one user in model identified */ -#define RECOGNITION_MODE_USER_AUTHENTICATION 0x4 /* trigger only if one user in mode - authenticated */ -#define RECOGNITION_STATUS_SUCCESS 0 -#define RECOGNITION_STATUS_ABORT 1 -#define RECOGNITION_STATUS_FAILURE 2 - -#define SOUND_MODEL_STATUS_UPDATED 0 - -typedef enum { - SOUND_MODEL_TYPE_UNKNOWN = -1, /* use for unspecified sound model type */ - SOUND_MODEL_TYPE_KEYPHRASE = 0 /* use for key phrase sound models */ -} sound_trigger_sound_model_type_t; - -typedef struct sound_trigger_uuid_s { - unsigned int timeLow; - unsigned short timeMid; - unsigned short timeHiAndVersion; - unsigned short clockSeq; - unsigned char node[6]; -} sound_trigger_uuid_t; - -/* - * sound trigger implementation descriptor read by the framework via get_properties(). - * Used by SoundTrigger service to report to applications and manage concurrency and policy. - */ -struct sound_trigger_properties { - char implementor[SOUND_TRIGGER_MAX_STRING_LEN]; /* implementor name */ - char description[SOUND_TRIGGER_MAX_STRING_LEN]; /* implementation description */ - unsigned int version; /* implementation version */ - sound_trigger_uuid_t uuid; /* unique implementation ID. - Must change with version each version */ - unsigned int max_sound_models; /* maximum number of concurrent sound models - loaded */ - unsigned int max_key_phrases; /* maximum number of key phrases */ - unsigned int max_users; /* maximum number of concurrent users detected */ - unsigned int recognition_modes; /* all supported modes. - e.g RECOGNITION_MODE_VOICE_TRIGGER */ - bool capture_transition; /* supports seamless transition from detection - to capture */ - unsigned int max_buffer_ms; /* maximum buffering capacity in ms if - capture_transition is true*/ - bool concurrent_capture; /* supports capture by other use cases while - detection is active */ - bool trigger_in_event; /* returns the trigger capture in event */ - unsigned int power_consumption_mw; /* Rated power consumption when detection is active - with TDB silence/sound/speech ratio */ -}; - -typedef int sound_trigger_module_handle_t; - -struct sound_trigger_module_descriptor { - sound_trigger_module_handle_t handle; - struct sound_trigger_properties properties; -}; - -typedef int sound_model_handle_t; - -/* - * Generic sound model descriptor. This struct is the header of a larger block passed to - * load_sound_model() and containing the binary data of the sound model. - * Proprietary representation of users in binary data must match information indicated - * by users field - */ -struct sound_trigger_sound_model { - sound_trigger_sound_model_type_t type; /* model type. e.g. SOUND_MODEL_TYPE_KEYPHRASE */ - sound_trigger_uuid_t uuid; /* unique sound model ID. */ - sound_trigger_uuid_t vendor_uuid; /* unique vendor ID. Identifies the engine the - sound model was build for */ - unsigned int data_size; /* size of opaque model data */ - unsigned int data_offset; /* offset of opaque data start from head of struct - (e.g sizeof struct sound_trigger_sound_model) */ -}; - -/* key phrase descriptor */ -struct sound_trigger_phrase { - unsigned int id; /* keyphrase ID */ - unsigned int recognition_mode; /* recognition modes supported by this key phrase */ - unsigned int num_users; /* number of users in the key phrase */ - unsigned int users[SOUND_TRIGGER_MAX_USERS]; /* users ids: (not uid_t but sound trigger - specific IDs */ - char locale[SOUND_TRIGGER_MAX_LOCALE_LEN]; /* locale - JAVA Locale style (e.g. en_US) */ - char text[SOUND_TRIGGER_MAX_STRING_LEN]; /* phrase text in UTF-8 format. */ -}; - -/* - * Specialized sound model for key phrase detection. - * Proprietary representation of key phrases in binary data must match information indicated - * by phrases field - */ -struct sound_trigger_phrase_sound_model { - struct sound_trigger_sound_model common; - unsigned int num_phrases; /* number of key phrases in model */ - struct sound_trigger_phrase phrases[SOUND_TRIGGER_MAX_PHRASES]; -}; - - -/* - * Generic recognition event sent via recognition callback - */ -struct sound_trigger_recognition_event { - int status; /* recognition status e.g. - RECOGNITION_STATUS_SUCCESS */ - sound_trigger_sound_model_type_t type; /* event type, same as sound model type. - e.g. SOUND_MODEL_TYPE_KEYPHRASE */ - sound_model_handle_t model; /* loaded sound model that triggered the - event */ - bool capture_available; /* it is possible to capture audio from this - utterance buffered by the - implementation */ - int capture_session; /* audio session ID. framework use */ - int capture_delay_ms; /* delay in ms between end of model - detection and start of audio available - for capture. A negative value is possible - (e.g. if key phrase is also available for - capture */ - int capture_preamble_ms; /* duration in ms of audio captured - before the start of the trigger. - 0 if none. */ - bool trigger_in_data; /* the opaque data is the capture of - the trigger sound */ - audio_config_t audio_config; /* audio format of either the trigger in - event data or to use for capture of the - rest of the utterance */ - unsigned int data_size; /* size of opaque event data */ - unsigned int data_offset; /* offset of opaque data start from start of - this struct (e.g sizeof struct - sound_trigger_phrase_recognition_event) */ -}; - -/* - * Confidence level for each user in struct sound_trigger_phrase_recognition_extra - */ -struct sound_trigger_confidence_level { - unsigned int user_id; /* user ID */ - unsigned int level; /* confidence level in percent (0 - 100). - - min level for recognition configuration - - detected level for recognition event */ -}; - -/* - * Specialized recognition event for key phrase detection - */ -struct sound_trigger_phrase_recognition_extra { - unsigned int id; /* keyphrase ID */ - unsigned int recognition_modes; /* recognition modes used for this keyphrase */ - unsigned int confidence_level; /* confidence level for mode RECOGNITION_MODE_VOICE_TRIGGER */ - unsigned int num_levels; /* number of user confidence levels */ - struct sound_trigger_confidence_level levels[SOUND_TRIGGER_MAX_USERS]; -}; - -struct sound_trigger_phrase_recognition_event { - struct sound_trigger_recognition_event common; - unsigned int num_phrases; - struct sound_trigger_phrase_recognition_extra phrase_extras[SOUND_TRIGGER_MAX_PHRASES]; -}; - -/* - * configuration for sound trigger capture session passed to start_recognition() - */ -struct sound_trigger_recognition_config { - audio_io_handle_t capture_handle; /* IO handle that will be used for capture. - N/A if capture_requested is false */ - audio_devices_t capture_device; /* input device requested for detection capture */ - bool capture_requested; /* capture and buffer audio for this recognition - instance */ - unsigned int num_phrases; /* number of key phrases recognition extras */ - struct sound_trigger_phrase_recognition_extra phrases[SOUND_TRIGGER_MAX_PHRASES]; - /* configuration for each key phrase */ - unsigned int data_size; /* size of opaque capture configuration data */ - unsigned int data_offset; /* offset of opaque data start from start of this struct - (e.g sizeof struct sound_trigger_recognition_config) */ -}; - -/* - * Event sent via load sound model callback - */ -struct sound_trigger_model_event { - int status; /* sound model status e.g. SOUND_MODEL_STATUS_UPDATED */ - sound_model_handle_t model; /* loaded sound model that triggered the event */ - unsigned int data_size; /* size of event data if any. Size of updated sound model if - status is SOUND_MODEL_STATUS_UPDATED */ - unsigned int data_offset; /* offset of data start from start of this struct - (e.g sizeof struct sound_trigger_model_event) */ -}; - - -#endif // ANDROID_SOUND_TRIGGER_H diff --git a/include/sysutils/NetlinkEvent.h b/include/sysutils/NetlinkEvent.h index 4fa49c5..b80f3ea 100644 --- a/include/sysutils/NetlinkEvent.h +++ b/include/sysutils/NetlinkEvent.h @@ -21,25 +21,29 @@ #define NL_PARAMS_MAX 32 class NetlinkEvent { +public: + enum class Action { + kUnknown = 0, + kAdd = 1, + kRemove = 2, + kChange = 3, + kLinkUp = 4, + kLinkDown = 5, + kAddressUpdated = 6, + kAddressRemoved = 7, + kRdnss = 8, + kRouteUpdated = 9, + kRouteRemoved = 10, + }; + +private: int mSeq; char *mPath; - int mAction; + Action mAction; char *mSubsystem; char *mParams[NL_PARAMS_MAX]; public: - const static int NlActionUnknown; - const static int NlActionAdd; - const static int NlActionRemove; - const static int NlActionChange; - const static int NlActionLinkDown; - const static int NlActionLinkUp; - const static int NlActionAddressUpdated; - const static int NlActionAddressRemoved; - const static int NlActionRdnss; - const static int NlActionRouteUpdated; - const static int NlActionRouteRemoved; - NetlinkEvent(); virtual ~NetlinkEvent(); @@ -47,7 +51,7 @@ public: const char *findParam(const char *paramName); const char *getSubsystem() { return mSubsystem; } - int getAction() { return mAction; } + Action getAction() { return mAction; } void dump(); diff --git a/include/utils/Looper.h b/include/utils/Looper.h index 15c9891..da2d5f2 100644 --- a/include/utils/Looper.h +++ b/include/utils/Looper.h @@ -386,11 +386,12 @@ public: void removeMessages(const sp<MessageHandler>& handler, int what); /** - * Return whether this looper's thread is currently idling -- that is, whether it - * stopped waiting for more work to do. Note that this is intrinsically racy, since - * its state can change before you get the result back. + * Returns whether this looper's thread is currently polling for more work to do. + * This is a good signal that the loop is still alive rather than being stuck + * handling a callback. Note that this method is intrinsically racy, since the + * state of the loop can change before you get the result back. */ - bool isIdling() const; + bool isPolling() const; /** * Prepares a looper associated with the calling thread, and returns it. @@ -419,8 +420,12 @@ private: struct Request { int fd; int ident; + int events; + int seq; sp<LooperCallback> callback; void* data; + + void initEventItem(struct epoll_event* eventItem) const; }; struct Response { @@ -442,8 +447,7 @@ private: const bool mAllowNonCallbacks; // immutable - int mWakeReadPipeFd; // immutable - int mWakeWritePipeFd; // immutable + int mWakeEventFd; // immutable Mutex mLock; Vector<MessageEnvelope> mMessageEnvelopes; // guarded by mLock @@ -451,12 +455,14 @@ private: // Whether we are currently waiting for work. Not protected by a lock, // any use of it is racy anyway. - volatile bool mIdling; + volatile bool mPolling; - int mEpollFd; // immutable + int mEpollFd; // guarded by mLock but only modified on the looper thread + bool mEpollRebuildRequired; // guarded by mLock // Locked list of file descriptor monitoring requests. KeyedVector<int, Request> mRequests; // guarded by mLock + int mNextRequestSeq; // This state is only used privately by pollOnce and does not require a lock since // it runs on a single thread. @@ -465,11 +471,15 @@ private: nsecs_t mNextMessageUptime; // set to LLONG_MAX when none int pollInner(int timeoutMillis); + int removeFd(int fd, int seq); void awoken(); void pushResponse(int events, const Request& request); + void rebuildEpollLocked(); + void scheduleEpollRebuildLocked(); static void initTLSKey(); static void threadDestructor(void *st); + static void initEpollEvent(struct epoll_event* eventItem); }; } // namespace android diff --git a/libion/ion.c b/libion/ion.c index 4908932..d1984bd 100644 --- a/libion/ion.c +++ b/libion/ion.c @@ -91,6 +91,7 @@ int ion_map(int fd, ion_user_handle_t handle, size_t length, int prot, int flags, off_t offset, unsigned char **ptr, int *map_fd) { int ret; + unsigned char *tmp_ptr; struct ion_fd_data data = { .handle = handle, }; @@ -103,16 +104,17 @@ int ion_map(int fd, ion_user_handle_t handle, size_t length, int prot, ret = ion_ioctl(fd, ION_IOC_MAP, &data); if (ret < 0) return ret; - *map_fd = data.fd; - if (*map_fd < 0) { + if (data.fd < 0) { ALOGE("map ioctl returned negative fd\n"); return -EINVAL; } - *ptr = mmap(NULL, length, prot, flags, *map_fd, offset); - if (*ptr == MAP_FAILED) { + tmp_ptr = mmap(NULL, length, prot, flags, data.fd, offset); + if (tmp_ptr == MAP_FAILED) { ALOGE("mmap failed: %s\n", strerror(errno)); return -errno; } + *map_fd = data.fd; + *ptr = tmp_ptr; return ret; } @@ -129,11 +131,11 @@ int ion_share(int fd, ion_user_handle_t handle, int *share_fd) ret = ion_ioctl(fd, ION_IOC_SHARE, &data); if (ret < 0) return ret; - *share_fd = data.fd; - if (*share_fd < 0) { + if (data.fd < 0) { ALOGE("share ioctl returned negative fd\n"); return -EINVAL; } + *share_fd = data.fd; return ret; } diff --git a/libnetutils/dhcp_utils.c b/libnetutils/dhcp_utils.c index 70e37c6..c6b9fe4 100644 --- a/libnetutils/dhcp_utils.c +++ b/libnetutils/dhcp_utils.c @@ -1,16 +1,16 @@ /* * Copyright 2008, 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 + * 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 + * 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 + * 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. */ @@ -33,7 +33,7 @@ static const char DHCP_CONFIG_PATH[] = "/system/etc/dhcpcd/dhcpcd.conf"; static const int NAP_TIME = 200; /* wait for 200ms at a time */ /* when polling for property values */ static const char DAEMON_NAME_RENEW[] = "iprenew"; -static char errmsg[100]; +static char errmsg[100] = "\0"; /* interface length for dhcpcd daemon start (dhcpcd_<interface> as defined in init.rc file) * or for filling up system properties dhcpcd.<interface>.ipaddress, dhcpcd.<interface>.dns1 * and other properties on a successful bind @@ -74,7 +74,7 @@ static int wait_for_property(const char *name, const char *desired_value, int ma while (maxnaps-- >= 0) { if (property_get(name, value, NULL)) { - if (desired_value == NULL || + if (desired_value == NULL || strcmp(value, desired_value) == 0) { return 0; } @@ -169,6 +169,47 @@ static int fill_ip_info(const char *interface, } /* + * Get any available DHCP results. + */ +int dhcp_get_results(const char *interface, + char *ipaddr, + char *gateway, + uint32_t *prefixLength, + char *dns[], + char *server, + uint32_t *lease, + char *vendorInfo, + char *domain, + char *mtu) +{ + char result_prop_name[PROPERTY_KEY_MAX]; + char prop_value[PROPERTY_VALUE_MAX]; + + /* Interface name after converting p2p0-p2p0-X to p2p to reuse system properties */ + char p2p_interface[MAX_INTERFACE_LENGTH]; + get_p2p_interface_replacement(interface, p2p_interface); + snprintf(result_prop_name, sizeof(result_prop_name), "%s.%s.result", + DHCP_PROP_NAME_PREFIX, + p2p_interface); + + memset(prop_value, '\0', PROPERTY_VALUE_MAX); + if (!property_get(result_prop_name, prop_value, NULL)) { + snprintf(errmsg, sizeof(errmsg), "%s", "DHCP result property was not set"); + return -1; + } + if (strcmp(prop_value, "ok") == 0) { + if (fill_ip_info(interface, ipaddr, gateway, prefixLength, dns, + server, lease, vendorInfo, domain, mtu) == -1) { + return -1; + } + return 0; + } else { + snprintf(errmsg, sizeof(errmsg), "DHCP result was %s", prop_value); + return -1; + } +} + +/* * Start the dhcp client daemon, and wait for it to finish * configuring the interface. * @@ -177,16 +218,7 @@ static int fill_ip_info(const char *interface, * Example: * service dhcpcd_<interface> /system/bin/dhcpcd -ABKL -f dhcpcd.conf */ -int dhcp_do_request(const char *interface, - char *ipaddr, - char *gateway, - uint32_t *prefixLength, - char *dns[], - char *server, - uint32_t *lease, - char *vendorInfo, - char *domain, - char *mtu) +int dhcp_start(const char *interface) { char result_prop_name[PROPERTY_KEY_MAX]; char daemon_prop_name[PROPERTY_KEY_MAX]; @@ -230,21 +262,7 @@ int dhcp_do_request(const char *interface, return -1; } - if (!property_get(result_prop_name, prop_value, NULL)) { - /* shouldn't ever happen, given the success of wait_for_property() */ - snprintf(errmsg, sizeof(errmsg), "%s", "DHCP result property was not set"); - return -1; - } - if (strcmp(prop_value, "ok") == 0) { - if (fill_ip_info(interface, ipaddr, gateway, prefixLength, dns, - server, lease, vendorInfo, domain, mtu) == -1) { - return -1; - } - return 0; - } else { - snprintf(errmsg, sizeof(errmsg), "DHCP result was %s", prop_value); - return -1; - } + return 0; } /** @@ -320,16 +338,7 @@ char *dhcp_get_errmsg() { * service iprenew_<interface> /system/bin/dhcpcd -n * */ -int dhcp_do_request_renew(const char *interface, - char *ipaddr, - char *gateway, - uint32_t *prefixLength, - char *dns[], - char *server, - uint32_t *lease, - char *vendorInfo, - char *domain, - char *mtu) +int dhcp_start_renew(const char *interface) { char result_prop_name[PROPERTY_KEY_MAX]; char prop_value[PROPERTY_VALUE_MAX] = {'\0'}; @@ -359,16 +368,5 @@ int dhcp_do_request_renew(const char *interface, return -1; } - if (!property_get(result_prop_name, prop_value, NULL)) { - /* shouldn't ever happen, given the success of wait_for_property() */ - snprintf(errmsg, sizeof(errmsg), "%s", "DHCP Renew result property was not set"); - return -1; - } - if (strcmp(prop_value, "ok") == 0) { - return fill_ip_info(interface, ipaddr, gateway, prefixLength, dns, - server, lease, vendorInfo, domain, mtu); - } else { - snprintf(errmsg, sizeof(errmsg), "DHCP Renew result was %s", prop_value); - return -1; - } + return 0; } diff --git a/libsysutils/src/NetlinkEvent.cpp b/libsysutils/src/NetlinkEvent.cpp index 909df86..ef30017 100644 --- a/libsysutils/src/NetlinkEvent.cpp +++ b/libsysutils/src/NetlinkEvent.cpp @@ -47,20 +47,8 @@ const int LOCAL_NFLOG_PACKET = NFNL_SUBSYS_ULOG << 8 | NFULNL_MSG_PACKET; #include <netlink/handlers.h> #include <netlink/msg.h> -const int NetlinkEvent::NlActionUnknown = 0; -const int NetlinkEvent::NlActionAdd = 1; -const int NetlinkEvent::NlActionRemove = 2; -const int NetlinkEvent::NlActionChange = 3; -const int NetlinkEvent::NlActionLinkUp = 4; -const int NetlinkEvent::NlActionLinkDown = 5; -const int NetlinkEvent::NlActionAddressUpdated = 6; -const int NetlinkEvent::NlActionAddressRemoved = 7; -const int NetlinkEvent::NlActionRdnss = 8; -const int NetlinkEvent::NlActionRouteUpdated = 9; -const int NetlinkEvent::NlActionRouteRemoved = 10; - NetlinkEvent::NetlinkEvent() { - mAction = NlActionUnknown; + mAction = Action::kUnknown; memset(mParams, 0, sizeof(mParams)); mPath = NULL; mSubsystem = NULL; @@ -154,8 +142,8 @@ bool NetlinkEvent::parseIfInfoMessage(const struct nlmsghdr *nh) { switch(rta->rta_type) { case IFLA_IFNAME: asprintf(&mParams[0], "INTERFACE=%s", (char *) RTA_DATA(rta)); - mAction = (ifi->ifi_flags & IFF_LOWER_UP) ? NlActionLinkUp : - NlActionLinkDown; + mAction = (ifi->ifi_flags & IFF_LOWER_UP) ? Action::kLinkUp : + Action::kLinkDown; mSubsystem = strdup("net"); return true; } @@ -244,8 +232,8 @@ bool NetlinkEvent::parseIfAddrMessage(const struct nlmsghdr *nh) { } // Fill in netlink event information. - mAction = (type == RTM_NEWADDR) ? NlActionAddressUpdated : - NlActionAddressRemoved; + mAction = (type == RTM_NEWADDR) ? Action::kAddressUpdated : + Action::kAddressRemoved; mSubsystem = strdup("net"); asprintf(&mParams[0], "ADDRESS=%s/%d", addrstr, ifaddr->ifa_prefixlen); @@ -276,7 +264,7 @@ bool NetlinkEvent::parseUlogPacketMessage(const struct nlmsghdr *nh) { asprintf(&mParams[0], "ALERT_NAME=%s", pm->prefix); asprintf(&mParams[1], "INTERFACE=%s", devname); mSubsystem = strdup("qlog"); - mAction = NlActionChange; + mAction = Action::kChange; return true; } @@ -311,7 +299,7 @@ bool NetlinkEvent::parseNfPacketMessage(struct nlmsghdr *nh) { asprintf(&mParams[0], "UID=%d", uid); mParams[1] = hex; mSubsystem = strdup("strict"); - mAction = NlActionChange; + mAction = Action::kChange; return true; } @@ -397,8 +385,8 @@ bool NetlinkEvent::parseRtMessage(const struct nlmsghdr *nh) { return false; // Fill in netlink event information. - mAction = (type == RTM_NEWROUTE) ? NlActionRouteUpdated : - NlActionRouteRemoved; + mAction = (type == RTM_NEWROUTE) ? Action::kRouteUpdated : + Action::kRouteRemoved; mSubsystem = strdup("net"); asprintf(&mParams[0], "ROUTE=%s/%d", dst, prefixLength); asprintf(&mParams[1], "GATEWAY=%s", (*gw) ? gw : ""); @@ -497,7 +485,7 @@ bool NetlinkEvent::parseNdUserOptMessage(const struct nlmsghdr *nh) { } buf[pos] = '\0'; - mAction = NlActionRdnss; + mAction = Action::kRdnss; mSubsystem = strdup("net"); asprintf(&mParams[0], "INTERFACE=%s", ifname); asprintf(&mParams[1], "LIFETIME=%u", lifetime); @@ -617,11 +605,11 @@ bool NetlinkEvent::parseAsciiNetlinkMessage(char *buffer, int size) { const char* a; if ((a = HAS_CONST_PREFIX(s, end, "ACTION=")) != NULL) { if (!strcmp(a, "add")) - mAction = NlActionAdd; + mAction = Action::kAdd; else if (!strcmp(a, "remove")) - mAction = NlActionRemove; + mAction = Action::kRemove; else if (!strcmp(a, "change")) - mAction = NlActionChange; + mAction = Action::kChange; } else if ((a = HAS_CONST_PREFIX(s, end, "SEQNUM=")) != NULL) { mSeq = atoi(a); } else if ((a = HAS_CONST_PREFIX(s, end, "SUBSYSTEM=")) != NULL) { diff --git a/libsysutils/src/SocketListener.cpp b/libsysutils/src/SocketListener.cpp index 527a6a0..3011ed7 100644 --- a/libsysutils/src/SocketListener.cpp +++ b/libsysutils/src/SocketListener.cpp @@ -86,6 +86,7 @@ int SocketListener::startListener(int backlog) { return -1; } SLOGV("got mSock = %d for %s", mSock, mSocketName); + fcntl(mSock, F_SETFD, FD_CLOEXEC); } if (mListen && listen(mSock, backlog) < 0) { @@ -212,6 +213,7 @@ void SocketListener::runListener() { sleep(1); continue; } + fcntl(c, F_SETFD, FD_CLOEXEC); pthread_mutex_lock(&mClientsLock); mClients->push_back(new SocketClient(c, true, mUseCmdNum)); pthread_mutex_unlock(&mClientsLock); diff --git a/libutils/Looper.cpp b/libutils/Looper.cpp index 9a2dd6c..e69784d 100644 --- a/libutils/Looper.cpp +++ b/libutils/Looper.cpp @@ -20,6 +20,8 @@ #include <unistd.h> #include <fcntl.h> #include <limits.h> +#include <inttypes.h> +#include <sys/eventfd.h> namespace android { @@ -68,41 +70,20 @@ static pthread_key_t gTLSKey = 0; Looper::Looper(bool allowNonCallbacks) : mAllowNonCallbacks(allowNonCallbacks), mSendingMessage(false), - mResponseIndex(0), mNextMessageUptime(LLONG_MAX) { - int wakeFds[2]; - int result = pipe(wakeFds); - LOG_ALWAYS_FATAL_IF(result != 0, "Could not create wake pipe. errno=%d", errno); + mPolling(false), mEpollFd(-1), mEpollRebuildRequired(false), + mNextRequestSeq(0), mResponseIndex(0), mNextMessageUptime(LLONG_MAX) { + mWakeEventFd = eventfd(0, EFD_NONBLOCK); + LOG_ALWAYS_FATAL_IF(mWakeEventFd < 0, "Could not make wake event fd. errno=%d", errno); - mWakeReadPipeFd = wakeFds[0]; - mWakeWritePipeFd = wakeFds[1]; - - result = fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK); - LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake read pipe non-blocking. errno=%d", - errno); - - result = fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK); - LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake write pipe non-blocking. errno=%d", - errno); - - mIdling = false; - - // Allocate the epoll instance and register the wake pipe. - mEpollFd = epoll_create(EPOLL_SIZE_HINT); - LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance. errno=%d", errno); - - struct epoll_event eventItem; - memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union - eventItem.events = EPOLLIN; - eventItem.data.fd = mWakeReadPipeFd; - result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, & eventItem); - LOG_ALWAYS_FATAL_IF(result != 0, "Could not add wake read pipe to epoll instance. errno=%d", - errno); + AutoMutex _l(mLock); + rebuildEpollLocked(); } Looper::~Looper() { - close(mWakeReadPipeFd); - close(mWakeWritePipeFd); - close(mEpollFd); + close(mWakeEventFd); + if (mEpollFd >= 0) { + close(mEpollFd); + } } void Looper::initTLSKey() { @@ -156,6 +137,50 @@ bool Looper::getAllowNonCallbacks() const { return mAllowNonCallbacks; } +void Looper::rebuildEpollLocked() { + // Close old epoll instance if we have one. + if (mEpollFd >= 0) { +#if DEBUG_CALLBACKS + ALOGD("%p ~ rebuildEpollLocked - rebuilding epoll set", this); +#endif + close(mEpollFd); + } + + // Allocate the new epoll instance and register the wake pipe. + mEpollFd = epoll_create(EPOLL_SIZE_HINT); + LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance. errno=%d", errno); + + struct epoll_event eventItem; + memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union + eventItem.events = EPOLLIN; + eventItem.data.fd = mWakeEventFd; + int result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeEventFd, & eventItem); + LOG_ALWAYS_FATAL_IF(result != 0, "Could not add wake event fd to epoll instance. errno=%d", + errno); + + for (size_t i = 0; i < mRequests.size(); i++) { + const Request& request = mRequests.valueAt(i); + struct epoll_event eventItem; + request.initEventItem(&eventItem); + + int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, request.fd, & eventItem); + if (epollResult < 0) { + ALOGE("Error adding epoll events for fd %d while rebuilding epoll set, errno=%d", + request.fd, errno); + } + } +} + +void Looper::scheduleEpollRebuildLocked() { + if (!mEpollRebuildRequired) { +#if DEBUG_CALLBACKS + ALOGD("%p ~ scheduleEpollRebuildLocked - scheduling epoll set rebuild", this); +#endif + mEpollRebuildRequired = true; + wake(); + } +} + int Looper::pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData) { int result = 0; for (;;) { @@ -206,7 +231,7 @@ int Looper::pollInner(int timeoutMillis) { timeoutMillis = messageTimeoutMillis; } #if DEBUG_POLL_AND_WAKE - ALOGD("%p ~ pollOnce - next message in %lldns, adjusted timeout: timeoutMillis=%d", + ALOGD("%p ~ pollOnce - next message in %" PRId64 "ns, adjusted timeout: timeoutMillis=%d", this, mNextMessageUptime - now, timeoutMillis); #endif } @@ -217,17 +242,24 @@ int Looper::pollInner(int timeoutMillis) { mResponseIndex = 0; // We are about to idle. - mIdling = true; + mPolling = true; struct epoll_event eventItems[EPOLL_MAX_EVENTS]; int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis); // No longer idling. - mIdling = false; + mPolling = false; // Acquire lock. mLock.lock(); + // Rebuild epoll set if needed. + if (mEpollRebuildRequired) { + mEpollRebuildRequired = false; + rebuildEpollLocked(); + goto Done; + } + // Check for poll error. if (eventCount < 0) { if (errno == EINTR) { @@ -255,11 +287,11 @@ int Looper::pollInner(int timeoutMillis) { for (int i = 0; i < eventCount; i++) { int fd = eventItems[i].data.fd; uint32_t epollEvents = eventItems[i].events; - if (fd == mWakeReadPipeFd) { + if (fd == mWakeEventFd) { if (epollEvents & EPOLLIN) { awoken(); } else { - ALOGW("Ignoring unexpected epoll events 0x%x on wake read pipe.", epollEvents); + ALOGW("Ignoring unexpected epoll events 0x%x on wake event fd.", epollEvents); } } else { ssize_t requestIndex = mRequests.indexOfKey(fd); @@ -326,10 +358,14 @@ Done: ; ALOGD("%p ~ pollOnce - invoking fd event callback %p: fd=%d, events=0x%x, data=%p", this, response.request.callback.get(), fd, events, data); #endif + // Invoke the callback. Note that the file descriptor may be closed by + // the callback (and potentially even reused) before the function returns so + // we need to be a little careful when removing the file descriptor afterwards. int callbackResult = response.request.callback->handleEvent(fd, events, data); if (callbackResult == 0) { - removeFd(fd); + removeFd(fd, response.request.seq); } + // Clear the callback reference in the response structure promptly because we // will not clear the response vector itself until the next poll. response.request.callback.clear(); @@ -370,12 +406,9 @@ void Looper::wake() { ALOGD("%p ~ wake", this); #endif - ssize_t nWrite; - do { - nWrite = write(mWakeWritePipeFd, "W", 1); - } while (nWrite == -1 && errno == EINTR); - - if (nWrite != 1) { + uint64_t inc = 1; + ssize_t nWrite = TEMP_FAILURE_RETRY(write(mWakeEventFd, &inc, sizeof(uint64_t))); + if (nWrite != sizeof(uint64_t)) { if (errno != EAGAIN) { ALOGW("Could not write wake signal, errno=%d", errno); } @@ -387,11 +420,8 @@ void Looper::awoken() { ALOGD("%p ~ awoken", this); #endif - char buffer[16]; - ssize_t nRead; - do { - nRead = read(mWakeReadPipeFd, buffer, sizeof(buffer)); - } while ((nRead == -1 && errno == EINTR) || nRead == sizeof(buffer)); + uint64_t counter; + TEMP_FAILURE_RETRY(read(mWakeEventFd, &counter, sizeof(uint64_t))); } void Looper::pushResponse(int events, const Request& request) { @@ -425,23 +455,20 @@ int Looper::addFd(int fd, int ident, int events, const sp<LooperCallback>& callb ident = POLL_CALLBACK; } - int epollEvents = 0; - if (events & EVENT_INPUT) epollEvents |= EPOLLIN; - if (events & EVENT_OUTPUT) epollEvents |= EPOLLOUT; - { // acquire lock AutoMutex _l(mLock); Request request; request.fd = fd; request.ident = ident; + request.events = events; + request.seq = mNextRequestSeq++; request.callback = callback; request.data = data; + if (mNextRequestSeq == -1) mNextRequestSeq = 0; // reserve sequence number -1 struct epoll_event eventItem; - memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union - eventItem.events = epollEvents; - eventItem.data.fd = fd; + request.initEventItem(&eventItem); ssize_t requestIndex = mRequests.indexOfKey(fd); if (requestIndex < 0) { @@ -454,8 +481,36 @@ int Looper::addFd(int fd, int ident, int events, const sp<LooperCallback>& callb } else { int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_MOD, fd, & eventItem); if (epollResult < 0) { - ALOGE("Error modifying epoll events for fd %d, errno=%d", fd, errno); - return -1; + if (errno == ENOENT) { + // Tolerate ENOENT because it means that an older file descriptor was + // closed before its callback was unregistered and meanwhile a new + // file descriptor with the same number has been created and is now + // being registered for the first time. This error may occur naturally + // when a callback has the side-effect of closing the file descriptor + // before returning and unregistering itself. Callback sequence number + // checks further ensure that the race is benign. + // + // Unfortunately due to kernel limitations we need to rebuild the epoll + // set from scratch because it may contain an old file handle that we are + // now unable to remove since its file descriptor is no longer valid. + // No such problem would have occurred if we were using the poll system + // call instead, but that approach carries others disadvantages. +#if DEBUG_CALLBACKS + ALOGD("%p ~ addFd - EPOLL_CTL_MOD failed due to file descriptor " + "being recycled, falling back on EPOLL_CTL_ADD, errno=%d", + this, errno); +#endif + epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, & eventItem); + if (epollResult < 0) { + ALOGE("Error modifying or adding epoll events for fd %d, errno=%d", + fd, errno); + return -1; + } + scheduleEpollRebuildLocked(); + } else { + ALOGE("Error modifying epoll events for fd %d, errno=%d", fd, errno); + return -1; + } } mRequests.replaceValueAt(requestIndex, request); } @@ -464,8 +519,12 @@ int Looper::addFd(int fd, int ident, int events, const sp<LooperCallback>& callb } int Looper::removeFd(int fd) { + return removeFd(fd, -1); +} + +int Looper::removeFd(int fd, int seq) { #if DEBUG_CALLBACKS - ALOGD("%p ~ removeFd - fd=%d", this, fd); + ALOGD("%p ~ removeFd - fd=%d, seq=%d", this, fd, seq); #endif { // acquire lock @@ -475,13 +534,43 @@ int Looper::removeFd(int fd) { return 0; } - int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_DEL, fd, NULL); - if (epollResult < 0) { - ALOGE("Error removing epoll events for fd %d, errno=%d", fd, errno); - return -1; + // Check the sequence number if one was given. + if (seq != -1 && mRequests.valueAt(requestIndex).seq != seq) { +#if DEBUG_CALLBACKS + ALOGD("%p ~ removeFd - sequence number mismatch, oldSeq=%d", + this, mRequests.valueAt(requestIndex).seq); +#endif + return 0; } + // Always remove the FD from the request map even if an error occurs while + // updating the epoll set so that we avoid accidentally leaking callbacks. mRequests.removeItemsAt(requestIndex); + + int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_DEL, fd, NULL); + if (epollResult < 0) { + if (seq != -1 && (errno == EBADF || errno == ENOENT)) { + // Tolerate EBADF or ENOENT when the sequence number is known because it + // means that the file descriptor was closed before its callback was + // unregistered. This error may occur naturally when a callback has the + // side-effect of closing the file descriptor before returning and + // unregistering itself. + // + // Unfortunately due to kernel limitations we need to rebuild the epoll + // set from scratch because it may contain an old file handle that we are + // now unable to remove since its file descriptor is no longer valid. + // No such problem would have occurred if we were using the poll system + // call instead, but that approach carries others disadvantages. +#if DEBUG_CALLBACKS + ALOGD("%p ~ removeFd - EPOLL_CTL_DEL failed due to file descriptor " + "being closed, errno=%d", this, errno); +#endif + scheduleEpollRebuildLocked(); + } else { + ALOGE("Error removing epoll events for fd %d, errno=%d", fd, errno); + return -1; + } + } } // release lock return 1; } @@ -500,7 +589,7 @@ void Looper::sendMessageDelayed(nsecs_t uptimeDelay, const sp<MessageHandler>& h void Looper::sendMessageAtTime(nsecs_t uptime, const sp<MessageHandler>& handler, const Message& message) { #if DEBUG_CALLBACKS - ALOGD("%p ~ sendMessageAtTime - uptime=%lld, handler=%p, what=%d", + ALOGD("%p ~ sendMessageAtTime - uptime=%" PRId64 ", handler=%p, what=%d", this, uptime, handler.get(), message.what); #endif @@ -566,8 +655,18 @@ void Looper::removeMessages(const sp<MessageHandler>& handler, int what) { } // release lock } -bool Looper::isIdling() const { - return mIdling; +bool Looper::isPolling() const { + return mPolling; +} + +void Looper::Request::initEventItem(struct epoll_event* eventItem) const { + int epollEvents = 0; + if (events & EVENT_INPUT) epollEvents |= EPOLLIN; + if (events & EVENT_OUTPUT) epollEvents |= EPOLLOUT; + + memset(eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union + eventItem->events = epollEvents; + eventItem->data.fd = fd; } } // namespace android diff --git a/logwrapper/logwrap.c b/logwrapper/logwrap.c index 3a6276e..83576fb 100644 --- a/logwrapper/logwrap.c +++ b/logwrapper/logwrap.c @@ -325,7 +325,7 @@ static int parent(const char *tag, int parent_read, pid_t pid, if (log_target & LOG_KLOG) { snprintf(log_info.klog_fmt, sizeof(log_info.klog_fmt), - "<6>%.*s: %%s", MAX_KLOG_TAG, log_info.btag); + "<6>%.*s: %%s\n", MAX_KLOG_TAG, log_info.btag); } if ((log_target & LOG_FILE) && !file_path) { diff --git a/rootdir/init.environ.rc.in b/rootdir/init.environ.rc.in index 0064790..b34ea01 100644 --- a/rootdir/init.environ.rc.in +++ b/rootdir/init.environ.rc.in @@ -5,7 +5,7 @@ on init export ANDROID_ASSETS /system/app export ANDROID_DATA /data export ANDROID_STORAGE /storage + export EXTERNAL_STORAGE /sdcard export ASEC_MOUNTPOINT /mnt/asec - export LOOP_MOUNTPOINT /mnt/obb export BOOTCLASSPATH %BOOTCLASSPATH% export SYSTEMSERVERCLASSPATH %SYSTEMSERVERCLASSPATH% diff --git a/rootdir/init.rc b/rootdir/init.rc index 0edb984..dd63cf4 100644 --- a/rootdir/init.rc +++ b/rootdir/init.rc @@ -26,9 +26,6 @@ on early-init start ueventd - # create mountpoints - mkdir /mnt 0775 root system - on init sysclktz 0 @@ -62,28 +59,30 @@ on init mkdir /cache 0770 system cache mkdir /config 0500 root root + # Mount staging areas for devices managed by vold # See storage config details at http://source.android.com/tech/storage/ - mkdir /mnt/shell 0700 shell shell - mkdir /mnt/media_rw 0700 media_rw media_rw - mkdir /storage 0751 root sdcard_r + mkdir /mnt 0755 root system + mount tmpfs tmpfs /mnt mode=0755,uid=0,gid=1000 + restorecon_recursive /mnt - # Directory for putting things only root should see. mkdir /mnt/secure 0700 root root + mkdir /mnt/secure/asec 0700 root root + mkdir /mnt/asec 0755 root system + mkdir /mnt/obb 0755 root system + mkdir /mnt/media_rw 0750 root media_rw + mkdir /mnt/user 0755 root root + mkdir /mnt/user/0 0755 root root + mkdir /mnt/expand 0771 system system + + # sdcard_r is GID 1028 + mkdir /storage 0751 root sdcard_r + mount tmpfs tmpfs /storage mode=0751,uid=0,gid=1028 + restorecon_recursive /storage - # Directory for staging bindmounts - mkdir /mnt/secure/staging 0700 root root - - # Directory-target for where the secure container - # imagefile directory will be bind-mounted - mkdir /mnt/secure/asec 0700 root root - - # Secure container public mount points. - mkdir /mnt/asec 0700 root system - mount tmpfs tmpfs /mnt/asec mode=0755,gid=1000 - - # Filesystem image public mount points. - mkdir /mnt/obb 0700 root system - mount tmpfs tmpfs /mnt/obb mode=0755,gid=1000 + # Symlink to keep legacy apps working in multi-user world + mkdir /storage/self 0751 root sdcard_r + symlink /storage/self/primary /sdcard + symlink /mnt/user/0/primary /storage/self/primary # memory control cgroup mkdir /dev/memcg 0700 root system @@ -111,6 +110,10 @@ on init # set fwmark on accepted sockets write /proc/sys/net/ipv4/tcp_fwmark_accept 1 + # disable icmp redirects + write /proc/sys/net/ipv4/conf/all/accept_redirects 0 + write /proc/sys/net/ipv6/conf/all/accept_redirects 0 + # Create cgroup mount points for process groups mkdir /dev/cpuctl mount cgroup none /dev/cpuctl cpu @@ -233,6 +236,9 @@ on post-fs-data # We restorecon /data in case the userdata partition has been reset. restorecon /data + # Emulated internal storage area + mkdir /data/media 0770 media_rw media_rw + # Start bootcharting as soon as possible after the data partition is # mounted to collect more data. mkdir /data/bootchart 0755 shell shell @@ -265,6 +271,7 @@ on post-fs-data chmod 0660 /data/misc/wifi/wpa_supplicant.conf mkdir /data/local 0751 root root mkdir /data/misc/media 0700 media media + mkdir /data/misc/vold 0700 root root # For security reasons, /data/local/tmp should always be empty. # Do not place files or directories in /data/local/tmp @@ -341,9 +348,9 @@ on boot write /proc/sys/vm/overcommit_memory 1 write /proc/sys/vm/min_free_order_shift 4 chown root system /sys/module/lowmemorykiller/parameters/adj - chmod 0220 /sys/module/lowmemorykiller/parameters/adj + chmod 0664 /sys/module/lowmemorykiller/parameters/adj chown root system /sys/module/lowmemorykiller/parameters/minfree - chmod 0220 /sys/module/lowmemorykiller/parameters/minfree + chmod 0664 /sys/module/lowmemorykiller/parameters/minfree # Tweak background writeout write /proc/sys/vm/dirty_expire_centisecs 200 @@ -531,7 +538,9 @@ service servicemanager /system/bin/servicemanager onrestart restart surfaceflinger onrestart restart drm -service vold /system/bin/vold +service vold /system/bin/vold \ + --blkid_context=u:r:blkid:s0 --blkid_untrusted_context=u:r:blkid_untrusted:s0 \ + --fsck_context=u:r:fsck:s0 --fsck_untrusted_context=u:r:fsck_untrusted:s0 class core socket vold stream 0660 root mount ioprio be 2 diff --git a/sdcard/sdcard.c b/sdcard/sdcard.c index 041c37a..4712e90 100644 --- a/sdcard/sdcard.c +++ b/sdcard/sdcard.c @@ -146,8 +146,6 @@ typedef enum { PERM_ANDROID_OBB, /* This node is "/Android/media" */ PERM_ANDROID_MEDIA, - /* This node is "/Android/user" */ - PERM_ANDROID_USER, } perm_t; /* Permissions structure to derive */ @@ -252,7 +250,7 @@ struct fuse { __u32 inode_ctr; Hashmap* package_to_appid; - Hashmap* appid_with_rw; + Hashmap* uid_with_rw; }; /* Private data used by a single fuse handler. */ @@ -474,6 +472,8 @@ static void derive_permissions_locked(struct fuse* fuse, struct node *parent, /* Legacy internal layout places users at top level */ node->perm = PERM_ROOT; node->userid = strtoul(node->name, NULL, 10); + node->gid = multiuser_get_uid(node->userid, AID_SDCARD_R); + node->mode = 0771; break; case PERM_ROOT: /* Assume masked off by default. */ @@ -485,14 +485,14 @@ static void derive_permissions_locked(struct fuse* fuse, struct node *parent, } else if (fuse->split_perms) { if (!strcasecmp(node->name, "DCIM") || !strcasecmp(node->name, "Pictures")) { - node->gid = AID_SDCARD_PICS; + node->gid = multiuser_get_uid(node->userid, AID_SDCARD_PICS); } else if (!strcasecmp(node->name, "Alarms") || !strcasecmp(node->name, "Movies") || !strcasecmp(node->name, "Music") || !strcasecmp(node->name, "Notifications") || !strcasecmp(node->name, "Podcasts") || !strcasecmp(node->name, "Ringtones")) { - node->gid = AID_SDCARD_AV; + node->gid = multiuser_get_uid(node->userid, AID_SDCARD_AV); } } break; @@ -512,13 +512,6 @@ static void derive_permissions_locked(struct fuse* fuse, struct node *parent, /* App-specific directories inside; let anyone traverse */ node->perm = PERM_ANDROID_MEDIA; node->mode = 0771; - } else if (!strcasecmp(node->name, "user")) { - /* User directories must only be accessible to system, protected - * by sdcard_all. Zygote will bind mount the appropriate user- - * specific path. */ - node->perm = PERM_ANDROID_USER; - node->gid = AID_SDCARD_ALL; - node->mode = 0770; } break; case PERM_ANDROID_DATA: @@ -530,13 +523,6 @@ static void derive_permissions_locked(struct fuse* fuse, struct node *parent, } node->mode = 0770; break; - case PERM_ANDROID_USER: - /* Root of a secondary user */ - node->perm = PERM_ROOT; - node->userid = strtoul(node->name, NULL, 10); - node->gid = AID_SDCARD_R; - node->mode = 0771; - break; } } @@ -547,8 +533,7 @@ static bool get_caller_has_rw_locked(struct fuse* fuse, const struct fuse_in_hea return true; } - appid_t appid = multiuser_get_app_id(hdr->uid); - return hashmapContainsKey(fuse->appid_with_rw, (void*) (uintptr_t) appid); + return hashmapContainsKey(fuse->uid_with_rw, (void*) (uintptr_t) hdr->uid); } /* Kernel has already enforced everything we returned through @@ -729,7 +714,7 @@ static struct node* acquire_or_create_child_locked( } static void fuse_init(struct fuse *fuse, int fd, const char *source_path, - gid_t write_gid, derive_t derive, bool split_perms) { + gid_t write_gid, userid_t owner_user, derive_t derive, bool split_perms) { pthread_mutex_init(&fuse->lock, NULL); fuse->fd = fd; @@ -761,10 +746,10 @@ static void fuse_init(struct fuse *fuse, int fd, const char *source_path, * places user_id at the top directory level, with the actual roots * just below that. Shared OBB path is also at top level. */ fuse->root.perm = PERM_LEGACY_PRE_ROOT; - fuse->root.mode = 0771; + fuse->root.mode = 0711; fuse->root.gid = AID_SDCARD_R; fuse->package_to_appid = hashmapCreate(256, str_hash, str_icase_equals); - fuse->appid_with_rw = hashmapCreate(128, int_hash, int_equals); + fuse->uid_with_rw = hashmapCreate(128, int_hash, int_equals); snprintf(fuse->obbpath, sizeof(fuse->obbpath), "%s/obb", source_path); fs_prepare_dir(fuse->obbpath, 0775, getuid(), getgid()); break; @@ -773,9 +758,10 @@ static void fuse_init(struct fuse *fuse, int fd, const char *source_path, * /Android/user and shared OBB path under /Android/obb. */ fuse->root.perm = PERM_ROOT; fuse->root.mode = 0771; - fuse->root.gid = AID_SDCARD_R; + fuse->root.userid = owner_user; + fuse->root.gid = multiuser_get_uid(owner_user, AID_SDCARD_R); fuse->package_to_appid = hashmapCreate(256, str_hash, str_icase_equals); - fuse->appid_with_rw = hashmapCreate(128, int_hash, int_equals); + fuse->uid_with_rw = hashmapCreate(128, int_hash, int_equals); snprintf(fuse->obbpath, sizeof(fuse->obbpath), "%s/Android/obb", source_path); break; } @@ -1710,7 +1696,7 @@ static int read_package_list(struct fuse *fuse) { pthread_mutex_lock(&fuse->lock); hashmapForEach(fuse->package_to_appid, remove_str_to_int, fuse->package_to_appid); - hashmapForEach(fuse->appid_with_rw, remove_int_to_null, fuse->appid_with_rw); + hashmapForEach(fuse->uid_with_rw, remove_int_to_null, fuse->uid_with_rw); FILE* file = fopen(kPackagesListFile, "r"); if (!file) { @@ -1731,9 +1717,14 @@ static int read_package_list(struct fuse *fuse) { char* token = strtok(gids, ","); while (token != NULL) { - if (strtoul(token, NULL, 10) == fuse->write_gid) { - hashmapPut(fuse->appid_with_rw, (void*) (uintptr_t) appid, (void*) (uintptr_t) 1); - break; + // Current packages.list format is a bit funky; it blends per + // user GID membership into a single per-app line. Here we + // work backwards from the groups to build the per-user UIDs + // that have write permission. + gid_t gid = strtoul(token, NULL, 10); + if (multiuser_get_app_id(gid) == fuse->write_gid) { + uid_t uid = multiuser_get_uid(multiuser_get_user_id(gid), appid); + hashmapPut(fuse->uid_with_rw, (void*) (uintptr_t) uid, (void*) (uintptr_t) 1); } token = strtok(NULL, ","); } @@ -1742,7 +1733,7 @@ static int read_package_list(struct fuse *fuse) { TRACE("read_package_list: found %zu packages, %zu with write_gid\n", hashmapSize(fuse->package_to_appid), - hashmapSize(fuse->appid_with_rw)); + hashmapSize(fuse->uid_with_rw)); fclose(file); pthread_mutex_unlock(&fuse->lock); return 0; @@ -1867,7 +1858,7 @@ static int usage() } static int run(const char* source_path, const char* dest_path, uid_t uid, - gid_t gid, gid_t write_gid, int num_threads, derive_t derive, + gid_t gid, gid_t write_gid, userid_t owner_user, int num_threads, derive_t derive, bool split_perms) { int fd; char opts[256]; @@ -1912,7 +1903,7 @@ static int run(const char* source_path, const char* dest_path, uid_t uid, goto error; } - fuse_init(&fuse, fd, source_path, write_gid, derive, split_perms); + fuse_init(&fuse, fd, source_path, write_gid, owner_user, derive, split_perms); umask(0); res = ignite_fuse(&fuse, num_threads); @@ -1933,6 +1924,7 @@ int main(int argc, char **argv) uid_t uid = 0; gid_t gid = 0; gid_t write_gid = AID_SDCARD_RW; + userid_t owner_user = 0; int num_threads = DEFAULT_NUM_THREADS; derive_t derive = DERIVE_NONE; bool split_perms = false; @@ -1941,7 +1933,7 @@ int main(int argc, char **argv) int fs_version; int opt; - while ((opt = getopt(argc, argv, "u:g:w:t:dls")) != -1) { + while ((opt = getopt(argc, argv, "u:g:w:o:t:dls")) != -1) { switch (opt) { case 'u': uid = strtoul(optarg, NULL, 10); @@ -1952,6 +1944,9 @@ int main(int argc, char **argv) case 'w': write_gid = strtoul(optarg, NULL, 10); break; + case 'o': + owner_user = strtoul(optarg, NULL, 10); + break; case 't': num_threads = strtoul(optarg, NULL, 10); break; @@ -2018,6 +2013,7 @@ int main(int argc, char **argv) sleep(1); } - res = run(source_path, dest_path, uid, gid, write_gid, num_threads, derive, split_perms); + res = run(source_path, dest_path, uid, gid, write_gid, owner_user, + num_threads, derive, split_perms); return res < 0 ? 1 : 0; } |