upload android base code part6

This commit is contained in:
August 2018-08-08 17:48:24 +08:00
parent 421e214c7d
commit 4e516ec6ed
35396 changed files with 9188716 additions and 0 deletions

Binary file not shown.

View file

@ -0,0 +1,29 @@
#
# 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.
#
# WARNING: Everything listed here will be built on ALL platforms,
# including x86, the emulator, and the SDK. Modules must be uniquely
# named (liblights.tungsten), and must build everywhere, or limit themselves
# to only building on ARM if they include assembly. Individual makefiles
# are responsible for having their own logic, for fine-grained control.
ifneq ($(filter fugu,$(TARGET_DEVICE)),)
LOCAL_PATH := $(call my-dir)
include $(call all-makefiles-under,$(LOCAL_PATH))
endif

View file

@ -0,0 +1,22 @@
#
# Copyright 2013 The Android Open-Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
LOCAL_PATH := $(my-dir)
include $(LOCAL_PATH)/AndroidKernel.mk
-include vendor/intel/prebuilts/$(TARGET_PRODUCT)/prebuilts.mk

View file

@ -0,0 +1,93 @@
ifeq ($(TARGET_KERNEL_BUILT_FROM_SOURCE),true)
# Force using bash as a shell, otherwise, on Ubuntu, dash will break some
# dependency due to its bad handling of echo \1
MAKE += SHELL=/bin/bash
ifeq ($(KERNEL_CFG_NAME),)
$(error cannot build kernel, config not specified)
endif
ifeq ($(TARGET_KERNEL_ARCH),x86_64)
KERNEL_TOOLCHAIN_ARCH := $(TARGET_KERNEL_ARCH)
else
KERNEL_TOOLCHAIN_ARCH := i686
endif
KERNEL_EXTRA_FLAGS := ANDROID_TOOLCHAIN_FLAGS="-mno-android -Werror"
KERNEL_CROSS_COMP := $(notdir $(TARGET_TOOLS_PREFIX))
KERNEL_CCACHE :=$(firstword $(TARGET_CC))
KERNEL_PATH := $(ANDROID_BUILD_TOP)/vendor/intel/support
ifeq ($(notdir $(KERNEL_CCACHE)),ccache)
KERNEL_CROSS_COMP := "ccache $(KERNEL_CROSS_COMP)"
KERNEL_PATH := $(KERNEL_PATH):$(ANDROID_BUILD_TOP)/$(dir $(KERNEL_CCACHE))
endif
#remove time_macros from ccache options, it breaks signing process
KERNEL_CCSLOP := $(filter-out time_macros,$(subst $(comma), ,$(CCACHE_SLOPPINESS)))
KERNEL_CCSLOP := $(subst $(space),$(comma),$(KERNEL_CCSLOP))
KERNEL_OUT_DIR := $(PRODUCT_OUT)/linux/kernel
KERNEL_CONFIG := $(KERNEL_OUT_DIR)/.config
KERNEL_SAVE_DEFCONFIG := $(KERNEL_OUT_DIR)/defconfig
KERNEL_BLD_FLAGS := \
ARCH=$(TARGET_KERNEL_ARCH) \
$(KERNEL_EXTRA_FLAGS)
KERNEL_BLD_FLAGS :=$(KERNEL_BLD_FLAGS) \
O=../../$(KERNEL_OUT_DIR) \
KERNEL_BLD_ENV := CROSS_COMPILE=$(KERNEL_CROSS_COMP) \
PATH=$(KERNEL_PATH):$(PATH) \
CCACHE_SLOPPINESS=$(KERNEL_CCSLOP)
KERNEL_DEFCONFIG ?= $(KERNEL_SRC_DIR)/arch/x86/configs/$(KERNEL_CFG_NAME)_defconfig
KERNEL_VERSION_FILE := $(KERNEL_OUT_DIR)/include/config/kernel.release
KERNEL_BZIMAGE := $(PRODUCT_OUT)/kernel
$(KERNEL_CONFIG): $(KERNEL_DEFCONFIG)
$(hide) echo Regenerating kernel config $(KERNEL_OUT_DIR)
$(hide) mkdir -p $(KERNEL_OUT_DIR)
$(hide) $(KERNEL_BLD_ENV) $(MAKE) -C $(KERNEL_SRC_DIR) $(KERNEL_BLD_FLAGS) $(notdir $(KERNEL_DEFCONFIG))
ifeq (,$(filter build_kernel-nodeps,$(MAKECMDGOALS)))
$(KERNEL_BZIMAGE): $(MINIGZIP)
endif
$(KERNEL_BZIMAGE): $(KERNEL_CONFIG)
$(hide) $(KERNEL_BLD_ENV) $(MAKE) -C $(KERNEL_SRC_DIR) $(KERNEL_BLD_FLAGS)
$(hide) cp -f $(KERNEL_OUT_DIR)/arch/x86/boot/bzImage $@
clean_kernel:
$(hide) $(KERNEL_BLD_ENV) $(MAKE) -C $(KERNEL_SRC_DIR) $(KERNEL_BLD_FLAGS) clean
menuconfig xconfig gconfig: $(KERNEL_CONFIG)
$(hide) $(KERNEL_BLD_ENV) $(MAKE) -C $(KERNEL_SRC_DIR) $(KERNEL_BLD_FLAGS) $@
$(hide) $(KERNEL_BLD_ENV) $(MAKE) -C $(KERNEL_SRC_DIR) $(KERNEL_BLD_FLAGS) savedefconfig
$(hide) cp -f $(KERNEL_SAVE_DEFCONFIG) $(KERNEL_DEFCONFIG)
$(hide) echo ===========
$(hide) echo $(KERNEL_DEFCONFIG) has been modified !
$(hide) echo ===========
TAGS_files := TAGS
tags_files := tags
gtags_files := GTAGS GPATH GRTAGS GSYMS
cscope_files := $(addprefix cscope.,files out out.in out.po)
TAGS tags gtags cscope: $(KERNEL_CONFIG)
$(hide) $(KERNEL_BLD_ENV) $(MAKE) -C $(KERNEL_SRC_DIR) $(KERNEL_BLD_FLAGS) $@
$(hide) rm -f $(KERNEL_SRC_DIR)/$($@_files)
$(hide) cp -fs $(addprefix `pwd`/$(KERNEL_OUT_DIR)/,$($@_files)) $(KERNEL_SRC_DIR)/
define build_kernel_module
$(error Use of external Kernel modules is not allowed)
endef
.PHONY: menuconfig xconfig gconfig
.PHONY: $(KERNEL_BZIMAGE)
.PHONY: build_kernel build_kernel-nodeps
$(PRODUCT_OUT)/boot.img: build_kernel
endif #TARGET_KERNEL_BUILT_FROM_SOURCE

View file

@ -0,0 +1,19 @@
#
# Copyright 2013 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.
#
PRODUCT_MAKEFILES := \
$(LOCAL_DIR)/aosp_fugu.mk \
$(LOCAL_DIR)/full_fugu.mk

View file

@ -0,0 +1,149 @@
#
# Copyright 2013 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.
#
# Use the non-open-source parts, if they're present
-include vendor/intel/fugu/BoardConfigVendor.mk
TARGET_ARCH := x86
TARGET_ARCH_VARIANT := silvermont
TARGET_CPU_ABI := x86
TARGET_RECOVERY_FSTAB := device/asus/fugu/recovery.fstab
TARGET_RELEASETOOLS_EXTENSIONS := device/asus/fugu
TARGET_RECOVERY_UPDATER_LIBS := librecovery_updater_fugu
TARGET_RECOVERY_UI_LIB := librecovery_ui_fugu
TARGET_BOARD_PLATFORM := moorefield
TARGET_BOOTLOADER_BOARD_NAME := fugu
TARGET_USERIMAGES_USE_EXT4 := true
BOARD_SYSTEMIMAGE_PARTITION_SIZE := 1073741824
BOARD_SYSTEMIMAGE_JOURNAL_SIZE := 0
# as of 3562118, inode usage was 2149, use 4096 to be safe
BOARD_SYSTEMIMAGE_EXTFS_INODE_COUNT := 4096
BOARD_FLASH_BLOCK_SIZE := 2048
BOARD_CACHEIMAGE_PARTITION_SIZE := 260014080
TARGET_DROIDBOOT_LIBS := libintel_droidboot
TARGET_RECOVERY_PIXEL_FORMAT := "RGBX_8888"
MALLOC_SVELTE := true
# Kernel cmdline
BOARD_KERNEL_CMDLINE := pci=noearly vmalloc=256M ptrace.ptrace_can_access=1
BOARD_KERNEL_CMDLINE += earlyprintk=nologger loglevel=8
BOARD_KERNEL_CMDLINE += androidboot.hardware=fugu androidboot.serialno=01234567890123456789
BOARD_KERNEL_CMDLINE += snd_pcm.maximum_substreams=8
BOARD_KERNEL_CMDLINE += intel_soc_pmu.enable_s3=0
BOARD_KERNEL_CMDLINE += loop.max_part=7
# Binder API version
TARGET_USES_64_BIT_BINDER := true
# Security
BUILD_WITH_SECURITY_FRAMEWORK := chaabi_token
BUILD_WITH_CHAABI_SUPPORT := true
# Wifi
BOARD_WLAN_DEVICE := bcmdhd
BOARD_WPA_SUPPLICANT_PRIVATE_LIB := lib_driver_cmd_bcmdhd
BOARD_HOSTAPD_PRIVATE_LIB := lib_driver_cmd_bcmdhd
WPA_SUPPLICANT_VERSION := VER_0_8_X
BOARD_WPA_SUPPLICANT_DRIVER := NL80211
WIFI_DRIVER_FW_PATH_PARAM := "/sys/module/bcmdhd/parameters/firmware_path"
WIFI_DRIVER_FW_PATH_AP := "/vendor/firmware/fw_bcmdhd_apsta.bin"
WIFI_DRIVER_FW_PATH_STA := "/vendor/firmware/fw_bcmdhd.bin"
# Bluetooth
BOARD_HAVE_BLUETOOTH := true
BOARD_HAVE_BLUETOOTH_BCM := true
BOARD_BLUETOOTH_BDROID_BUILDCFG_INCLUDE_DIR := device/asus/fugu/bluetooth
# IMG graphics
BOARD_GFX_REV := RGX6400
ENABLE_IMG_GRAPHICS := true
ENABLE_MRFL_GRAPHICS := true
INTEL_HWC_MOOREFIELD_HDMI := true
HWUI_IMG_FBO_CACHE_OPTIM := true
TARGET_SUPPORT_HDMI_PRIMARY := true
BOARD_USES_LIBDRM := true
TARGET_USES_HWC2 := true
NUM_FRAMEBUFFER_SURFACE_BUFFERS := 3
SF_START_GRAPHICS_ALLOCATOR_SERVICE := true
# Audio
BOARD_USES_ALSA_AUDIO := true
BOARD_USES_TINY_ALSA_AUDIO := true
# System's VSYNC phase offsets in nanoseconds
VSYNC_EVENT_PHASE_OFFSET_NS := 7500000
SF_VSYNC_EVENT_PHASE_OFFSET_NS := 5000000
BOARD_EGL_CFG := device/asus/fugu/egl.cfg
MAX_EGL_CACHE_ENTRY_SIZE := 65536
MAX_EGL_CACHE_SIZE := 1048576
INTEL_VA := true
BUILD_WITH_FULL_STAGEFRIGHT := true
BOARD_USES_VIDEO := true
BOARD_USES_WRS_OMXIL_CORE := true
BOARD_USES_MRST_OMX := true
USE_HW_VP8 := true
# DRM Protected Video
BOARD_WIDEVINE_OEMCRYPTO_LEVEL := 1
USE_INTEL_SECURE_AVC := true
# Settings for the Media SDK library and plug-ins:
# - USE_MEDIASDK: use Media SDK support or not
# - MFX_IPP: sets IPP library optimization to use
USE_MEDIASDK := true
MFX_IPP := p8
# Video Post Processing
TARGET_HAS_ISV := true
OVERRIDE_RS_DRIVER := libPVRRS.so
# enable ARM codegen for x86 with Houdini
BUILD_ARM_FOR_X86 := true
# enabled to carry out all drawing operations performed on a View's canvas with GPU for 2D rendering pipeline.
USE_OPENGL_RENDERER := true
# DPST
INTEL_DPST := true
# bootstub as 2nd bootloader
TARGET_BOOTLOADER_IS_2ND := true
BOARD_SEPOLICY_DIRS += device/asus/fugu/sepolicy
USE_CLANG_PLATFORM_BUILD := true
# Use the non-open-source parts, if they're present
-include vendor/asus/fugu/BoardConfigVendor.mk
# Recipes to generate prebuilts
-include device/intel/common/external/external.mk
# Don't dex preopt prebuilt apps that will be updated from Play Store
DONT_DEXPREOPT_PREBUILTS := true
# Vendor Interface Manifest
DEVICE_MANIFEST_FILE := device/asus/fugu/manifest.xml
DEVICE_MATRIX_FILE := device/asus/fugu/compatibility_matrix.xml

View file

@ -0,0 +1,441 @@
# Copyright (C) 2010 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.
#
# Generic key layout file for full alphabetic US English PC style external keyboards.
#
# This file is intentionally very generic and is intended to support a broad rang of keyboards.
# Do not edit the generic key layout to support a specific keyboard; instead, create
# a new key layout file with the required keyboard configuration.
#
key 1 ESCAPE
key 2 1
key 3 2
key 4 3
key 5 4
key 6 5
key 7 6
key 8 7
key 9 8
key 10 9
key 11 0
key 12 MINUS
key 13 EQUALS
key 14 DEL
key 15 TAB
key 16 Q
key 17 W
key 18 E
key 19 R
key 20 T
key 21 Y
key 22 U
key 23 I
key 24 O
key 25 P
key 26 LEFT_BRACKET
key 27 RIGHT_BRACKET
key 28 ENTER
key 29 CTRL_LEFT
key 30 A
key 31 S
key 32 D
key 33 F
key 34 G
key 35 H
key 36 J
key 37 K
key 38 L
key 39 SEMICOLON
key 40 APOSTROPHE
key 41 GRAVE
key 42 SHIFT_LEFT
key 43 BACKSLASH
key 44 Z
key 45 X
key 46 C
key 47 V
key 48 B
key 49 N
key 50 M
key 51 COMMA
key 52 PERIOD
key 53 SLASH
key 54 SHIFT_RIGHT
key 55 NUMPAD_MULTIPLY
key 56 ALT_LEFT
key 57 SPACE
key 58 CAPS_LOCK
key 59 F1
key 60 F2
key 61 F3
key 62 F4
key 63 F5
key 64 F6
key 65 F7
key 66 F8
key 67 F9
key 68 F10
key 69 NUM_LOCK
key 70 SCROLL_LOCK
key 71 NUMPAD_7
key 72 NUMPAD_8
key 73 NUMPAD_9
key 74 NUMPAD_SUBTRACT
key 75 NUMPAD_4
key 76 NUMPAD_5
key 77 NUMPAD_6
key 78 NUMPAD_ADD
key 79 NUMPAD_1
key 80 NUMPAD_2
key 81 NUMPAD_3
key 82 NUMPAD_0
key 83 NUMPAD_DOT
# key 84 (undefined)
key 85 ZENKAKU_HANKAKU
key 86 BACKSLASH
key 87 F11
key 88 F12
key 89 RO
# key 90 "KEY_KATAKANA"
# key 91 "KEY_HIRAGANA"
key 92 HENKAN
key 93 KATAKANA_HIRAGANA
key 94 MUHENKAN
key 95 NUMPAD_COMMA
key 96 NUMPAD_ENTER
key 97 CTRL_RIGHT
key 98 NUMPAD_DIVIDE
key 99 SYSRQ
key 100 ALT_RIGHT
# key 101 "KEY_LINEFEED"
key 102 MOVE_HOME
key 103 DPAD_UP
key 104 PAGE_UP
key 105 DPAD_LEFT
key 106 DPAD_RIGHT
key 107 MOVE_END
key 108 DPAD_DOWN
key 109 PAGE_DOWN
key 110 INSERT
key 111 FORWARD_DEL
# key 112 "KEY_MACRO"
key 113 VOLUME_MUTE
key 114 VOLUME_DOWN
key 115 VOLUME_UP
key 116 POWER
key 117 NUMPAD_EQUALS
# key 118 "KEY_KPPLUSMINUS"
key 119 BREAK
# key 120 (undefined)
key 121 NUMPAD_COMMA
key 122 KANA
key 123 EISU
key 124 YEN
key 125 META_LEFT
key 126 META_RIGHT
key 127 MENU
key 128 MEDIA_STOP
# key 129 "KEY_AGAIN"
# key 130 "KEY_PROPS"
# key 131 "KEY_UNDO"
# key 132 "KEY_FRONT"
key 133 COPY
# key 134 "KEY_OPEN"
key 135 PASTE
# key 136 "KEY_FIND"
key 137 CUT
# key 138 "KEY_HELP"
key 139 MENU
key 140 CALCULATOR
# key 141 "KEY_SETUP"
key 142 SLEEP
key 143 WAKEUP
# key 144 "KEY_FILE"
# key 145 "KEY_SENDFILE"
# key 146 "KEY_DELETEFILE"
# key 147 "KEY_XFER"
# key 148 "KEY_PROG1"
# key 149 "KEY_PROG2"
key 150 EXPLORER
# key 151 "KEY_MSDOS"
key 152 POWER
# key 153 "KEY_DIRECTION"
# key 154 "KEY_CYCLEWINDOWS"
key 155 ENVELOPE
key 156 BOOKMARK
# key 157 "KEY_COMPUTER"
key 158 BACK
key 159 FORWARD
key 160 MEDIA_CLOSE
key 161 MEDIA_EJECT
key 162 MEDIA_EJECT
key 163 MEDIA_NEXT
key 164 MEDIA_PLAY_PAUSE
key 165 MEDIA_PREVIOUS
key 166 MEDIA_STOP
key 167 MEDIA_RECORD
key 168 MEDIA_REWIND
key 169 CALL
# key 170 "KEY_ISO"
key 171 MUSIC
key 172 HOME
# key 173 "KEY_REFRESH"
# key 174 "KEY_EXIT"
# key 175 "KEY_MOVE"
# key 176 "KEY_EDIT"
key 177 PAGE_UP
key 178 PAGE_DOWN
key 179 NUMPAD_LEFT_PAREN
key 180 NUMPAD_RIGHT_PAREN
# key 181 "KEY_NEW"
# key 182 "KEY_REDO"
# key 183 F13
# key 184 F14
# key 185 F15
# key 186 F16
# key 187 F17
# key 188 F18
# key 189 F19
# key 190 F20
# key 191 F21
# key 192 F22
# key 193 F23
# key 194 F24
# key 195 (undefined)
# key 196 (undefined)
# key 197 (undefined)
# key 198 (undefined)
# key 199 (undefined)
key 200 MEDIA_PLAY
key 201 MEDIA_PAUSE
# key 202 "KEY_PROG3"
# key 203 "KEY_PROG4"
# key 204 (undefined)
# key 205 "KEY_SUSPEND"
# key 206 "KEY_CLOSE"
key 207 MEDIA_PLAY
key 208 MEDIA_FAST_FORWARD
# key 209 "KEY_BASSBOOST"
# key 210 "KEY_PRINT"
# key 211 "KEY_HP"
key 212 CAMERA
key 213 MUSIC
# key 214 "KEY_QUESTION"
key 215 ENVELOPE
# key 216 "KEY_CHAT"
key 217 ASSIST
# key 218 "KEY_CONNECT"
# key 219 "KEY_FINANCE"
# key 220 "KEY_SPORT"
# key 221 "KEY_SHOP"
# key 222 "KEY_ALTERASE"
# key 223 "KEY_CANCEL"
key 224 BRIGHTNESS_DOWN
key 225 BRIGHTNESS_UP
key 226 HEADSETHOOK
key 256 BUTTON_1
key 257 BUTTON_2
key 258 BUTTON_3
key 259 BUTTON_4
key 260 BUTTON_5
key 261 BUTTON_6
key 262 BUTTON_7
key 263 BUTTON_8
key 264 BUTTON_9
key 265 BUTTON_10
key 266 BUTTON_11
key 267 BUTTON_12
key 268 BUTTON_13
key 269 BUTTON_14
key 270 BUTTON_15
key 271 BUTTON_16
key 288 BUTTON_1
key 289 BUTTON_2
key 290 BUTTON_3
key 291 BUTTON_4
key 292 BUTTON_5
key 293 BUTTON_6
key 294 BUTTON_7
key 295 BUTTON_8
key 296 BUTTON_9
key 297 BUTTON_10
key 298 BUTTON_11
key 299 BUTTON_12
key 300 BUTTON_13
key 301 BUTTON_14
key 302 BUTTON_15
key 303 BUTTON_16
key 304 BUTTON_A
key 305 BUTTON_B
key 306 BUTTON_C
key 307 BUTTON_X
key 308 BUTTON_Y
key 309 BUTTON_Z
key 310 BUTTON_L1
key 311 BUTTON_R1
key 312 BUTTON_L2
key 313 BUTTON_R2
key 314 BUTTON_SELECT
key 315 BUTTON_START
key 316 BUTTON_MODE
key 317 BUTTON_THUMBL
key 318 BUTTON_THUMBR
# key 352 "KEY_OK"
key 353 DPAD_CENTER
# key 354 "KEY_GOTO"
# key 355 "KEY_CLEAR"
# key 356 "KEY_POWER2"
# key 357 "KEY_OPTION"
# key 358 "KEY_INFO"
# key 359 "KEY_TIME"
# key 360 "KEY_VENDOR"
# key 361 "KEY_ARCHIVE"
key 362 GUIDE
# key 363 "KEY_CHANNEL"
# key 364 "KEY_FAVORITES"
# key 365 "KEY_EPG"
key 366 DVR
# key 367 "KEY_MHP"
# key 368 "KEY_LANGUAGE"
# key 369 "KEY_TITLE"
# key 370 "KEY_SUBTITLE"
# key 371 "KEY_ANGLE"
# key 372 "KEY_ZOOM"
# key 373 "KEY_MODE"
# key 374 "KEY_KEYBOARD"
# key 375 "KEY_SCREEN"
# key 376 "KEY_PC"
key 377 TV
# key 378 "KEY_TV2"
# key 379 "KEY_VCR"
# key 380 "KEY_VCR2"
# key 381 "KEY_SAT"
# key 382 "KEY_SAT2"
# key 383 "KEY_CD"
# key 384 "KEY_TAPE"
# key 385 "KEY_RADIO"
# key 386 "KEY_TUNER"
# key 387 "KEY_PLAYER"
# key 388 "KEY_TEXT"
# key 389 "KEY_DVD"
# key 390 "KEY_AUX"
# key 391 "KEY_MP3"
# key 392 "KEY_AUDIO"
# key 393 "KEY_VIDEO"
# key 394 "KEY_DIRECTORY"
# key 395 "KEY_LIST"
# key 396 "KEY_MEMO"
key 397 CALENDAR
# key 398 "KEY_RED"
# key 399 "KEY_GREEN"
# key 400 "KEY_YELLOW"
# key 401 "KEY_BLUE"
key 402 CHANNEL_UP
key 403 CHANNEL_DOWN
# key 404 "KEY_FIRST"
# key 405 "KEY_LAST"
# key 406 "KEY_AB"
# key 407 "KEY_NEXT"
# key 408 "KEY_RESTART"
# key 409 "KEY_SLOW"
# key 410 "KEY_SHUFFLE"
# key 411 "KEY_BREAK"
# key 412 "KEY_PREVIOUS"
# key 413 "KEY_DIGITS"
# key 414 "KEY_TEEN"
# key 415 "KEY_TWEN"
key 429 CONTACTS
# key 448 "KEY_DEL_EOL"
# key 449 "KEY_DEL_EOS"
# key 450 "KEY_INS_LINE"
# key 451 "KEY_DEL_LINE"
key 464 FUNCTION
key 465 ESCAPE FUNCTION
key 466 F1 FUNCTION
key 467 F2 FUNCTION
key 468 F3 FUNCTION
key 469 F4 FUNCTION
key 470 F5 FUNCTION
key 471 F6 FUNCTION
key 472 F7 FUNCTION
key 473 F8 FUNCTION
key 474 F9 FUNCTION
key 475 F10 FUNCTION
key 476 F11 FUNCTION
key 477 F12 FUNCTION
key 478 1 FUNCTION
key 479 2 FUNCTION
key 480 D FUNCTION
key 481 E FUNCTION
key 482 F FUNCTION
key 483 S FUNCTION
key 484 B FUNCTION
# key 497 KEY_BRL_DOT1
# key 498 KEY_BRL_DOT2
# key 499 KEY_BRL_DOT3
# key 500 KEY_BRL_DOT4
# key 501 KEY_BRL_DOT5
# key 502 KEY_BRL_DOT6
# key 503 KEY_BRL_DOT7
# key 504 KEY_BRL_DOT8
key 580 APP_SWITCH
key 582 VOICE_ASSIST
# Keys defined by HID usages
key usage 0x0c006F BRIGHTNESS_UP
key usage 0x0c0070 BRIGHTNESS_DOWN
# Joystick and game controller axes.
# Axes that are not mapped will be assigned generic axis numbers by the input subsystem.
axis 0x00 X
axis 0x01 Y
axis 0x02 Z
axis 0x03 RX
axis 0x04 RY
axis 0x05 RZ
axis 0x06 THROTTLE
axis 0x07 RUDDER
axis 0x08 WHEEL
axis 0x09 GAS
axis 0x0a BRAKE
axis 0x10 HAT_X
axis 0x11 HAT_Y
# LEDs
led 0x00 NUM_LOCK
led 0x01 CAPS_LOCK
led 0x02 SCROLL_LOCK
led 0x03 COMPOSE
led 0x04 KANA
led 0x05 SLEEP
led 0x06 SUSPEND
led 0x07 MUTE
led 0x08 MISC
led 0x09 MAIL
led 0x0a CHARGING

View file

@ -0,0 +1,16 @@
# 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.
device.internal = 0
audio.mic = 1

View file

@ -0,0 +1,27 @@
# Copyright (C) 2010 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Key layout file for remote control
#
key 103 DPAD_UP
key 105 DPAD_LEFT
key 106 DPAD_RIGHT
key 108 DPAD_DOWN
key 158 BACK
key 164 MEDIA_PLAY_PAUSE
key 172 HOME
key 217 ASSIST
key 353 DPAD_CENTER

View file

@ -0,0 +1,27 @@
# Copyright (C) 2010 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Key layout file for remote control
#
key 103 DPAD_UP
key 105 DPAD_LEFT
key 106 DPAD_RIGHT
key 108 DPAD_DOWN
key 158 BACK
key 164 MEDIA_PLAY_PAUSE
key 172 HOME
key 217 ASSIST
key 353 DPAD_CENTER

View file

@ -0,0 +1,19 @@
#
# Copyright 2013 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.
#
$(call inherit-product, device/asus/fugu/full_fugu.mk)
PRODUCT_NAME := aosp_fugu

View file

@ -0,0 +1,86 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!-- Copyright (C) 2017 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.
-->
<audioPolicyConfiguration version="1.0" xmlns:xi="http://www.w3.org/2001/XInclude">
<globalConfiguration speaker_drc_enabled="false"/>
<modules>
<module name="primary" halVersion="2.0">
<mixPorts>
<mixPort name="primary output" role="source">
<profile name="" format="AUDIO_FORMAT_PCM_8_24_BIT"
samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
</mixPort>
<mixPort name="multichannel output" role="source" flags="AUDIO_OUTPUT_FLAG_DIRECT">
<profile name=""/>
</mixPort>
<mixPort name="primary input" role="sink">
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
channelMasks="AUDIO_CHANNEL_IN_MONO"/>
</mixPort>
</mixPorts>
<devicePorts>
<devicePort tagName="HDMI Out" type="AUDIO_DEVICE_OUT_AUX_DIGITAL" role="sink">
</devicePort>
<devicePort tagName="Wired Headset Mic" type="AUDIO_DEVICE_IN_WIRED_HEADSET" role="source">
</devicePort>
</devicePorts>
<routes>
<route type="mix" sink="HDMI Out"
sources="primary output,multichannel output"/>
<route type="mix" sink="primary input"
sources="Wired Headset Mic"/>
</routes>
</module>
<module name="stub" halVersion="2.0">
<attachedDevices>
<item>Default Out</item>
</attachedDevices>
<defaultOutputDevice>Default Out</defaultOutputDevice>
<mixPorts>
<mixPort name="stub output" role="source" flags="AUDIO_OUTPUT_FLAG_PRIMARY">
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
</mixPort>
</mixPorts>
<devicePorts>
<devicePort tagName="Default Out" type="AUDIO_DEVICE_OUT_STUB" role="sink">
</devicePort>
</devicePorts>
<routes>
<route type="mix" sink="Default Out" sources="stub output"/>
</routes>
</module>
<!-- A2dp Audio HAL -->
<xi:include href="a2dp_audio_policy_configuration.xml"/>
<!-- Usb Audio HAL -->
<xi:include href="usb_audio_policy_configuration.xml"/>
<!-- Remote Submix Audio HAL -->
<xi:include href="r_submix_audio_policy_configuration.xml"/>
</modules>
<!-- Volume section -->
<xi:include href="audio_policy_volumes.xml"/>
<xi:include href="default_volume_tables.xml"/>
</audioPolicyConfiguration>

View file

@ -0,0 +1,75 @@
/*
* 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 _BDROID_BUILDCFG_H
#define _BDROID_BUILDCFG_H
#define BTM_DEF_LOCAL_NAME "Nexus Player"
#define BTA_DM_COD {0x20, BTM_COD_MAJOR_AUDIO, BTM_COD_MINOR_SET_TOP_BOX}
#define BLE_VND_INCLUDED TRUE
// Turn off BLE_PRIVACY_SPT. Remote reconnect fails on
// often if this is enabled.
#define BLE_PRIVACY_SPT FALSE
// Force connection interval to 13.75ms
#define BTM_BLE_CONN_INT_MIN_DEF 11 /* 13.75ms = 11 * 1.25 */
#define BTM_BLE_CONN_INT_MAX_DEF BTM_BLE_CONN_INT_MIN_DEF
// Allow better battery life
#define BTM_BLE_CONN_SLAVE_LATENCY_DEF 24
// Detect disconnects faster
#define BTM_BLE_CONN_TIMEOUT_DEF 300
// Increase background scanning to reduce reconnect time
#define BTM_BLE_SCAN_SLOW_INT_1 110 /* 68.75 ms = 110 *0.625 */
#define BTM_BLE_SCAN_SLOW_WIN_1 8 /* 5 ms = 8 *0.625 */
// Disable HFP
#define BTIF_HF_SERVICES (BTA_HSP_SERVICE_MASK)
#define BTIF_HF_SERVICE_NAMES { BTIF_HSAG_SERVICE_NAME, NULL }
// Disable compiling code in Bluedroid for profiles we don't support
#define BTA_PAN_INCLUDED FALSE
#define BNEP_INCLUDED FALSE
#define AVDT_INCLUDED FALSE
#define PAN_INCLUDED FALSE
#define AVCT_INCLUDED FALSE
/* We will support a remote + 4 game controllers. To be able to
* allocate sufficient bandwidth for all devices we will restrict the
* Game Controllers to a sniff interval of 13.75ms.
*/
#define BTA_DM_PM_SNIFF4_MAX 22
#define BTA_DM_PM_SNIFF4_MIN 22
#define BTA_DM_PM_SNIFF4_ATTEMPT 1
#define BTA_DM_PM_SNIFF4_TIMEOUT 0
#define BTA_DM_PM_SNIFF_HH_OPEN_IDX BTA_DM_PM_SNIFF4
#define BTA_DM_PM_HH_OPEN_DELAY 0
#define BTA_DM_PM_SNIFF_HH_ACTIVE_IDX BTA_DM_PM_SNIFF4
#define BTA_DM_PM_HH_ACTIVE_DELAY 0
#define BTA_DM_PM_SNIFF_HH_IDLE_IDX BTA_DM_PM_SNIFF4
#define BTA_DM_PM_HH_IDLE_DELAY 0
// Change I/O capabilities to output only so pairing uses passkey instead of pin
#define BTM_LOCAL_IO_CAPS BTM_IO_CAP_OUT
#endif

Binary file not shown.

View file

@ -0,0 +1,5 @@
# UART device port where Bluetooth controller is attached
UartPort = /dev/ttyMFD0
# Firmware patch file location
FwPatchFilePath = /data/misc/bluedroid/

View file

@ -0,0 +1,730 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!-- Copyright (C) 2012 The Android Open Source Project
Copyright (c) 2015 Intel Corporation
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.
-->
<CodecResourcesLimitation>
<Codec name="Decoder_AVC_0">
<codecType value="CODEC_TYPE_AVC"/>
<isEncoder value="false"/>
<isSecured value="false"/>
<resolutionType value="480"/>
<frameRate value="30"/>
<instanceLimit value="5"/>
</Codec>
<Codec name="Decoder_AVC_1">
<codecType value="CODEC_TYPE_AVC"/>
<isEncoder value="false"/>
<isSecured value="false"/>
<resolutionType value="480"/>
<frameRate value="60"/>
<instanceLimit value="5"/>
</Codec>
<Codec name="Decoder_AVC_2">
<codecType value="CODEC_TYPE_AVC"/>
<isEncoder value="false"/>
<isSecured value="false"/>
<resolutionType value="720"/>
<frameRate value="30"/>
<instanceLimit value="5"/>
</Codec>
<Codec name="Decoder_AVC_3">
<codecType value="CODEC_TYPE_AVC"/>
<isEncoder value="false"/>
<isSecured value="false"/>
<resolutionType value="720"/>
<frameRate value="60"/>
<instanceLimit value="4"/>
</Codec>
<Codec name="Decoder_AVC_4">
<codecType value="CODEC_TYPE_AVC"/>
<isEncoder value="false"/>
<isSecured value="false"/>
<resolutionType value="1080"/>
<frameRate value="30"/>
<instanceLimit value="4"/>
</Codec>
<Codec name="Decoder_AVC_5">
<codecType value="CODEC_TYPE_AVC"/>
<isEncoder value="false"/>
<isSecured value="false"/>
<resolutionType value="1080"/>
<frameRate value="60"/>
<instanceLimit value="3"/>
</Codec>
<Codec name="Decoder_AVC_6">
<codecType value="CODEC_TYPE_AVC"/>
<isEncoder value="false"/>
<isSecured value="false"/>
<resolutionType value="2K"/>
<frameRate value="30"/>
<instanceLimit value="1"/>
</Codec>
<Codec name="Decoder_AVC_7">
<codecType value="CODEC_TYPE_AVC"/>
<isEncoder value="false"/>
<isSecured value="false"/>
<resolutionType value="2K"/>
<frameRate value="60"/>
<instanceLimit value="1"/>
</Codec>
<Codec name="Decoder_AVC_8">
<codecType value="CODEC_TYPE_AVC"/>
<isEncoder value="false"/>
<isSecured value="false"/>
<resolutionType value="4K"/>
<frameRate value="30"/>
<instanceLimit value="0"/>
</Codec>
<Codec name="Decoder_AVC_9">
<codecType value="CODEC_TYPE_AVC"/>
<isEncoder value="false"/>
<isSecured value="false"/>
<resolutionType value="4K"/>
<frameRate value="60"/>
<instanceLimit value="0"/>
</Codec>
<Codec name="Decoder_AVC_10">
<codecType value="CODEC_TYPE_AVC"/>
<isEncoder value="false"/>
<isSecured value="true"/>
<resolutionType value="480"/>
<frameRate value="30"/>
<instanceLimit value="1"/>
</Codec>
<Codec name="Decoder_AVC_11">
<codecType value="CODEC_TYPE_AVC"/>
<isEncoder value="false"/>
<isSecured value="true"/>
<resolutionType value="720"/>
<frameRate value="30"/>
<instanceLimit value="1"/>
</Codec>
<Codec name="Decoder_AVC_12">
<codecType value="CODEC_TYPE_AVC"/>
<isEncoder value="false"/>
<isSecured value="true"/>
<resolutionType value="1080"/>
<frameRate value="30"/>
<instanceLimit value="1"/>
</Codec>
<Codec name="Decoder_HEVC_0">
<codecType value="CODEC_TYPE_HEVC"/>
<isEncoder value="false"/>
<isSecured value="false"/>
<resolutionType value="480"/>
<frameRate value="30"/>
<instanceLimit value="5"/>
</Codec>
<Codec name="Decoder_HEVC_1">
<codecType value="CODEC_TYPE_HEVC"/>
<isEncoder value="false"/>
<isSecured value="false"/>
<resolutionType value="480"/>
<frameRate value="60"/>
<instanceLimit value="2"/>
</Codec>
<Codec name="Decoder_HEVC_2">
<codecType value="CODEC_TYPE_HEVC"/>
<isEncoder value="false"/>
<isSecured value="false"/>
<resolutionType value="720"/>
<frameRate value="30"/>
<instanceLimit value="5"/>
</Codec>
<Codec name="Decoder_HEVC_3">
<codecType value="CODEC_TYPE_HEVC"/>
<isEncoder value="false"/>
<isSecured value="false"/>
<resolutionType value="720"/>
<frameRate value="60"/>
<instanceLimit value="2"/>
</Codec>
<Codec name="Decoder_HEVC_4">
<codecType value="CODEC_TYPE_HEVC"/>
<isEncoder value="false"/>
<isSecured value="false"/>
<resolutionType value="1080"/>
<frameRate value="30"/>
<instanceLimit value="1"/>
</Codec>
<Codec name="Decoder_HEVC_5">
<codecType value="CODEC_TYPE_HEVC"/>
<isEncoder value="false"/>
<isSecured value="false"/>
<resolutionType value="1080"/>
<frameRate value="60"/>
<instanceLimit value="0"/>
</Codec>
<Codec name="Decoder_HEVC_6">
<codecType value="CODEC_TYPE_HEVC"/>
<isEncoder value="false"/>
<isSecured value="false"/>
<resolutionType value="2K"/>
<frameRate value="30"/>
<instanceLimit value="0"/>
</Codec>
<Codec name="Decoder_HEVC_7">
<codecType value="CODEC_TYPE_HEVC"/>
<isEncoder value="false"/>
<isSecured value="false"/>
<resolutionType value="2K"/>
<frameRate value="60"/>
<instanceLimit value="0"/>
</Codec>
<Codec name="Decoder_HEVC_8">
<codecType value="CODEC_TYPE_HEVC"/>
<isEncoder value="false"/>
<isSecured value="false"/>
<resolutionType value="4K"/>
<frameRate value="30"/>
<instanceLimit value="0"/>
</Codec>
<Codec name="Decoder_HEVC_9">
<codecType value="CODEC_TYPE_HEVC"/>
<isEncoder value="false"/>
<isSecured value="false"/>
<resolutionType value="4K"/>
<frameRate value="60"/>
<instanceLimit value="0"/>
</Codec>
<Codec name="Decoder_VP8_0">
<codecType value="CODEC_TYPE_VP8"/>
<isEncoder value="false"/>
<isSecured value="false"/>
<resolutionType value="480"/>
<frameRate value="30"/>
<instanceLimit value="5"/>
</Codec>
<Codec name="Decoder_VP8_1">
<codecType value="CODEC_TYPE_VP8"/>
<isEncoder value="false"/>
<isSecured value="false"/>
<resolutionType value="480"/>
<frameRate value="60"/>
<instanceLimit value="3"/>
</Codec>
<Codec name="Decoder_VP8_2">
<codecType value="CODEC_TYPE_VP8"/>
<isEncoder value="false"/>
<isSecured value="false"/>
<resolutionType value="720"/>
<frameRate value="30"/>
<instanceLimit value="5"/>
</Codec>
<Codec name="Decoder_VP8_3">
<codecType value="CODEC_TYPE_VP8"/>
<isEncoder value="false"/>
<isSecured value="false"/>
<resolutionType value="720"/>
<frameRate value="60"/>
<instanceLimit value="3"/>
</Codec>
<Codec name="Decoder_VP8_4">
<codecType value="CODEC_TYPE_VP8"/>
<isEncoder value="false"/>
<isSecured value="false"/>
<resolutionType value="1080"/>
<frameRate value="30"/>
<instanceLimit value="3"/>
</Codec>
<Codec name="Decoder_VP8_5">
<codecType value="CODEC_TYPE_VP8"/>
<isEncoder value="false"/>
<isSecured value="false"/>
<resolutionType value="1080"/>
<frameRate value="60"/>
<instanceLimit value="1"/>
</Codec>
<Codec name="Decoder_VP8_6">
<codecType value="CODEC_TYPE_VP8"/>
<isEncoder value="false"/>
<isSecured value="false"/>
<resolutionType value="2K"/>
<frameRate value="30"/>
<instanceLimit value="0"/>
</Codec>
<Codec name="Decoder_VP8_7">
<codecType value="CODEC_TYPE_VP8"/>
<isEncoder value="false"/>
<isSecured value="false"/>
<resolutionType value="2K"/>
<frameRate value="60"/>
<instanceLimit value="0"/>
</Codec>
<Codec name="Decoder_VP8_8">
<codecType value="CODEC_TYPE_VP8"/>
<isEncoder value="false"/>
<isSecured value="false"/>
<resolutionType value="4K"/>
<frameRate value="30"/>
<instanceLimit value="0"/>
</Codec>
<Codec name="Decoder_VP8_9">
<codecType value="CODEC_TYPE_VP8"/>
<isEncoder value="false"/>
<isSecured value="false"/>
<resolutionType value="4K"/>
<frameRate value="60"/>
<instanceLimit value="0"/>
</Codec>
<Codec name="Decoder_VP9_0">
<codecType value="CODEC_TYPE_VP9"/>
<isEncoder value="false"/>
<isSecured value="false"/>
<resolutionType value="480"/>
<frameRate value="30"/>
<instanceLimit value="2"/>
</Codec>
<Codec name="Decoder_VP9_1">
<codecType value="CODEC_TYPE_VP9"/>
<isEncoder value="false"/>
<isSecured value="false"/>
<resolutionType value="480"/>
<frameRate value="60"/>
<instanceLimit value="1"/>
</Codec>
<Codec name="Decoder_VP9_2">
<codecType value="CODEC_TYPE_VP9"/>
<isEncoder value="false"/>
<isSecured value="false"/>
<resolutionType value="720"/>
<frameRate value="30"/>
<instanceLimit value="2"/>
</Codec>
<Codec name="Decoder_VP9_3">
<codecType value="CODEC_TYPE_VP9"/>
<isEncoder value="false"/>
<isSecured value="false"/>
<resolutionType value="720"/>
<frameRate value="60"/>
<instanceLimit value="1"/>
</Codec>
<Codec name="Decoder_VP9_4">
<codecType value="CODEC_TYPE_VP9"/>
<isEncoder value="false"/>
<isSecured value="false"/>
<resolutionType value="1080"/>
<frameRate value="30"/>
<instanceLimit value="1"/>
</Codec>
<Codec name="Decoder_VP9_5">
<codecType value="CODEC_TYPE_VP9"/>
<isEncoder value="false"/>
<isSecured value="false"/>
<resolutionType value="1080"/>
<frameRate value="60"/>
<instanceLimit value="0"/>
</Codec>
<Codec name="Decoder_VP9_6">
<codecType value="CODEC_TYPE_VP9"/>
<isEncoder value="false"/>
<isSecured value="false"/>
<resolutionType value="2K"/>
<frameRate value="30"/>
<instanceLimit value="0"/>
</Codec>
<Codec name="Decoder_VP9_7">
<codecType value="CODEC_TYPE_VP9"/>
<isEncoder value="false"/>
<isSecured value="false"/>
<resolutionType value="2K"/>
<frameRate value="60"/>
<instanceLimit value="0"/>
</Codec>
<Codec name="Decoder_VP9_8">
<codecType value="CODEC_TYPE_VP9"/>
<isEncoder value="false"/>
<isSecured value="false"/>
<resolutionType value="4K"/>
<frameRate value="30"/>
<instanceLimit value="0"/>
</Codec>
<Codec name="Decoder_VP9_9">
<codecType value="CODEC_TYPE_VP9"/>
<isEncoder value="false"/>
<isSecured value="false"/>
<resolutionType value="4K"/>
<frameRate value="60"/>
<instanceLimit value="0"/>
</Codec>
<Codec name="Decoder_MPEG4_0">
<codecType value="CODEC_TYPE_MPEG4"/>
<isEncoder value="false"/>
<isSecured value="false"/>
<resolutionType value="480"/>
<frameRate value="30"/>
<instanceLimit value="4"/>
</Codec>
<Codec name="Decoder_MPEG4_1">
<codecType value="CODEC_TYPE_MPEG4"/>
<isEncoder value="false"/>
<isSecured value="false"/>
<resolutionType value="480"/>
<frameRate value="60"/>
<instanceLimit value="2"/>
</Codec>
<Codec name="Decoder_MPEG4_2">
<codecType value="CODEC_TYPE_MPEG4"/>
<isEncoder value="false"/>
<isSecured value="false"/>
<resolutionType value="720"/>
<frameRate value="30"/>
<instanceLimit value="4"/>
</Codec>
<Codec name="Decoder_MPEG4_3">
<codecType value="CODEC_TYPE_MPEG4"/>
<isEncoder value="false"/>
<isSecured value="false"/>
<resolutionType value="720"/>
<frameRate value="60"/>
<instanceLimit value="2"/>
</Codec>
<Codec name="Decoder_MPEG4_4">
<codecType value="CODEC_TYPE_MPEG4"/>
<isEncoder value="false"/>
<isSecured value="false"/>
<resolutionType value="1080"/>
<frameRate value="30"/>
<instanceLimit value="3"/>
</Codec>
<Codec name="Decoder_MPEG4_5">
<codecType value="CODEC_TYPE_MPEG4"/>
<isEncoder value="false"/>
<isSecured value="false"/>
<resolutionType value="1080"/>
<frameRate value="60"/>
<instanceLimit value="2"/>
</Codec>
<Codec name="Decoder_MPEG4_6">
<codecType value="CODEC_TYPE_MPEG4"/>
<isEncoder value="false"/>
<isSecured value="false"/>
<resolutionType value="2K"/>
<frameRate value="30"/>
<instanceLimit value="0"/>
</Codec>
<Codec name="Decoder_MPEG4_7">
<codecType value="CODEC_TYPE_MPEG4"/>
<isEncoder value="false"/>
<isSecured value="false"/>
<resolutionType value="2K"/>
<frameRate value="60"/>
<instanceLimit value="0"/>
</Codec>
<Codec name="Decoder_MPEG4_8">
<codecType value="CODEC_TYPE_MPEG4"/>
<isEncoder value="false"/>
<isSecured value="false"/>
<resolutionType value="4K"/>
<frameRate value="30"/>
<instanceLimit value="0"/>
</Codec>
<Codec name="Decoder_MPEG4_9">
<codecType value="CODEC_TYPE_MPEG4"/>
<isEncoder value="false"/>
<isSecured value="false"/>
<resolutionType value="4K"/>
<frameRate value="60"/>
<instanceLimit value="0"/>
</Codec>
<Codec name="Decoder_MPEG2_0">
<codecType value="CODEC_TYPE_MPEG2"/>
<isEncoder value="false"/>
<isSecured value="false"/>
<resolutionType value="480"/>
<frameRate value="30"/>
<instanceLimit value="4"/>
</Codec>
<Codec name="Decoder_MPEG2_1">
<codecType value="CODEC_TYPE_MPEG2"/>
<isEncoder value="false"/>
<isSecured value="false"/>
<resolutionType value="480"/>
<frameRate value="60"/>
<instanceLimit value="2"/>
</Codec>
<Codec name="Decoder_MPEG2_2">
<codecType value="CODEC_TYPE_MPEG2"/>
<isEncoder value="false"/>
<isSecured value="false"/>
<resolutionType value="720"/>
<frameRate value="30"/>
<instanceLimit value="4"/>
</Codec>
<Codec name="Decoder_MPEG2_3">
<codecType value="CODEC_TYPE_MPEG2"/>
<isEncoder value="false"/>
<isSecured value="false"/>
<resolutionType value="720"/>
<frameRate value="60"/>
<instanceLimit value="2"/>
</Codec>
<Codec name="Decoder_MPEG2_4">
<codecType value="CODEC_TYPE_MPEG2"/>
<isEncoder value="false"/>
<isSecured value="false"/>
<resolutionType value="1080"/>
<frameRate value="30"/>
<instanceLimit value="3"/>
</Codec>
<Codec name="Decoder_MPEG2_5">
<codecType value="CODEC_TYPE_MPEG2"/>
<isEncoder value="false"/>
<isSecured value="false"/>
<resolutionType value="1080"/>
<frameRate value="60"/>
<instanceLimit value="2"/>
</Codec>
<Codec name="Decoder_MPEG2_6">
<codecType value="CODEC_TYPE_MPEG2"/>
<isEncoder value="false"/>
<isSecured value="false"/>
<resolutionType value="2K"/>
<frameRate value="30"/>
<instanceLimit value="0"/>
</Codec>
<Codec name="Decoder_MPEG2_7">
<codecType value="CODEC_TYPE_MPEG2"/>
<isEncoder value="false"/>
<isSecured value="false"/>
<resolutionType value="2K"/>
<frameRate value="60"/>
<instanceLimit value="0"/>
</Codec>
<Codec name="Decoder_MPEG2_8">
<codecType value="CODEC_TYPE_MPEG2"/>
<isEncoder value="false"/>
<isSecured value="false"/>
<resolutionType value="4K"/>
<frameRate value="30"/>
<instanceLimit value="0"/>
</Codec>
<Codec name="Decoder_MPEG2_9">
<codecType value="CODEC_TYPE_MPEG2"/>
<isEncoder value="false"/>
<isSecured value="false"/>
<resolutionType value="4K"/>
<frameRate value="60"/>
<instanceLimit value="0"/>
</Codec>
<Codec name="Decoder_H263_0">
<codecType value="CODEC_TYPE_H263"/>
<isEncoder value="false"/>
<isSecured value="false"/>
<resolutionType value="480"/>
<frameRate value="30"/>
<instanceLimit value="1"/>
</Codec>
<Codec name="Decoder_H263_1">
<codecType value="CODEC_TYPE_H263"/>
<isEncoder value="false"/>
<isSecured value="false"/>
<resolutionType value="480"/>
<frameRate value="60"/>
<instanceLimit value="1"/>
</Codec>
<Codec name="Decoder_H263_2">
<codecType value="CODEC_TYPE_H263"/>
<isEncoder value="false"/>
<isSecured value="false"/>
<resolutionType value="720"/>
<frameRate value="30"/>
<instanceLimit value="1"/>
</Codec>
<Codec name="Decoder_H263_3">
<codecType value="CODEC_TYPE_H263"/>
<isEncoder value="false"/>
<isSecured value="false"/>
<resolutionType value="720"/>
<frameRate value="60"/>
<instanceLimit value="1"/>
</Codec>
<Codec name="Decoder_H263_4">
<codecType value="CODEC_TYPE_H263"/>
<isEncoder value="false"/>
<isSecured value="false"/>
<resolutionType value="1080"/>
<frameRate value="30"/>
<instanceLimit value="0"/>
</Codec>
<Codec name="Decoder_H263_5">
<codecType value="CODEC_TYPE_H263"/>
<isEncoder value="false"/>
<isSecured value="false"/>
<resolutionType value="1080"/>
<frameRate value="60"/>
<instanceLimit value="0"/>
</Codec>
<Codec name="Decoder_H263_6">
<codecType value="CODEC_TYPE_H263"/>
<isEncoder value="false"/>
<isSecured value="false"/>
<resolutionType value="2K"/>
<frameRate value="30"/>
<instanceLimit value="0"/>
</Codec>
<Codec name="Decoder_H263_7">
<codecType value="CODEC_TYPE_H263"/>
<isEncoder value="false"/>
<isSecured value="false"/>
<resolutionType value="2K"/>
<frameRate value="60"/>
<instanceLimit value="0"/>
</Codec>
<Codec name="Decoder_H263_8">
<codecType value="CODEC_TYPE_H263"/>
<isEncoder value="false"/>
<isSecured value="false"/>
<resolutionType value="4K"/>
<frameRate value="30"/>
<instanceLimit value="0"/>
</Codec>
<Codec name="Decoder_H263_9">
<codecType value="CODEC_TYPE_H263"/>
<isEncoder value="false"/>
<isSecured value="false"/>
<resolutionType value="4K"/>
<frameRate value="60"/>
<instanceLimit value="0"/>
</Codec>
<Codec name="Encoder_AVC_0">
<codecType value="CODEC_TYPE_AVC"/>
<isEncoder value="true"/>
<isSecured value="false"/>
<resolutionType value="480"/>
<frameRate value="30"/>
<instanceLimit value="3"/>
</Codec>
<Codec name="Encoder_AVC_1">
<codecType value="CODEC_TYPE_AVC"/>
<isEncoder value="true"/>
<isSecured value="false"/>
<resolutionType value="720"/>
<frameRate value="30"/>
<instanceLimit value="3"/>
</Codec>
<Codec name="Encoder_AVC_2">
<codecType value="CODEC_TYPE_AVC"/>
<isEncoder value="true"/>
<isSecured value="false"/>
<resolutionType value="1080"/>
<frameRate value="30"/>
<instanceLimit value="3"/>
</Codec>
<Codec name="Encoder_VP8_0">
<codecType value="CODEC_TYPE_VP8"/>
<isEncoder value="true"/>
<isSecured value="false"/>
<resolutionType value="480"/>
<frameRate value="30"/>
<instanceLimit value="3"/>
</Codec>
<Codec name="Encoder_VP8_1">
<codecType value="CODEC_TYPE_VP8"/>
<isEncoder value="true"/>
<isSecured value="false"/>
<resolutionType value="720"/>
<frameRate value="30"/>
<instanceLimit value="3"/>
</Codec>
<Codec name="Encoder_VP8_2">
<codecType value="CODEC_TYPE_VP8"/>
<isEncoder value="true"/>
<isSecured value="false"/>
<resolutionType value="1080"/>
<frameRate value="30"/>
<instanceLimit value="3"/>
</Codec>
</CodecResourcesLimitation>

View file

@ -0,0 +1,59 @@
<compatibility-matrix version="1.0" type="device">
<hal format="hidl" optional="false">
<name>android.frameworks.schedulerservice</name>
<version>1.0</version>
<interface>
<name>ISchedulingPolicyService</name>
<instance>default</instance>
</interface>
</hal>
<hal format="hidl" optional="false">
<name>android.frameworks.sensorservice</name>
<version>1.0</version>
<interface>
<name>ISensorManager</name>
<instance>default</instance>
</interface>
</hal>
<hal format="hidl" optional="false">
<name>android.hidl.allocator</name>
<version>1.0</version>
<interface>
<name>IAllocator</name>
<instance>ashmem</instance>
</interface>
</hal>
<hal format="hidl" optional="false">
<name>android.hidl.manager</name>
<version>1.0</version>
<interface>
<name>IServiceManager</name>
<instance>default</instance>
</interface>
</hal>
<hal format="hidl" optional="false">
<name>android.hidl.memory</name>
<version>1.0</version>
<interface>
<name>IMapper</name>
<instance>ashmem</instance>
</interface>
</hal>
<hal format="hidl" optional="false">
<name>android.hidl.token</name>
<version>1.0</version>
<interface>
<name>ITokenManager</name>
<instance>default</instance>
</interface>
</hal>
<hal format="hidl" optional="false">
<name>android.system.wifi.keystore</name>
<version>1.0</version>
<interface>
<name>IKeystore</name>
<instance>default</instance>
</interface>
</hal>
</compatibility-matrix>

View file

@ -0,0 +1,358 @@
#
# Copyright 2013 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.
#
KERNEL_SRC_DIR ?= linux/kernel-fugu
KERNEL_CFG_NAME ?= fugu
TARGET_KERNEL_ARCH ?= x86_64
# Check for availability of kernel source
ifneq ($(wildcard $(KERNEL_SRC_DIR)/Makefile),)
# Give precedence to TARGET_PREBUILT_KERNEL
ifeq ($(TARGET_PREBUILT_KERNEL),)
TARGET_KERNEL_BUILT_FROM_SOURCE := true
endif
endif
ifneq ($(TARGET_KERNEL_BUILT_FROM_SOURCE), true)
# Use prebuilt kernel
ifeq ($(TARGET_PREBUILT_KERNEL),)
LOCAL_KERNEL := device/asus/fugu-kernel/bzImage
else
LOCAL_KERNEL := $(TARGET_PREBUILT_KERNEL)
endif
PRODUCT_COPY_FILES += \
$(LOCAL_KERNEL):kernel
endif #TARGET_KERNEL_BUILT_FROM_SOURCE
# Need AppWidget permission to prevent from Launcher's crash.
# TODO(pattjin): Remove this when the TV Launcher is used, which does not support AppWidget.
PRODUCT_COPY_FILES += \
frameworks/native/data/etc/android.software.app_widgets.xml:system/etc/permissions/android.software.app_widgets.xml
PRODUCT_AAPT_CONFIG := normal large xlarge hdpi xhdpi
PRODUCT_AAPT_PREF_CONFIG := xhdpi
# xhdpi, while we are hardcoding the 1080 resolution.
# when we start doing 720 as well, will need to stop hardcoding this.
PRODUCT_PROPERTY_OVERRIDES += \
ro.sf.lcd_density=320
# There may be a cleaner way to do this.
PRODUCT_PROPERTY_OVERRIDES += \
dalvik.vm.heapstartsize=8m \
dalvik.vm.heapgrowthlimit=128m \
dalvik.vm.heapsize=174m
$(call inherit-product-if-exists, frameworks/native/build/tablet-10in-xhdpi-2048-dalvik-heap.mk)
PRODUCT_CHARACTERISTICS := nosdcard,tv
DEVICE_PACKAGE_OVERLAYS := \
device/asus/fugu/overlay
PRODUCT_COPY_FILES += \
device/asus/fugu/fstab.fugu:root/fstab.fugu \
device/asus/fugu/init.fugu.rc:root/init.fugu.rc \
device/asus/fugu/init.fugu.usb.rc:root/init.fugu.usb.rc \
device/asus/fugu/ueventd.fugu.rc:root/ueventd.fugu.rc \
device/asus/fugu/init.recovery.fugu.rc:root/init.recovery.fugu.rc
# Audio
PRODUCT_PACKAGES += \
libtinyalsa \
audio.primary.fugu \
audio.stub.default \
audio.usb.default \
audio.a2dp.default \
audio.r_submix.default \
libaudio-resampler
PRODUCT_PACKAGES += \
android.hardware.audio@2.0-impl \
android.hardware.audio.effect@2.0-impl
# Keymaster HAL
PRODUCT_PACKAGES += \
android.hardware.keymaster@3.0-impl
# Dumpstate HAL
PRODUCT_PACKAGES += \
android.hardware.dumpstate@1.0-service.fugu
USE_CUSTOM_AUDIO_POLICY := 1
USE_XML_AUDIO_POLICY_CONF := 1
# specific management of audio_policy.conf
PRODUCT_COPY_FILES += \
device/asus/fugu/audio_policy_configuration.xml:$(TARGET_COPY_OUT_VENDOR)/etc/audio_policy_configuration.xml \
frameworks/av/services/audiopolicy/config/a2dp_audio_policy_configuration.xml:$(TARGET_COPY_OUT_VENDOR)/etc/a2dp_audio_policy_configuration.xml \
frameworks/av/services/audiopolicy/config/r_submix_audio_policy_configuration.xml:$(TARGET_COPY_OUT_VENDOR)/etc/r_submix_audio_policy_configuration.xml \
frameworks/av/services/audiopolicy/config/usb_audio_policy_configuration.xml:$(TARGET_COPY_OUT_VENDOR)/etc/usb_audio_policy_configuration.xml \
frameworks/av/services/audiopolicy/config/default_volume_tables.xml:$(TARGET_COPY_OUT_VENDOR)/etc/default_volume_tables.xml \
frameworks/av/services/audiopolicy/config/audio_policy_volumes.xml:$(TARGET_COPY_OUT_VENDOR)/etc/audio_policy_volumes.xml
# Hdmi CEC: Fugu works as a playback device (4).
PRODUCT_PROPERTY_OVERRIDES += ro.hdmi.device_type=4
# Hdmi CEC: Disable 'Set Menu Language' feature.
PRODUCT_PROPERTY_OVERRIDES += ro.hdmi.set_menu_language=false
# Keep secure decoders in mediaserver process
PRODUCT_PROPERTY_OVERRIDES += media.stagefright.less-secure=true
# Boot Animation
PRODUCT_COPY_FILES += \
device/asus/fugu/bootanimation-580-256col.zip:system/media/bootanimation.zip
# Bluetooth
PRODUCT_PACKAGES += \
bt_bcm4354
PRODUCT_COPY_FILES += \
device/asus/fugu/bt_vendor.conf:system/etc/bluetooth/bt_vendor.conf
# Bluetooth HAL
PRODUCT_PACKAGES += \
libbt-vendor \
android.hardware.bluetooth@1.0-impl
# IMG graphics
PRODUCT_PACKAGES += \
IMG_graphics \
hwcomposer.moorefield
PRODUCT_PACKAGES += \
android.hardware.graphics.allocator@2.0-impl \
android.hardware.graphics.composer@2.1-impl \
android.hardware.graphics.mapper@2.0-impl
# RenderScript HAL
PRODUCT_PACKAGES += \
android.hardware.renderscript@1.0-impl
# Video
PRODUCT_COPY_FILES += \
device/asus/fugu/media_profiles.xml:system/etc/media_profiles.xml \
device/asus/fugu/wrs_omxil_components.list:system/etc/wrs_omxil_components.list \
frameworks/av/media/libstagefright/data/media_codecs_google_audio.xml:system/etc/media_codecs_google_audio.xml \
frameworks/av/media/libstagefright/data/media_codecs_google_tv.xml:system/etc/media_codecs_google_tv.xml \
frameworks/av/media/libstagefright/data/media_codecs_google_video_le.xml:system/etc/media_codecs_google_video_le.xml \
device/asus/fugu/media_codecs.xml:system/etc/media_codecs.xml \
device/asus/fugu/media_codecs_performance.xml:system/etc/media_codecs_performance.xml \
device/asus/fugu/mfx_omxil_core.conf:system/etc/mfx_omxil_core.conf \
device/asus/fugu/video_isv_profile.xml:system/etc/video_isv_profile.xml \
device/asus/fugu/codec_resources_limitation.xml:system/etc/codec_resources_limitation.xml
# Default OMX service to non-Treble
PRODUCT_PROPERTY_OVERRIDES += \
persist.media.treble_omx=false
# psb video
PRODUCT_PACKAGES += \
pvr_drv_video
# Media SDK and OMX IL components
PRODUCT_PACKAGES += \
libmfxsw32 \
libmfx_omx_core \
libmfx_omx_components_sw \
libgabi++-mfx \
libstlport-mfx
#video firmware
PRODUCT_PACKAGES += \
msvdx.bin.0008.0000.0000 \
msvdx.bin.0008.0000.0001 \
msvdx.bin.0008.0002.0001 \
msvdx.bin.0008.0000.0002 \
msvdx.bin.000c.0001.0001 \
topaz.bin.0008.0000.0000 \
topaz.bin.0008.0000.0001 \
topaz.bin.0008.0000.0002 \
topaz.bin.0008.0002.0001 \
topaz.bin.000c.0001.0001 \
vsp.bin.0008.0000.0000 \
vsp.bin.0008.0000.0001 \
vsp.bin.0008.0000.0002 \
vsp.bin.0008.0002.0001 \
vsp.bin.000c.0001.0001
# libva
PRODUCT_PACKAGES += \
libva \
libva-android \
libva-tpi \
vainfo
#libstagefrighthw
PRODUCT_PACKAGES += \
libstagefrighthw
# libmix
PRODUCT_PACKAGES += \
libmixvbp_mpeg4 \
libmixvbp_h264 \
libmixvbp_h264secure \
libmixvbp_vc1 \
libmixvbp_vp8 \
libmixvbp_mpeg2 \
libmixvbp \
libva_videodecoder \
libva_videoencoder
PRODUCT_PACKAGES += \
libwrs_omxil_common \
libwrs_omxil_core_pvwrapped \
libOMXVideoDecoderAVC \
libOMXVideoDecoderH263 \
libOMXVideoDecoderMPEG4 \
libOMXVideoDecoderWMV \
libOMXVideoDecoderVP8 \
libOMXVideoDecoderMPEG2 \
libOMXVideoDecoderVP9HWR \
libOMXVideoDecoderVP9Hybrid \
libOMXVideoEncoderAVC \
libOMXVideoEncoderH263 \
libOMXVideoEncoderMPEG4 \
libOMXVideoEncoderVP8
#libISV
PRODUCT_PACKAGES += libisv_omx_core
# pvr
PRODUCT_PACKAGES += \
libpvr2d
# libdrm
PRODUCT_PACKAGES += \
libdrm \
dristat \
drmstat
# libion
PRODUCT_PACKAGES += \
libion
# Wifi
PRODUCT_PACKAGES += \
libwpa_client \
lib_driver_cmd_bcmdhd \
hostapd \
wificond \
wifilogd \
wpa_supplicant \
bcmdhd.cal \
bcmdhd_sr2.cal
PRODUCT_COPY_FILES += \
device/asus/fugu/wpa_supplicant.conf:/system/etc/wifi/wpa_supplicant.conf
PRODUCT_COPY_FILES += \
frameworks/native/data/etc/android.hardware.wifi.xml:system/etc/permissions/android.hardware.wifi.xml \
frameworks/native/data/etc/android.hardware.wifi.direct.xml:system/etc/permissions/android.hardware.wifi.direct.xml \
frameworks/native/data/etc/android.hardware.bluetooth_le.xml:system/etc/permissions/android.hardware.bluetooth_le.xml \
frameworks/native/data/etc/android.hardware.bluetooth.xml:system/etc/permissions/android.hardware.bluetooth.xml \
frameworks/native/data/etc/android.hardware.usb.host.xml:system/etc/permissions/android.hardware.usb.host.xml \
frameworks/native/data/etc/android.hardware.hdmi.cec.xml:system/etc/permissions/android.hardware.hdmi.cec.xml \
frameworks/native/data/etc/android.software.midi.xml:system/etc/permissions/android.software.midi.xml
# Key layout files
PRODUCT_COPY_FILES += \
device/asus/fugu/Nexus_Remote.idc:system/usr/idc/Nexus_Remote.idc \
device/asus/fugu/gpio-keys.idc:system/usr/idc/gpio-keys.idc \
device/asus/fugu/gpio-keys.kl:system/usr/keylayout/gpio-keys.kl \
device/asus/fugu/gpio-keys.kcm:system/usr/keychars/gpio-keys.kcm \
device/asus/fugu/Spike.kl:system/usr/keylayout/Spike.kl \
device/asus/fugu/Nexus_Remote.kl:system/usr/keylayout/Nexus_Remote.kl \
device/asus/fugu/Generic.kl:system/usr/keylayout/Generic.kl
#GFX Config
PRODUCT_COPY_FILES += \
device/asus/fugu/powervr.ini:system/etc/powervr.ini \
frameworks/native/data/etc/android.hardware.vulkan.level-0.xml:system/etc/permissions/android.hardware.vulkan.level-0.xml \
frameworks/native/data/etc/android.hardware.vulkan.version-1_0_3.xml:system/etc/permissions/android.hardware.vulkan.version-1_0_3.xml
# Thermal itux
ENABLE_ITUXD := true
PRODUCT_PACKAGES += \
ituxd
# Memtrack HAL
PRODUCT_PACKAGES += \
android.hardware.memtrack@1.0-impl
# Power HAL
PRODUCT_PACKAGES += \
power.fugu \
android.hardware.power@1.0-impl \
# TV Input HAL
PRODUCT_PACKAGES += \
android.hardware.tv.input@1.0-impl
# HDMI CEC HAL
PRODUCT_PACKAGES += \
android.hardware.tv.cec@1.0-impl
PRODUCT_PACKAGES += \
android.hardware.drm@1.0-impl \
# Debug rc files
ifneq (,$(filter userdebug eng, $(TARGET_BUILD_VARIANT)))
PRODUCT_COPY_FILES += \
device/asus/fugu/init.fugu.diag.rc.userdebug:root/init.fugu.diag.rc
endif
$(call inherit-product-if-exists, vendor/asus/fugu/device-vendor.mk)
$(call inherit-product-if-exists, vendor/intel/PRIVATE/fugu/device-vendor.mk)
$(call inherit-product-if-exists, vendor/intel/moorefield/prebuilts/houdini/houdini.mk)
# Add WiFi Firmware
$(call inherit-product-if-exists, hardware/broadcom/wlan/bcmdhd/firmware/bcm4354/device-bcm.mk)
# specific management of sep_policy.conf
PRODUCT_COPY_FILES += \
device/asus/fugu/sep_policy.conf:system/etc/security/sep_policy.conf
#PRODUCT_CHARACTERISTICS := tablet
# Wifi country code
PRODUCT_COPY_FILES += \
device/asus/fugu/init.fugu.countrycode.sh:system/bin/init.fugu.countrycode.sh
# Some CTS tests will be skipped based on what the initial API level that
# shipped on device was.
PRODUCT_PROPERTY_OVERRIDES += \
ro.product.first_api_level=21
PRODUCT_DEFAULT_PROPERTY_OVERRIDES += \
ro.opengles.version=196609 \
ro.hwui.drop_shadow_cache_size=4.0 \
ro.hwui.gradient_cache_size=0.8 \
ro.hwui.layer_cache_size=32.0 \
ro.hwui.path_cache_size=24.0 \
ro.hwui.text_large_cache_width=2048 \
ro.hwui.text_large_cache_height=1024 \
ro.hwui.text_small_cache_width=1024 \
ro.hwui.text_small_cache_height=512 \
ro.hwui.texture_cache_flushrate=0.4 \
ro.hwui.texture_cache_size=48.0 \
PRODUCT_DEFAULT_PROPERTY_OVERRIDES += \
persist.intel.isv.vpp=1 \
persist.intel.isv.frc=1

View file

@ -0,0 +1,39 @@
# Copyright (C) 2016 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := android.hardware.dumpstate@1.0-service.fugu
LOCAL_INIT_RC := android.hardware.dumpstate@1.0-service.fugu.rc
LOCAL_MODULE_RELATIVE_PATH := hw
LOCAL_SRC_FILES := \
DumpstateDevice.cpp \
service.cpp
LOCAL_SHARED_LIBRARIES := \
android.hardware.dumpstate@1.0 \
libbase \
libcutils \
libdumpstateutil \
libhidlbase \
libhidltransport \
libhwbinder \
liblog \
libutils
LOCAL_MODULE_TAGS := optional
LOCAL_PROPRIETARY_MODULE := true
include $(BUILD_EXECUTABLE)

View file

@ -0,0 +1,139 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_TAG "dumpstate"
#include "DumpstateDevice.h"
#include "DumpstateUtil.h"
#include <errno.h>
#include <log/log.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
static const char base64[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static const char pad64 = '=';
using android::os::dumpstate::CommandOptions;
using android::os::dumpstate::DumpFileToFd;
using android::os::dumpstate::RunCommandToFd;
namespace android {
namespace hardware {
namespace dumpstate {
namespace V1_0 {
namespace implementation {
static void base64_output3(int out_fd, const unsigned char *src, int len)
{
dprintf(out_fd, "%c", base64[src[0] >> 2]);
dprintf(out_fd, "%c", base64[((src[0] & 0x03) << 4) | (src[1] >> 4)]);
if (len == 1) {
dprintf(out_fd, "==");
return;
}
dprintf(out_fd, "%c", base64[((src[1] & 0x0F) << 2) | (src[2] >> 6)]);
if (len == 2) {
dprintf(out_fd, "=");
return;
}
dprintf(out_fd, "%c", base64[src[2] & 0x3F]);
}
static void fugu_dump_base64(int out_fd, const char *path)
{
dprintf(out_fd, "------ (%s) ------\n", path);
int fd = open(path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW);
if (fd < 0) {
dprintf(out_fd, "*** %s: %s\n\n", path, strerror(errno));
return;
}
/* buffer size multiple of 3 for ease of use */
unsigned char buffer[1200];
int left = 0;
int count = 0;
for (;;) {
int ret = read(fd, &buffer[left], sizeof(buffer) - left);
if (ret <= 0) {
break;
}
left += ret;
int ofs = 0;
while (left > 2) {
base64_output3(out_fd, &buffer[ofs], 3);
left -= 3;
ofs += 3;
count += 4;
if (count > 72) {
dprintf(out_fd, "\n");
count = 0;
}
}
if (left) {
memmove(buffer, &buffer[ofs], left);
}
}
close(fd);
if (!left) {
dprintf(out_fd, "\n------ end ------\n");
return;
}
/* finish padding */
count = left;
while (count < 3) {
buffer[count++] = 0;
}
base64_output3(out_fd, buffer, left);
dprintf(out_fd, "\n------ end ------\n");
}
// Methods from ::android::hardware::dumpstate::V1_0::IDumpstateDevice follow.
Return<void> DumpstateDevice::dumpstateBoard(const hidl_handle& handle) {
if (handle == nullptr || handle->numFds < 1) {
ALOGE("no FDs\n");
return Void();
}
int fd = handle->data[0];
if (fd < 0) {
ALOGE("invalid FD: %d\n", handle->data[0]);
return Void();
}
DumpFileToFd(fd, "INTERRUPTS", "/proc/interrupts");
DumpFileToFd(fd, "last ipanic_console", "/data/dontpanic/ipanic_console");
DumpFileToFd(fd, "last ipanic_threads", "/data/dontpanic/ipanic_threads");
fugu_dump_base64(fd, "/dev/snd_atvr_mSBC");
fugu_dump_base64(fd, "/dev/snd_atvr_pcm");
return Void();
}
} // namespace implementation
} // namespace V1_0
} // namespace dumpstate
} // namespace hardware
} // namespace android

View file

@ -0,0 +1,50 @@
/*
* Copyright (C) 2016 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_HARDWARE_DUMPSTATE_V1_0_DUMPSTATEDEVICE_H
#define ANDROID_HARDWARE_DUMPSTATE_V1_0_DUMPSTATEDEVICE_H
#include <android/hardware/dumpstate/1.0/IDumpstateDevice.h>
#include <hidl/MQDescriptor.h>
#include <hidl/Status.h>
namespace android {
namespace hardware {
namespace dumpstate {
namespace V1_0 {
namespace implementation {
using ::android::hardware::dumpstate::V1_0::IDumpstateDevice;
using ::android::hardware::hidl_array;
using ::android::hardware::hidl_handle;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::sp;
struct DumpstateDevice : public IDumpstateDevice {
// Methods from ::android::hardware::dumpstate::V1_0::IDumpstateDevice follow.
Return<void> dumpstateBoard(const hidl_handle& h) override;
};
} // namespace implementation
} // namespace V1_0
} // namespace dumpstate
} // namespace hardware
} // namespace android
#endif // ANDROID_HARDWARE_DUMPSTATE_V1_0_DUMPSTATEDEVICE_H

View file

@ -0,0 +1,190 @@
Copyright (C) 2016 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.
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.
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS

View file

@ -0,0 +1,4 @@
service dumpstate-1-0 /vendor/bin/hw/android.hardware.dumpstate@1.0-service.guppy
class hal
user system
group system

View file

@ -0,0 +1,41 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_TAG "android.hardware.dumpstate@1.0-service.fugu"
#include <hidl/HidlSupport.h>
#include <hidl/HidlTransportSupport.h>
#include "DumpstateDevice.h"
using ::android::hardware::configureRpcThreadpool;
using ::android::hardware::dumpstate::V1_0::IDumpstateDevice;
using ::android::hardware::dumpstate::V1_0::implementation::DumpstateDevice;
using ::android::hardware::joinRpcThreadpool;
using ::android::OK;
using ::android::sp;
int main(int /* argc */, char* /* argv */ []) {
sp<IDumpstateDevice> dumpstate = new DumpstateDevice;
configureRpcThreadpool(1, true /* will join */);
if (dumpstate->registerAsService() != OK) {
ALOGE("Could not register service.");
return 1;
}
joinRpcThreadpool();
ALOGE("Service exited!");
return 1;
}

View file

@ -0,0 +1 @@
0 0 POWERVR_ROGUE

View file

@ -0,0 +1,24 @@
#!/bin/sh
# Copyright 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.
source ../../../common/clear-factory-images-variables.sh
BUILD=1472661
DEVICE=fugu
PRODUCT=fugu
VERSION=lrw90
SRCPREFIX=signed-
BOOTLOADER=fugu-02.05
source ../../../common/generate-factory-images-common.sh

View file

@ -0,0 +1,7 @@
/dev/block/by-name/system /system ext4 ro,noatime wait
/dev/block/by-name/cache /cache ext4 nosuid,nodev,noatime,barrier=1,data=ordered wait,check
/dev/block/by-name/userdata /data ext4 nosuid,nodev,noatime,barrier=1,data=ordered,noauto_da_alloc wait,check
/dev/block/by-name/factory /factory ext4 nosuid,nodev,noatime,barrier=1,data=ordered wait
/dev/block/by-name/misc /misc emmc defaults defaults
/dev/block/zram0 none swap defaults zramsize=104857600,notrim
/devices/*/dwc3-host.2/usb* auto auto defaults voldmanaged=usb:auto,encryptable=userdata

View file

@ -0,0 +1,23 @@
#
# Copyright 2013 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.
#
$(call inherit-product, device/asus/fugu/device.mk)
$(call inherit-product, device/google/atv/products/atv_base.mk)
PRODUCT_NAME := full_fugu
PRODUCT_DEVICE := fugu
PRODUCT_BRAND := Android
PRODUCT_MODEL := fugu
PRODUCT_MANUFACTURER := ASUS

View file

@ -0,0 +1,15 @@
# 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.
device.internal = 1

View file

@ -0,0 +1,15 @@
# 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.
type SPECIAL_FUNCTION

View file

@ -0,0 +1,15 @@
# 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.
key 218 PAIRING

View file

@ -0,0 +1,2 @@
#!/system/bin/sh
setprop ro.boot.wificountrycode `cat /factory/country`

View file

@ -0,0 +1,7 @@
# This file gets copied as /init.fugu.diag.rc
on boot
# Voice search logging collection
chmod 444 /dev/snd_atvr_pcm
chmod 444 /dev/snd_atvr_mSBC
chmod 444 /dev/snd_atvr_adpcm

View file

@ -0,0 +1,231 @@
#
# Copyright 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.
#
import init.fugu.usb.rc
import init.intel.tools.rc
import init.fugu.diag.rc
on early-init
mount debugfs debugfs /sys/kernel/debug mode=0755
# IMG Graphics
symlink /dev/dri/card0 /dev/card0
on init
# Android creates by-name disk links with the disk controller
# in the generated path, so that the names pulled out of the GPT
# can be associated with the correct disk. Create a shortcut to
# /dev/block/by-name so that we can use the same fstabs everywhere.
symlink /dev/block/pci/pci0000:00/0000:00:01.0/by-name /dev/block/by-name
symlink /sdcard /storage/sdcard0
# ZRAM options
write /sys/block/zram0/comp_algorithm lz4
write /sys/block/zram0/max_comp_streams 2
# KSM options
write /sys/kernel/mm/ksm/pages_to_scan 100
write /sys/kernel/mm/ksm/sleep_millisecs 500
write /sys/kernel/mm/ksm/run 1
# Mount the sep filesystem
mount sepfs sepfs /sys/fs/sepfs
on fs
mkdir /logs 0770 system log
mkdir /factory 0775 system system
mount_all ./fstab.fugu
swapon_all ./fstab.fugu
restorecon_recursive /factory
on early-boot
# set RLIMIT_MEMLOCK to 64MB
setrlimit 8 67108864 67108864
setprop ro.audio.flinger_standbytime_ms 600000
on boot
# Assign TCP buffer thresholds to be ceiling value of technology maximums
# Increased technology maximums should be reflected here.
write /proc/sys/net/core/rmem_max 1500000
write /proc/sys/net/core/wmem_max 1500000
write /proc/sys/net/ipv4/tcp_limit_output_bytes 1500000
setprop net.tcp.buffersize.wifi 500000,1000000,1500000,500000,1000000,1500000
chown system system /sys/class/backlight/psb-bl/brightness
chown system system /sys/class/backlight/psb-bl/max_brightness
chown system system /sys/class/backlight/psb-bl/actual_brightness
chmod 0664 /sys/class/backlight/psb-bl/brightness
chmod 0664 /sys/class/backlight/psb-bl/max_brightness
chmod 0664 /sys/class/backlight/psb-bl/actual_brightness
# Wifi
setprop wifi.interface wlan0
# Set correct country code
exec - root root system -- /system/bin/init.fugu.countrycode.sh
# Wifi firmware reload path
chown wifi wifi /sys/module/bcmdhd/parameters/firmware_path
on post-fs
# Performance tweaks for interactive governor
chown system system /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq
chmod 0660 /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq
chown system system /sys/devices/system/cpu/cpu1/cpufreq/scaling_max_freq
chmod 0660 /sys/devices/system/cpu/cpu1/cpufreq/scaling_max_freq
chown system system /sys/devices/system/cpu/cpu2/cpufreq/scaling_max_freq
chmod 0660 /sys/devices/system/cpu/cpu2/cpufreq/scaling_max_freq
chown system system /sys/devices/system/cpu/cpu3/cpufreq/scaling_max_freq
chmod 0660 /sys/devices/system/cpu/cpu3/cpufreq/scaling_max_freq
chown system system /sys/devices/system/cpu/cpufreq/interactive/timer_rate
chown system system /sys/devices/system/cpu/cpufreq/interactive/go_hispeed_load
chown system system /sys/devices/system/cpu/cpufreq/interactive/boostpulse
chown system system /sys/devices/system/cpu/cpufreq/interactive/touchboostpulse
chown system system /sys/devices/system/cpu/cpufreq/interactive/touchboostpulse_duration
chown system system /sys/devices/system/cpu/cpufreq/interactive/touchboost_freq
chmod 0220 /sys/devices/system/cpu/cpufreq/interactive/touchboostpulse
chmod 0220 /sys/devices/system/cpu/cpufreq/interactive/boostpulse
# Tune interactive governor parameters for Android TV UI animations
write /sys/devices/system/cpu/cpufreq/interactive/timer_rate 4000
write /sys/devices/system/cpu/cpufreq/interactive/timer_slack 16000
write /sys/devices/system/cpu/cpufreq/interactive/go_hispeed_load 90
write /sys/devices/system/cpu/cpufreq/interactive/target_loads 70
write /sys/devices/system/cpu/cpufreq/interactive/boostpulse_duration 800000
# SEP
copy /system/etc/security/sep_policy.conf /sys/fs/sepfs/load
chown system system /dev/dx_sep_q0
chmod 0666 /dev/dx_sep_q0
# hdmi cec
chown system system /sys/module/drm_intel_mid/parameters/hdmi_state
chmod 0440 /sys/module/drm_intel_mid/parameters/hdmi_state
chown system system /sys/module/drm_intel_mid/parameters/hdmi_edid_src_phy_addr
chmod 0440 /sys/module/drm_intel_mid/parameters/hdmi_edid_src_phy_addr
on post-fs-data
# Create the directories used by the Wireless subsystem
mkdir /data/misc/wifi 0770 wifi wifi
mkdir /data/misc/wifi/sockets 0770 wifi wifi
mkdir /data/misc/dhcp 0770 dhcp wifi
# Bluetooth
setprop ro.bt.bdaddr_path "/factory/bt/bd_addr.conf"
chmod 0660 /sys/class/rfkill/rfkill2/state
chown bluetooth bluetooth /sys/class/rfkill/rfkill2/state
chown bluetooth bluetooth /sys/class/rfkill/rfkill2/type
# Create directory used by audio subsystem
mkdir /data/misc/audio 0770 audio audio
mkdir /data/system 0775 system system
setprop vold.post_fs_data_done 1
setprop init.post_fs_data.bootreason ${ro.boot.bootreason}
# itux
# Set this property to enable Thermal service
setprop persist.service.thermal 1
# Properties for Thermal Service
setprop persist.thermal.turbo.dynamic 1
setprop ro.thermal.ituxversion 3.0
setprop persist.thermal.shutdown.msg 0
setprop persist.thermal.shutdown.vibra 0
setprop persist.thermal.shutdown.tone 0
chown system system /sys/module/intel_mid_osip/parameters/force_shutdown_occured
chown system system /sys/module/intel_mid_osip/parameters/thermal_shutdown_occured
chown system system /sys/devices/platform/coretemp.0/temp2_threshold1
chown system system /sys/devices/platform/coretemp.0/temp2_threshold2
chown system system /sys/devices/virtual/thermal/thermal_zone6/emul_temp
chown system system /sys/devices/virtual/thermal/thermal_zone7/emul_temp
# Stop led blinking and reduce brightness
write /sys/class/leds/white/device/led_lighting_effect 1
write /sys/class/leds/white/brightness 0
# Playready
mkdir /data/mediadrm/playready/ 0770 mediadrm mediadrm
copy /system/vendor/firmware/PR-ModelCert /data/mediadrm/playready/bgroupcert.dat
chown mediadrm mediadrm /data/mediadrm/playready/bgroupcert.dat
chmod 0440 /data/mediadrm/playready/bgroupcert.dat
on property:init.post_fs_data.bootreason=panic
# Create dump dir and collect dumps. (use the same location as in init.rc)
mkdir /data/dontpanic 0750 root log
copy /proc/emmc_ipanic_console /data/dontpanic/ipanic_console
chown root log /data/dontpanic/ipanic_console
chmod 0640 /data/dontpanic/ipanic_console
copy /proc/emmc_ipanic_threads /data/dontpanic/ipanic_threads
chown root log /data/dontpanic/ipanic_threads
chmod 0640 /data/dontpanic/ipanic_threads
copy /proc/emmc_ipanic_gbuffer /data/dontpanic/ipanic_gbuffer
chown root log /data/dontpanic/ipanic_gbuffer
chmod 0640 /data/dontpanic/ipanic_gbuffer
# Clear panic partition
write /proc/emmc_ipanic_header 1
service wpa_supplicant /system/vendor/bin/hw/wpa_supplicant \
-iwlan0 -Dnl80211 -c/data/misc/wifi/wpa_supplicant.conf \
-m/data/misc/wifi/p2p_supplicant.conf \
-puse_p2p_group_interface=1p2p_device=1use_multi_chan_concurrent=1 \
-O/data/misc/wifi/sockets \
-e/data/misc/wifi/entropy.bin \
-g@android:wpa_wlan0
class main
socket wpa_wlan0 dgram 660 wifi wifi
disabled
oneshot
# Bluetooth related services
service BtFwLoader /system/bin/BtFwLoader
class main
group bluetooth
user bluetooth
oneshot
# bugreport is triggered by holding down volume down, volume up and power
service bugreport /system/bin/dumpstate -d -p -B -z \
-o /data/user_de/0/com.android.shell/files/bugreports/bugreport
class main
disabled
oneshot
keycodes 114 115 116
# interval:60s margin:20s
service watchdogd /sbin/watchdogd 60 20
class core
oneshot
seclabel u:r:watchdogd:s0
# Reset the watchdog counter once boot is completed
on property:sys.boot_completed=1
write /sys/devices/virtual/misc/watchdog/counter "0"
# Enable native bridge for target executables
on early-init
mount binfmt_misc binfmt_misc /proc/sys/fs/binfmt_misc
on property:ro.enable.native.bridge.exec=1
copy /system/etc/binfmt_misc/arm_exe /proc/sys/fs/binfmt_misc/register
copy /system/etc/binfmt_misc/arm_dyn /proc/sys/fs/binfmt_misc/register

View file

@ -0,0 +1,68 @@
# Copyright 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.
on init
mkdir /dev/bus
mkdir /dev/bus/usb
mkdir /dev/bus/usb/001
# set usb serial number
write /sys/class/android_usb/android0/iSerial ${ro.serialno}
on fs
mkdir /dev/usb-ffs 0770 shell shell
mkdir /dev/usb-ffs/adb 0770 shell shell
mount functionfs adb /dev/usb-ffs/adb uid=2000,gid=2000
write /sys/class/android_usb/android0/f_ffs/aliases adb
on post-fs-data
chown system system /sys/class/android_usb/android0/f_mass_storage/lun/file
chmod 0660 /sys/class/android_usb/android0/f_mass_storage/lun/file
chown system system /sys/class/android_usb/android0/f_rndis/ethaddr
chmod 0660 /sys/class/android_usb/android0/f_rndis/ethaddr
# Used to disable USB when switching states
on property:sys.usb.config=none
stop adbd
write /sys/class/android_usb/android0/enable 0
write /sys/class/android_usb/android0/bDeviceClass 0
setprop sys.usb.state ${sys.usb.config}
# adb only
on property:sys.usb.config=adb
write /sys/class/android_usb/android0/enable 0
write /sys/class/android_usb/android0/idVendor 18d1
write /sys/class/android_usb/android0/idProduct 4ee7
write /sys/class/android_usb/android0/functions ${sys.usb.config}
write /sys/bus/pci/devices/0000:00:02.3/sdis 0
write /sys/class/android_usb/android0/enable 1
start adbd
setprop sys.usb.state ${sys.usb.config}
# Used to set USB configuration at boot and to switch the configuration
# when changing the default configuration
on property:persist.sys.usb.config=*
setprop sys.usb.config ${persist.sys.usb.config}
# USB vBus status changed to normal
on property:sys.usb.vbus=normal
write /sys/class/usb_otg/otg0/a_bus_drop 0
# USB vBus status changed to warning
on property:sys.usb.vbus=warning
write /sys/class/usb_otg/otg0/a_bus_drop 0
# USB vBus status changed to critical
on property:sys.usb.vbus=critical
write /sys/class/usb_otg/otg0/a_bus_drop 1

View file

@ -0,0 +1,16 @@
on init
# Android creates by-name disk links with the disk controller
# in the generated path, so that the names pulled out of the GPT
# can be associated with the correct disk. Create a shortcut to
# /dev/block/by-name so that we can use the same fstabs everywhere.
symlink /dev/block/pci/pci0000:00/0000:00:01.0/by-name /dev/block/by-name
# interval:60s margin:20s
service watchdogd /sbin/watchdogd 60 20
oneshot
seclabel u:r:watchdogd:s0
# Reset the watchdog counter once boot is completed
on property:init.svc.recovery=running
write /sys/devices/virtual/misc/watchdog/counter "0"

View file

@ -0,0 +1,72 @@
/****************************************************************************
****************************************************************************
***
*** This header was automatically generated from a Linux kernel header
*** of the same name, to make information necessary for userspace to
*** call into the kernel available to libc. It contains only constants,
*** structures, and macros generated from the original header, and thus,
*** contains no copyrightable information.
***
*** To edit the content of this header, modify the corresponding
*** source file (e.g. under external/kernel-headers/original/) then
*** run bionic/libc/kernel/tools/update_all.py
***
*** Any manual change here will be lost the next time this script will
*** be run. You've been warned!
***
****************************************************************************
****************************************************************************/
#ifndef TTM_FENCE_USER_H
#define TTM_FENCE_USER_H
#ifndef _KERNEL
#include <stdint.h>
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#endif
#define TTM_FENCE_MAJOR 0
#define TTM_FENCE_MINOR 1
#define TTM_FENCE_PL 0
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define TTM_FENCE_DATE "080819"
struct ttm_fence_signaled_req {
uint32_t handle;
uint32_t fence_type;
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
int32_t flush;
uint32_t pad64;
};
struct ttm_fence_rep {
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
uint32_t signaled_types;
uint32_t fence_error;
};
union ttm_fence_signaled_arg {
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
struct ttm_fence_signaled_req req;
struct ttm_fence_rep rep;
};
#define TTM_FENCE_FINISH_MODE_LAZY (1 << 0)
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define TTM_FENCE_FINISH_MODE_NO_BLOCK (1 << 1)
struct ttm_fence_finish_req {
uint32_t handle;
uint32_t fence_type;
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
uint32_t mode;
uint32_t pad64;
};
union ttm_fence_finish_arg {
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
struct ttm_fence_finish_req req;
struct ttm_fence_rep rep;
};
struct ttm_fence_unref_arg {
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
uint32_t handle;
uint32_t pad64;
};
#define TTM_FENCE_SIGNALED 0x01
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define TTM_FENCE_FINISH 0x02
#define TTM_FENCE_UNREF 0x03
#endif

View file

@ -0,0 +1,126 @@
/****************************************************************************
****************************************************************************
***
*** This header was automatically generated from a Linux kernel header
*** of the same name, to make information necessary for userspace to
*** call into the kernel available to libc. It contains only constants,
*** structures, and macros generated from the original header, and thus,
*** contains no copyrightable information.
***
*** To edit the content of this header, modify the corresponding
*** source file (e.g. under external/kernel-headers/original/) then
*** run bionic/libc/kernel/tools/update_all.py
***
*** Any manual change here will be lost the next time this script will
*** be run. You've been warned!
***
****************************************************************************
****************************************************************************/
#ifndef _TTM_PLACEMENT_USER_H_
#define _TTM_PLACEMENT_USER_H_
#ifndef _KERNEL
#include <stdint.h>
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#else
#include <linux/kernel.h>
#endif
#include "ttm/ttm_placement.h"
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define TTM_PLACEMENT_MAJOR 0
#define TTM_PLACEMENT_MINOR 1
#define TTM_PLACEMENT_PL 0
#define TTM_PLACEMENT_DATE "080819"
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
struct ttm_pl_create_req {
uint64_t size;
uint32_t placement;
uint32_t page_alignment;
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
};
struct ttm_pl_create_ub_req {
uint64_t size;
uint64_t user_address;
int32_t fd;
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
uint32_t placement;
uint32_t page_alignment;
};
struct ttm_pl_rep {
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
uint64_t gpu_offset;
uint64_t bo_size;
uint64_t map_handle;
uint32_t placement;
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
uint32_t handle;
uint32_t sync_object_arg;
uint32_t pad64;
};
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
struct ttm_pl_setstatus_req {
uint32_t set_placement;
uint32_t clr_placement;
uint32_t handle;
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
uint32_t pad64;
};
struct ttm_pl_reference_req {
uint32_t handle;
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
uint32_t pad64;
};
#define TTM_PL_SYNCCPU_MODE_READ TTM_ACCESS_READ
#define TTM_PL_SYNCCPU_MODE_WRITE TTM_ACCESS_WRITE
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define TTM_PL_SYNCCPU_MODE_NO_BLOCK (1 << 2)
#define TTM_PL_SYNCCPU_MODE_TRYCACHED (1 << 3)
struct ttm_pl_synccpu_arg {
uint32_t handle;
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
uint32_t access_mode;
enum {
TTM_PL_SYNCCPU_OP_GRAB,
TTM_PL_SYNCCPU_OP_RELEASE
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
} op;
uint32_t pad64;
};
#define TTM_PL_WAITIDLE_MODE_LAZY (1 << 0)
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define TTM_PL_WAITIDLE_MODE_NO_BLOCK (1 << 1)
struct ttm_pl_waitidle_arg {
uint32_t handle;
uint32_t mode;
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
};
union ttm_pl_create_arg {
struct ttm_pl_create_req req;
struct ttm_pl_rep rep;
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
};
union ttm_pl_reference_arg {
struct ttm_pl_reference_req req;
struct ttm_pl_rep rep;
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
};
union ttm_pl_setstatus_arg {
struct ttm_pl_setstatus_req req;
struct ttm_pl_rep rep;
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
};
union ttm_pl_create_ub_arg {
struct ttm_pl_create_ub_req req;
struct ttm_pl_rep rep;
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
};
#define TTM_PL_CREATE 0x00
#define TTM_PL_REFERENCE 0x01
#define TTM_PL_UNREF 0x02
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define TTM_PL_SYNCCPU 0x03
#define TTM_PL_WAITIDLE 0x04
#define TTM_PL_SETSTATUS 0x05
#define TTM_PL_CREATE_UB 0x06
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#endif

View file

@ -0,0 +1,60 @@
/****************************************************************************
****************************************************************************
***
*** This header was automatically generated from a Linux kernel header
*** of the same name, to make information necessary for userspace to
*** call into the kernel available to libc. It contains only constants,
*** structures, and macros generated from the original header, and thus,
*** contains no copyrightable information.
***
*** To edit the content of this header, modify the corresponding
*** source file (e.g. under external/kernel-headers/original/) then
*** run bionic/libc/kernel/tools/update_all.py
***
*** Any manual change here will be lost the next time this script will
*** be run. You've been warned!
***
****************************************************************************
****************************************************************************/
#ifndef _TTM_PLACEMENT_H_
#define _TTM_PLACEMENT_H_
#define TTM_PL_SYSTEM 0
#define TTM_PL_TT 1
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define TTM_PL_VRAM 2
#define TTM_PL_PRIV0 3
#define TTM_PL_PRIV1 4
#define TTM_PL_PRIV2 5
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define TTM_PL_PRIV3 6
#define TTM_PL_PRIV4 7
#define TTM_PL_PRIV5 8
#define TTM_PL_SWAPPED 15
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define TTM_PL_FLAG_SYSTEM (1 << TTM_PL_SYSTEM)
#define TTM_PL_FLAG_TT (1 << TTM_PL_TT)
#define TTM_PL_FLAG_VRAM (1 << TTM_PL_VRAM)
#define TTM_PL_FLAG_PRIV0 (1 << TTM_PL_PRIV0)
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define TTM_PL_FLAG_PRIV1 (1 << TTM_PL_PRIV1)
#define TTM_PL_FLAG_PRIV2 (1 << TTM_PL_PRIV2)
#define TTM_PL_FLAG_PRIV3 (1 << TTM_PL_PRIV3)
#define TTM_PL_FLAG_PRIV4 (1 << TTM_PL_PRIV4)
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define TTM_PL_FLAG_PRIV5 (1 << TTM_PL_PRIV5)
#define TTM_PL_FLAG_SWAPPED (1 << TTM_PL_SWAPPED)
#define TTM_PL_MASK_MEM 0x0000FFFF
#define TTM_PL_FLAG_CACHED (1 << 16)
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define TTM_PL_FLAG_UNCACHED (1 << 17)
#define TTM_PL_FLAG_WC (1 << 18)
#define TTM_PL_FLAG_SHARED (1 << 20)
#define TTM_PL_FLAG_NO_EVICT (1 << 21)
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define TTM_PL_MASK_CACHING (TTM_PL_FLAG_CACHED | TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_WC)
#define TTM_PL_MASK_MEMTYPE (TTM_PL_MASK_MEM | TTM_PL_MASK_CACHING)
#define TTM_ACCESS_READ (1 << 0)
#define TTM_ACCESS_WRITE (1 << 1)
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#endif

View file

@ -0,0 +1,106 @@
/****************************************************************************
****************************************************************************
***
*** This header was automatically generated from a Linux kernel header
*** of the same name, to make information necessary for userspace to
*** call into the kernel available to libc. It contains only constants,
*** structures, and macros generated from the original header, and thus,
*** contains no copyrightable information.
***
*** To edit the content of this header, modify the corresponding
*** source file (e.g. under external/kernel-headers/original/) then
*** run bionic/libc/kernel/tools/update_all.py
***
*** Any manual change here will be lost the next time this script will
*** be run. You've been warned!
***
****************************************************************************
****************************************************************************/
#ifndef KCT_H_
#define KCT_H_
#include <linux/netlink.h>
#define EV_FLAGS_PRIORITY_LOW (1<<0)
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#ifndef MAX_SB_N
#define MAX_SB_N 32
#endif
#ifndef MAX_EV_N
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define MAX_EV_N 32
#endif
#define NETLINK_CRASHTOOL 27
#define ATTCHMT_ALIGN 4U
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
enum ct_ev_type {
CT_EV_STAT,
CT_EV_INFO,
CT_EV_ERROR,
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
CT_EV_CRASH,
CT_EV_LAST
};
enum ct_attchmt_type {
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
CT_ATTCHMT_DATA0,
CT_ATTCHMT_DATA1,
CT_ATTCHMT_DATA2,
CT_ATTCHMT_DATA3,
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
CT_ATTCHMT_DATA4,
CT_ATTCHMT_DATA5,
CT_ATTCHMT_BINARY,
CT_ATTCHMT_FILELIST
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
};
struct ct_attchmt {
__u32 size;
enum ct_attchmt_type type;
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
char data[];
} __aligned(4);
struct ct_event {
__u64 timestamp;
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
char submitter_name[MAX_SB_N];
char ev_name[MAX_EV_N];
enum ct_ev_type type;
__u32 attchmt_size;
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
__u32 flags;
struct ct_attchmt attachments[];
} __aligned(4);
enum kct_nlmsg_type {
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
KCT_EVENT,
KCT_SET_PID = 4200,
};
struct kct_packet {
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
struct nlmsghdr nlh;
struct ct_event event;
};
#define ATTCHMT_ALIGNMENT 4
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#ifndef KCT_ALIGN
#define __KCT_ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask))
#define __KCT_ALIGN(x, a) __KCT_ALIGN_MASK(x, (typeof(x))(a) - 1)
#define KCT_ALIGN(x, a) __KCT_ALIGN((x), (a))
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#endif
#define foreach_attchmt(Event, Attchmt) if ((Event)->attchmt_size) for ((Attchmt) = (Event)->attachments; (Attchmt) < (typeof(Attchmt))(((char *) (Event)->attachments) + (Event)->attchmt_size); (Attchmt) = (typeof(Attchmt))KCT_ALIGN(((size_t)(Attchmt)) + sizeof(*(Attchmt)) + (Attchmt)->size, ATTCHMT_ALIGNMENT))
#define MKFN(fn, ...) MKFN_N(fn, ##__VA_ARGS__, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)(__VA_ARGS__)
#define MKFN_N(fn, n0, n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n, ...) fn##n
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define kct_log(...) MKFN(__kct_log_, ##__VA_ARGS__)
#define __kct_log_4(Type, Submitter_name, Ev_name, flags) do { if (kct_alloc_event) { struct ct_event *__ev = kct_alloc_event(Submitter_name, Ev_name, Type, GFP_ATOMIC, flags); if (__ev) { kct_log_event(__ev, GFP_ATOMIC); } } } while (0)
#define __kct_log_5(Type, Submitter_name, Ev_name, flags, Data0) do { if (kct_alloc_event) { struct ct_event *__ev = kct_alloc_event(Submitter_name, Ev_name, Type, GFP_ATOMIC, flags); if (__ev) { if (Data0) kct_add_attchmt(&__ev, CT_ATTCHMT_DATA0, strlen(Data0) + 1, Data0, GFP_ATOMIC); kct_log_event(__ev, GFP_ATOMIC); } } } while (0)
#define __kct_log_6(Type, Submitter_name, Ev_name, flags, Data0, Data1) do { if (kct_alloc_event) { struct ct_event *__ev = kct_alloc_event(Submitter_name, Ev_name, Type, GFP_ATOMIC, flags); if (__ev) { if (Data0) kct_add_attchmt(&__ev, CT_ATTCHMT_DATA0, strlen(Data0) + 1, Data0, GFP_ATOMIC); if (Data1) kct_add_attchmt(&__ev, CT_ATTCHMT_DATA1, strlen(Data1) + 1, Data1, GFP_ATOMIC); kct_log_event(__ev, GFP_ATOMIC); } } } while (0)
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define __kct_log_7(Type, Submitter_name, Ev_name, flags, Data0, Data1, Data2) do { if (kct_alloc_event) { struct ct_event *__ev = kct_alloc_event(Submitter_name, Ev_name, Type, GFP_ATOMIC, flags); if (__ev) { if (Data0) kct_add_attchmt(&__ev, CT_ATTCHMT_DATA0, strlen(Data0) + 1, Data0, GFP_ATOMIC); if (Data1) kct_add_attchmt(&__ev, CT_ATTCHMT_DATA1, strlen(Data1) + 1, Data1, GFP_ATOMIC); if (Data2) kct_add_attchmt(&__ev, CT_ATTCHMT_DATA2, strlen(Data2) + 1, Data2, GFP_ATOMIC); kct_log_event(__ev, GFP_ATOMIC); } } } while (0)
#define __kct_log_8(Type, Submitter_name, Ev_name, flags, Data0, Data1, Data2, Data3) do { if (kct_alloc_event) { struct ct_event *__ev = kct_alloc_event(Submitter_name, Ev_name, Type, GFP_ATOMIC, flags); if (__ev) { if (Data0) kct_add_attchmt(&__ev, CT_ATTCHMT_DATA0, strlen(Data0) + 1, Data0, GFP_ATOMIC); if (Data1) kct_add_attchmt(&__ev, CT_ATTCHMT_DATA1, strlen(Data1) + 1, Data1, GFP_ATOMIC); if (Data2) kct_add_attchmt(&__ev, CT_ATTCHMT_DATA2, strlen(Data2) + 1, Data2, GFP_ATOMIC); if (Data3) kct_add_attchmt(&__ev, CT_ATTCHMT_DATA3, strlen(Data3) + 1, Data3, GFP_ATOMIC); kct_log_event(__ev, GFP_ATOMIC); } } } while (0)
#define __kct_log_9(Type, Submitter_name, Ev_name, flags, Data0, Data1, Data2, Data3, Data4) do { if (kct_alloc_event) { struct ct_event *__ev = kct_alloc_event(Submitter_name, Ev_name, Type, GFP_ATOMIC, flags); if (__ev) { if (Data0) kct_add_attchmt(&__ev, CT_ATTCHMT_DATA0, strlen(Data0) + 1, Data0, GFP_ATOMIC); if (Data1) kct_add_attchmt(&__ev, CT_ATTCHMT_DATA1, strlen(Data1) + 1, Data1, GFP_ATOMIC); if (Data2) kct_add_attchmt(&__ev, CT_ATTCHMT_DATA2, strlen(Data2) + 1, Data2, GFP_ATOMIC); if (Data3) kct_add_attchmt(&__ev, CT_ATTCHMT_DATA3, strlen(Data3) + 1, Data3, GFP_ATOMIC); if (Data4) kct_add_attchmt(&__ev, CT_ATTCHMT_DATA4, strlen(Data4) + 1, Data4, GFP_ATOMIC); kct_log_event(__ev, GFP_ATOMIC); } } } while (0)
#define __kct_log_10(Type, Submitter_name, Ev_name, flags, Data0, Data1, Data2, Data3, Data4, Data5) do { if (kct_alloc_event) { struct ct_event *__ev = kct_alloc_event(Submitter_name, Ev_name, Type, GFP_ATOMIC, flags); if (__ev) { if (Data0) kct_add_attchmt(&__ev, CT_ATTCHMT_DATA0, strlen(Data0) + 1, Data0, GFP_ATOMIC); if (Data1) kct_add_attchmt(&__ev, CT_ATTCHMT_DATA1, strlen(Data1) + 1, Data1, GFP_ATOMIC); if (Data2) kct_add_attchmt(&__ev, CT_ATTCHMT_DATA2, strlen(Data2) + 1, Data2, GFP_ATOMIC); if (Data3) kct_add_attchmt(&__ev, CT_ATTCHMT_DATA3, strlen(Data3) + 1, Data3, GFP_ATOMIC); if (Data4) kct_add_attchmt(&__ev, CT_ATTCHMT_DATA4, strlen(Data4) + 1, Data4, GFP_ATOMIC); if (Data5) kct_add_attchmt(&__ev, CT_ATTCHMT_DATA5, strlen(Data5) + 1, Data5, GFP_ATOMIC); kct_log_event(__ev, GFP_ATOMIC); } } } while (0)
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define __kct_log_11(Type, Submitter_name, Ev_name, flags, Data0, Data1, Data2, Data3, Data4, Data5, filelist) do { if (kct_alloc_event) { struct ct_event *__ev = kct_alloc_event(Submitter_name, Ev_name, Type, GFP_ATOMIC, flags); if (__ev) { if (Data0) kct_add_attchmt(&__ev, CT_ATTCHMT_DATA0, strlen(Data0) + 1, Data0, GFP_ATOMIC); if (Data1) kct_add_attchmt(&__ev, CT_ATTCHMT_DATA1, strlen(Data1) + 1, Data1, GFP_ATOMIC); if (Data2) kct_add_attchmt(&__ev, CT_ATTCHMT_DATA2, strlen(Data2) + 1, Data2, GFP_ATOMIC); if (Data3) kct_add_attchmt(&__ev, CT_ATTCHMT_DATA3, strlen(Data3) + 1, Data3, GFP_ATOMIC); if (Data4) kct_add_attchmt(&__ev, CT_ATTCHMT_DATA4, strlen(Data4) + 1, Data4, GFP_ATOMIC); if (Data5) kct_add_attchmt(&__ev, CT_ATTCHMT_DATA5, strlen(Data5) + 1, Data5, GFP_ATOMIC); if (filelist) kct_add_attchmt(&__ev, CT_ATTCHMT_FILELIST, strlen(filelist) + 1, filelist, GFP_ATOMIC); kct_log_event(__ev, GFP_ATOMIC); } } } while (0)
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,51 @@
/****************************************************************************
****************************************************************************
***
*** This header was automatically generated from a Linux kernel header
*** of the same name, to make information necessary for userspace to
*** call into the kernel available to libc. It contains only constants,
*** structures, and macros generated from the original header, and thus,
*** contains no copyrightable information.
***
*** To edit the content of this header, modify the corresponding
*** source file (e.g. under external/kernel-headers/original/) then
*** run bionic/libc/kernel/tools/update_all.py
***
*** Any manual change here will be lost the next time this script will
*** be run. You've been warned!
***
****************************************************************************
****************************************************************************/
#ifndef __INTEL_SST_IOCTL_H__
#define __INTEL_SST_IOCTL_H__
#include <linux/types.h>
struct snd_ppp_params {
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
__u8 algo_id;
__u8 str_id;
__u8 enable;
__u8 operation;
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
__u32 size;
void *params;
} __packed;
struct snd_sst_driver_info {
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
__u32 max_streams;
};
struct snd_sst_tuning_params {
__u8 type;
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
__u8 str_id;
__u8 size;
__u8 rsvd;
__u64 addr;
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
} __packed;
#define SNDRV_SST_DRIVER_INFO _IOR('L', 0x10, struct snd_sst_driver_info)
#define SNDRV_SST_SET_ALGO _IOW('L', 0x30, struct snd_ppp_params)
#define SNDRV_SST_GET_ALGO _IOWR('L', 0x31, struct snd_ppp_params)
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define SNDRV_SST_TUNING_PARAMS _IOW('L', 0x32, struct snd_sst_tuning_params)
#endif

View file

@ -0,0 +1,176 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_TAG "ATVAudioPolicyManager"
//#define LOG_NDEBUG 0
#include <media/AudioParameter.h>
#include <media/mediarecorder.h>
#include <utils/Log.h>
#include <utils/String16.h>
#include <utils/String8.h>
#include <utils/StrongPointer.h>
#include "AudioHardwareOutput.h"
#include "ATVAudioPolicyManager.h"
#ifdef REMOTE_CONTROL_INTERFACE
#include <IRemoteControlService.h>
#endif
namespace android {
extern AudioHardwareOutput gAudioHardwareOutput;
// ----------------------------------------------------------------------------
// Common audio policy manager code is implemented in AudioPolicyManager class
// ----------------------------------------------------------------------------
// --- class factory
extern "C" AudioPolicyInterface* createAudioPolicyManager(
AudioPolicyClientInterface *clientInterface)
{
return new ATVAudioPolicyManager(clientInterface);
}
extern "C" void destroyAudioPolicyManager(AudioPolicyInterface *interface)
{
delete interface;
}
ATVAudioPolicyManager::ATVAudioPolicyManager(
AudioPolicyClientInterface *clientInterface)
: AudioPolicyManager(clientInterface), mForceSubmixInputSelection(false)
{
}
float ATVAudioPolicyManager::computeVolume(audio_stream_type_t stream,
int index,
audio_devices_t device)
{
// We only use master volume, so all audio flinger streams
// should be set to maximum
(void)stream;
(void)index;
(void)device;
return 0.0; // no attenuation == 0.0dB
}
status_t ATVAudioPolicyManager::setDeviceConnectionState(audio_devices_t device,
audio_policy_dev_state_t state,
const char *device_address,
const char *device_name)
{
audio_devices_t tmp = AUDIO_DEVICE_NONE;;
ALOGE("setDeviceConnectionState %08x %x %s", device, state,
device_address ? device_address : "(null)");
// If the input device is the remote submix and an address starting with "force=" was
// specified, enable "force=1" / disable "force=0" the forced selection of the remote submix
// input device over hardware input devices (e.g RemoteControl).
if (device == AUDIO_DEVICE_IN_REMOTE_SUBMIX && device_address) {
AudioParameter parameters = AudioParameter(String8(device_address));
int forceValue;
if (parameters.getInt(String8("force"), forceValue) == OK) {
mForceSubmixInputSelection = forceValue != 0;
}
}
if (audio_is_output_device(device)) {
switch (state) {
case AUDIO_POLICY_DEVICE_STATE_AVAILABLE:
tmp = mAvailableOutputDevices.types() | device;
break;
case AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE:
tmp = mAvailableOutputDevices.types() & ~device;
break;
default:
ALOGE("setDeviceConnectionState() invalid state: %x", state);
return BAD_VALUE;
}
gAudioHardwareOutput.updateRouting(tmp);
tmp = mAvailableOutputDevices.types();
}
status_t ret = 0;
if (device != AUDIO_DEVICE_IN_REMOTE_SUBMIX) {
ret = AudioPolicyManager::setDeviceConnectionState(
device, state, device_address, device_name);
}
if (audio_is_output_device(device)) {
if (tmp != mAvailableOutputDevices.types())
gAudioHardwareOutput.updateRouting(mAvailableOutputDevices.types());
}
return ret;
}
audio_devices_t ATVAudioPolicyManager::getDeviceForInputSource(audio_source_t inputSource)
{
uint32_t device = AUDIO_DEVICE_NONE;
bool usePhysRemote = true;
const audio_devices_t availableDeviceTypes = mAvailableInputDevices.types() &
~AUDIO_DEVICE_BIT_IN;
if (inputSource == AUDIO_SOURCE_VOICE_RECOGNITION ||
inputSource == AUDIO_SOURCE_UNPROCESSED) {
#ifdef REMOTE_CONTROL_INTERFACE
ALOGI("Using REMOTE_CONTROL_INTERFACE.");
// Check if remote is actually connected or we should move on
sp<IRemoteControlService> service = IRemoteControlService::getInstance();
if (service == NULL) {
ALOGV("getDeviceForInputSource No RemoteControl service detected, ignoring");
usePhysRemote = false;
} else if (!service->hasActiveRemote()) {
if (mForceSubmixInputSelection == false && service->hasConnectedRemotes()) {
ALOGV("getDeviceForInputSource connected remote and submix not forced");
usePhysRemote = true;
} else {
ALOGV("getDeviceForInputSource No active connected device, passing onto submix");
usePhysRemote = false;
}
}
#endif
ALOGV("getDeviceForInputSource %s %s", usePhysRemote ? "use physical" : "",
mForceSubmixInputSelection ? "use virtual" : "");
if (availableDeviceTypes & AUDIO_DEVICE_IN_WIRED_HEADSET &&
usePhysRemote) {
// User a wired headset (physical remote) if available, connected and active
ALOGV("Wired Headset available");
device = AUDIO_DEVICE_IN_WIRED_HEADSET;
} else if (availableDeviceTypes & AUDIO_DEVICE_IN_REMOTE_SUBMIX &&
mForceSubmixInputSelection) {
// REMOTE_SUBMIX should always be avaible, let's make sure it's being forced at the moment
ALOGV("Virtual remote available");
device = AUDIO_DEVICE_IN_REMOTE_SUBMIX;
} else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_DEVICE) {
ALOGV("Use USB audio input");
device = AUDIO_DEVICE_IN_USB_DEVICE;
}
} else if ((availableDeviceTypes & AUDIO_DEVICE_IN_REMOTE_SUBMIX) &&
(inputSource == AUDIO_SOURCE_REMOTE_SUBMIX)) {
device = AUDIO_DEVICE_IN_REMOTE_SUBMIX;
}
ALOGV("getDeviceForInputSource() input source %d, device %08x", inputSource, device);
return device;
}
} // namespace android

View file

@ -0,0 +1,54 @@
/*
* 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.
*/
#include <stdint.h>
#include <sys/types.h>
#include <utils/Timers.h>
#include <utils/Errors.h>
#include <utils/KeyedVector.h>
#include <managerdefault/AudioPolicyManager.h>
#ifndef ANDROID_ATV_AUDIO_POLICY_MANAGER_H
#define ANDROID_ATV_AUDIO_POLICY_MANAGER_H
namespace android {
class ATVAudioPolicyManager: public AudioPolicyManager
{
public:
ATVAudioPolicyManager(AudioPolicyClientInterface *clientInterface);
virtual ~ATVAudioPolicyManager() {}
virtual status_t setDeviceConnectionState(audio_devices_t device,
audio_policy_dev_state_t state,
const char *device_address,
const char *device_name);
virtual audio_devices_t getDeviceForInputSource(audio_source_t inputSource);
protected:
virtual float computeVolume(audio_stream_type_t stream,
int index,
audio_devices_t device);
private:
// Flag which indicates whether to record from the submix device.
bool mForceSubmixInputSelection;
};
} // namespace android
#endif // ATV_ANDROID_AUDIO_POLICY_MANAGER_H

View file

@ -0,0 +1,137 @@
# 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.
LOCAL_PATH := $(call my-dir)
######################################################
# Library used by both policy manager and the audioHAL
######################################################
include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
alsa_utils.cpp \
AudioHardwareOutput.cpp \
AudioOutput.cpp \
AudioStreamOut.cpp \
HDMIAudioOutput.cpp \
AudioHardwareInput.cpp \
AudioStreamIn.cpp \
AudioHotplugThread.cpp \
LinearTransform.cpp
LOCAL_C_INCLUDES := \
external/tinyalsa/include \
$(call include-path-for, audio-utils)
LOCAL_SHARED_LIBRARIES := \
libcommon_time_client \
libcutils \
liblog \
libutils \
libmedia \
libbinder \
libtinyalsa \
libaudiospdif \
libaudioutils
# until remotecontrolservice is added to PDK, don't include
# this in aosp_fugu builds. only use in regular fugu builds.
ifneq ($(filter fugu fugu_gmscore_next, $(TARGET_PRODUCT)),)
LOCAL_C_INCLUDES += \
vendor/google_athome/services/RemoteControlService/include
LOCAL_SHARED_LIBRARIES += \
libremotecontrolservice
LOCAL_CFLAGS += -DREMOTE_CONTROL_INTERFACE
endif
LOCAL_STATIC_LIBRARIES += libmedia_helper
LOCAL_MODULE := libatv_audio
LOCAL_MODULE_TAGS := optional
LOCAL_CFLAGS += -Werror
include $(BUILD_SHARED_LIBRARY)
##################################
# audioHAL
##################################
include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
audio_hal_hooks.c \
audio_hal_thunks.cpp \
LOCAL_C_INCLUDES := \
external/tinyalsa/include \
$(call include-path-for, audio-utils)
LOCAL_SHARED_LIBRARIES := \
libcutils \
liblog \
libutils \
libmedia \
libatv_audio
LOCAL_MODULE := audio.primary.fugu
LOCAL_MODULE_RELATIVE_PATH := hw
LOCAL_MODULE_TAGS := optional
LOCAL_CFLAGS += -Werror
include $(BUILD_SHARED_LIBRARY)
##################################
# Audio Policy Manager
##################################
include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
ATVAudioPolicyManager.cpp
LOCAL_SHARED_LIBRARIES := \
libcutils \
liblog \
libutils \
libmedia \
libatv_audio \
libbinder \
libaudiopolicymanagerdefault
LOCAL_C_INCLUDES := \
external/tinyalsa/include \
$(TOPDIR)frameworks/av/services/audiopolicy \
$(TOPDIR)frameworks/av/services/audiopolicy/common/include \
$(TOPDIR)frameworks/av/services/audiopolicy/common/managerdefinitions/include \
$(TOPDIR)frameworks/av/services/audiopolicy/engine/interface
ifneq ($(filter fugu fugu_gmscore_next, $(TARGET_PRODUCT)),)
LOCAL_C_INCLUDES += \
vendor/google_athome/services/RemoteControlService/include
LOCAL_SHARED_LIBRARIES += \
libremotecontrolservice
LOCAL_CFLAGS += -DREMOTE_CONTROL_INTERFACE
endif
LOCAL_MODULE := libaudiopolicymanager
LOCAL_MODULE_TAGS := optional
LOCAL_CFLAGS += -Werror
include $(BUILD_SHARED_LIBRARY)

View file

@ -0,0 +1,297 @@
/*
**
** Copyright 2012, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
#define LOG_TAG "AudioHAL:AudioHardwareInput"
#include <utils/Log.h>
#include <fcntl.h>
#include <sys/eventfd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <utils/String8.h>
#include "AudioHardwareInput.h"
#include "AudioHotplugThread.h"
#include "AudioStreamIn.h"
namespace android {
// Global singleton.
AudioHardwareInput gAudioHardwareInput;
AudioHardwareInput::AudioHardwareInput()
: mMicMute(false)
{
mHotplugThread = new AudioHotplugThread(*this);
if (mHotplugThread == NULL) {
ALOGE("Unable to create ATV Remote audio hotplug thread. "
"Pluggable audio input devices will not function.");
} else if (!mHotplugThread->start()) {
ALOGE("Unable to start ATV Remote audio hotplug thread. "
"Pluggable audio input devices will not function.");
mHotplugThread.clear();
}
for (int i=0; i<kMaxDevices; i++) {
mDeviceInfos[i].valid = false;
}
}
AudioHardwareInput::~AudioHardwareInput()
{
if (mHotplugThread != NULL) {
mHotplugThread->shutdown();
mHotplugThread.clear();
}
closeAllInputStreams();
}
status_t AudioHardwareInput::setMicMute(bool mute)
{
mMicMute = mute;
return NO_ERROR;
}
status_t AudioHardwareInput::getMicMute(bool* mute)
{
*mute = mMicMute;
return NO_ERROR;
}
// milliseconds per ALSA period
const uint32_t AudioHardwareInput::kPeriodMsec = 20;
size_t AudioHardwareInput::calculateInputBufferSize(uint32_t outputSampleRate,
audio_format_t format,
uint32_t channelCount)
{
size_t size;
// AudioFlinger expects audio buffers to be a multiple of 16 frames
size = (kPeriodMsec * outputSampleRate) / 1000;
size = ((size + 15) / 16) * 16;
return size * channelCount * audio_bytes_per_sample(format);
}
status_t AudioHardwareInput::getInputBufferSize(const audio_config* config)
{
size_t size = calculateInputBufferSize(config->sample_rate,
config->format,
audio_channel_count_from_in_mask(config->channel_mask));
return size;
}
AudioStreamIn* AudioHardwareInput::openInputStream(uint32_t devices,
audio_format_t* format, uint32_t* channelMask, uint32_t* sampleRate,
status_t* status)
{
(void) devices;
Mutex::Autolock _l(mLock);
AudioStreamIn* in;
in = new AudioStreamIn(*this);
if (in == NULL) {
*status = NO_MEMORY;
return NULL;
}
*status = in->set(format, channelMask, sampleRate);
if (*status != NO_ERROR) {
delete in;
return NULL;
}
mInputStreams.add(in);
return in;
}
void AudioHardwareInput::closeInputStream(AudioStreamIn* in)
{
Mutex::Autolock _l(mLock);
for (size_t i = 0; i < mInputStreams.size(); i++) {
if (in == mInputStreams[i]) {
mInputStreams.removeAt(i);
in->standby();
delete in;
break;
}
}
}
void AudioHardwareInput::closeAllInputStreams()
{
while (mInputStreams.size() != 0) {
AudioStreamIn* in = mInputStreams[0];
mInputStreams.removeAt(0);
in->standby();
delete in;
}
}
void AudioHardwareInput::standbyAllInputStreams(const AudioHotplugThread::DeviceInfo* deviceInfo)
{
for (size_t i = 0; i < mInputStreams.size(); i++) {
if (deviceInfo == NULL || deviceInfo == mInputStreams[i]->getDeviceInfo()) {
mInputStreams[i]->standby();
}
}
}
#define DUMP(a...) \
snprintf(buffer, SIZE, a); \
buffer[SIZE - 1] = 0; \
result.append(buffer);
#define B2STR(b) b ? "true" : "false"
status_t AudioHardwareInput::dump(int fd)
{
const size_t SIZE = 256;
char buffer[SIZE];
String8 result;
DUMP("\nAudioHardwareInput::dump\n");
for (int i=0; i<kMaxDevices; i++) {
if (mDeviceInfos[i].valid) {
DUMP("device[%d] is valid\n", i);
DUMP("\tcapture card: %d\n", mDeviceInfos[i].pcmCard);
DUMP("\tcapture device: %d\n", mDeviceInfos[i].pcmDevice);
}
}
::write(fd, result.string(), result.size());
{
Mutex::Autolock _l(mLock);
for (size_t i = 0; i < mInputStreams.size(); i++) {
mInputStreams[i]->dump(fd);
}
}
return NO_ERROR;
}
#undef DUMP
#undef B2STR
// called on the audio hotplug thread
void AudioHardwareInput::onDeviceFound(
const AudioHotplugThread::DeviceInfo& devInfo)
{
bool foundSlot = false;
Mutex::Autolock _l(mLock);
ALOGD("AudioHardwareInput::onDeviceFound pcmCard = %d", devInfo.pcmCard);
for (int i=0; i<kMaxDevices; i++) {
if (mDeviceInfos[i].valid) {
if ((mDeviceInfos[i].pcmCard == devInfo.pcmCard)
&& (mDeviceInfos[i].pcmDevice == devInfo.pcmDevice)) {
ALOGW("AudioHardwareInput::onDeviceFound already has %d:%d",
devInfo.pcmCard, devInfo.pcmDevice);
return; // Got it already so no action needed.
}
}
}
// New device so find an empty slot and save it.
for (int i=0; i<kMaxDevices; i++) {
if (!mDeviceInfos[i].valid) {
ALOGD("AudioHardwareInput::onDeviceFound saving as device #%d", i);
mDeviceInfos[i] = devInfo;
mDeviceInfos[i].valid = true;
foundSlot = true;
/* Restart any currently running streams. */
standbyAllInputStreams(NULL);
break;
}
}
if (!foundSlot) {
ALOGW("AudioHardwareInput::onDeviceFound found more devices than expected! Dropped");
}
}
// called on the audio hotplug thread
void AudioHardwareInput::onDeviceRemoved(unsigned int pcmCard, unsigned int pcmDevice)
{
Mutex::Autolock _l(mLock);
ALOGD("AudioHardwareInput::onDeviceRemoved pcmCard = %d", pcmCard);
// Find matching DeviceInfo.
for (int i=0; i<kMaxDevices; i++) {
if (mDeviceInfos[i].valid) {
if ((mDeviceInfos[i].pcmCard == pcmCard) && (mDeviceInfos[i].pcmDevice == pcmDevice)) {
ALOGD("AudioHardwareInput::onDeviceRemoved matches #%d", i);
mDeviceInfos[i].valid = false;
/* If currently active stream is using this device then restart. */
standbyAllInputStreams(&mDeviceInfos[i]);
break;
}
}
}
}
const AudioHotplugThread::DeviceInfo* AudioHardwareInput::getBestDevice(int inputSource)
{
bool doVoiceRecognition = (inputSource == AUDIO_SOURCE_VOICE_RECOGNITION);
const bool favorNoVoiceRecognition = (inputSource == AUDIO_SOURCE_UNPROCESSED);
int chosenDeviceIndex = -1;
Mutex::Autolock _l(mLock);
ALOGD("AudioHardwareInput::getBestDevice inputSource = %d, doVoiceRecognition = %d",
inputSource, (doVoiceRecognition ? 1 : 0));
// RemoteControl is the only input device usable for voice recognition
// and no other devices are used for voice recognition.
// Currently the RemoteControl is the only device marked with forVoiceRecognition=true.
// A connected USB mic could be used for anything but voice recognition.
// For UNPROCESSED source, a connected USB microphone will be favored over the remote mic.
for (int i=0; i<kMaxDevices; i++) {
if (mDeviceInfos[i].valid) {
if (favorNoVoiceRecognition) {
if (mDeviceInfos[i].forVoiceRecognition) {
chosenDeviceIndex = i;
//continue matching
} else {
chosenDeviceIndex = i;
break;
}
} else if (mDeviceInfos[i].forVoiceRecognition == doVoiceRecognition) {
chosenDeviceIndex = i;
break;
}
}
}
if (chosenDeviceIndex < 0) {
ALOGE("ERROR AudioHardwareInput::getBestDevice, none for source %d", inputSource);
} else {
ALOGD("AudioHardwareInput::getBestDevice chose #%d", chosenDeviceIndex);
}
return (chosenDeviceIndex >= 0) ? &mDeviceInfos[chosenDeviceIndex] : NULL;
}
}; // namespace android

View file

@ -0,0 +1,83 @@
/*
**
** Copyright 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_AUDIO_HARDWARE_INPUT_H
#define ANDROID_AUDIO_HARDWARE_INPUT_H
#include <hardware/audio.h>
#include <system/audio.h>
#include <utils/Errors.h>
#include <utils/threads.h>
#include <utils/Vector.h>
#include "AudioHotplugThread.h"
namespace android {
class AudioStreamIn;
class AudioHardwareInput : public AudioHotplugThread::Callback {
public:
AudioHardwareInput();
~AudioHardwareInput();
status_t setMicMute(bool mute);
status_t getMicMute(bool* mute);
status_t getInputBufferSize(const audio_config* config);
AudioStreamIn* openInputStream(uint32_t devices,
audio_format_t* format,
uint32_t* channelMask,
uint32_t* sampleRate,
status_t* status);
void closeInputStream(AudioStreamIn* in);
status_t dump(int fd);
// AudioHotplugThread callbacks
virtual void onDeviceFound(const AudioHotplugThread::DeviceInfo& devInfo);
virtual void onDeviceRemoved(unsigned int pcmCard, unsigned int pcmDevice);
static size_t calculateInputBufferSize(uint32_t outputSampleRate,
audio_format_t format,
uint32_t channelCount);
static const uint32_t kPeriodMsec;
/**
* Decide which device to use for the given input.
*/
const AudioHotplugThread::DeviceInfo* getBestDevice(int inputSource);
private:
static const int kMaxDevices = 8; // TODO review strategy for adding more devices
void closeAllInputStreams();
// Place all input streams using the specified device into standby. If deviceInfo is NULL,
// all input streams are placed into standby.
void standbyAllInputStreams(const AudioHotplugThread::DeviceInfo* deviceInfo);
Mutex mLock;
bool mMicMute;
Vector<AudioStreamIn*> mInputStreams;
sp<AudioHotplugThread> mHotplugThread;
AudioHotplugThread::DeviceInfo mDeviceInfos[kMaxDevices];
};
}; // namespace android
#endif // ANDROID_AUDIO_HARDWARE_INPUT_H

View file

@ -0,0 +1,592 @@
/*
**
** Copyright 2014, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
#define LOG_TAG "AudioHAL_AudioHardwareOutput"
#include <utils/Log.h>
#include <stdint.h>
#include <limits.h>
#include <math.h>
#include <common_time/local_clock.h>
#include <cutils/properties.h>
#include "AudioHardwareOutput.h"
#include "AudioStreamOut.h"
#include "HDMIAudioOutput.h"
namespace android {
// Global singleton.
AudioHardwareOutput gAudioHardwareOutput;
// HDMI options.
const String8 AudioHardwareOutput::kHDMIAllowedParamKey(
"atv.hdmi_audio.allowed");
const String8 AudioHardwareOutput::kHDMIDelayCompParamKey(
"atv.hdmi.audio_delay");
const String8 AudioHardwareOutput::kFixedHDMIOutputParamKey(
"atv.hdmi.fixed_volume");
const String8 AudioHardwareOutput::kFixedHDMIOutputLevelParamKey(
"atv.hdmi.fixed_level");
// Video delay comp hack options (not exposed to user level)
const String8 AudioHardwareOutput::kVideoDelayCompParamKey(
"atv.video.delay_comp");
// Defaults for settings.
void AudioHardwareOutput::OutputSettings::setDefaults()
{
allowed = true;
delayCompUsec = 0;
isFixed = false;
fixedLvl = 0.0f;
}
void AudioHardwareOutput::Settings::setDefaults() {
hdmi.setDefaults();
masterVolume = 0.60;
masterMute = false;
// Default this to 16mSec or so. Since audio start times are not sync'ed to
// to the VBI, there should be a +/-0.5 output frame rate error in the AV
// sync, even under the best of circumstances.
//
// In practice, the android core seems to have a hard time hitting its frame
// cadence consistently. Sometimes the frames are on time, and sometimes
// they are even a little early, but more often than not, the frames are
// late by about a full output frame time.
//
// ATV pretty much always uses a 60fps output rate, and the only thing
// consuming the latency estimate provided by the HAL is the path handling
// AV sync. For now, we can fudge this number to move things back in the
// direction of correct by providing a setting for video delay compensation
// which will be subtracted from the latency estimate and defaulting it to
// a reasonable middle gound (12mSec in this case).
videoDelayCompUsec = 12000;
}
AudioHardwareOutput::AudioHardwareOutput()
: mMainOutput(NULL)
, mMCOutput(NULL)
, mHDMIConnected(false)
, mMaxDelayCompUsec(0)
{
mSettings.setDefaults();
mHDMICardID = find_alsa_card_by_name(kHDMI_ALSADeviceName);
}
AudioHardwareOutput::~AudioHardwareOutput()
{
closeOutputStream(mMainOutput);
closeOutputStream(mMCOutput);
}
status_t AudioHardwareOutput::initCheck() {
return NO_ERROR;
}
AudioStreamOut* AudioHardwareOutput::openOutputStream(
uint32_t devices,
audio_format_t *format,
uint32_t *channels,
uint32_t *sampleRate,
audio_output_flags_t flags,
status_t *status) {
(void) devices;
AutoMutex lock(mStreamLock);
AudioStreamOut** pp_out;
AudioStreamOut* out;
bool isIec958NonAudio = (flags & AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO) != 0;
if (!(flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
pp_out = &mMainOutput;
out = new AudioStreamOut(*this, false, isIec958NonAudio);
} else {
pp_out = &mMCOutput;
out = new AudioStreamOut(*this, true, isIec958NonAudio);
}
if (out == NULL) {
*status = NO_MEMORY;
return NULL;
}
*status = out->set(format, channels, sampleRate);
if (*status == NO_ERROR) {
*pp_out = out;
updateTgtDevices_l();
} else {
delete out;
}
return *pp_out;
}
void AudioHardwareOutput::closeOutputStream(AudioStreamOut* out) {
if (out == NULL)
return;
// Putting the stream into "standby" should cause it to release all of its
// physical outputs.
out->standby();
{
Mutex::Autolock _l(mStreamLock);
if (mMainOutput && out == mMainOutput) {
delete mMainOutput;
mMainOutput = NULL;
} else if (mMCOutput && out == mMCOutput) {
delete mMCOutput;
mMCOutput = NULL;
}
updateTgtDevices_l();
}
}
status_t AudioHardwareOutput::setMasterVolume(float volume)
{
Mutex::Autolock _l1(mOutputLock);
Mutex::Autolock _l2(mSettingsLock);
mSettings.masterVolume = volume;
AudioOutputList::iterator I;
for (I = mPhysOutputs.begin(); I != mPhysOutputs.end(); ++I)
(*I)->setVolume(mSettings.masterVolume);
return NO_ERROR;
}
status_t AudioHardwareOutput::getMasterVolume(float* volume) {
if (NULL == volume)
return BAD_VALUE;
// Explicit scope for auto-lock pattern.
{
Mutex::Autolock _l(mSettingsLock);
*volume = mSettings.masterVolume;
}
return NO_ERROR;
}
status_t AudioHardwareOutput::setMasterMute(bool muted)
{
Mutex::Autolock _l1(mOutputLock);
Mutex::Autolock _l2(mSettingsLock);
mSettings.masterMute = muted;
AudioOutputList::iterator I;
for (I = mPhysOutputs.begin(); I != mPhysOutputs.end(); ++I)
(*I)->setMute(mSettings.masterMute);
return NO_ERROR;
}
status_t AudioHardwareOutput::getMasterMute(bool* muted) {
if (NULL == muted)
return BAD_VALUE;
// Explicit scope for auto-lock pattern.
{
Mutex::Autolock _l(mSettingsLock);
*muted = mSettings.masterMute;
}
return NO_ERROR;
}
status_t AudioHardwareOutput::setParameters(const char* kvpairs) {
AudioParameter param = AudioParameter(String8(kvpairs));
status_t status = NO_ERROR;
float floatVal;
int intVal;
Settings initial, s;
{
// Record the initial state of the settings from inside the lock. Then
// leave the lock in order to parse the changes to be made.
Mutex::Autolock _l(mSettingsLock);
initial = s = mSettings;
}
/***************************************************************
* HDMI Audio Options *
***************************************************************/
if (param.getInt(kHDMIAllowedParamKey, intVal) == NO_ERROR) {
s.hdmi.allowed = (intVal != 0);
param.remove(kHDMIAllowedParamKey);
}
if ((param.getFloat(kHDMIDelayCompParamKey, floatVal) == NO_ERROR) &&
(floatVal >= 0.0) &&
(floatVal <= AudioOutput::kMaxDelayCompensationMSec)) {
uint32_t delay_comp = static_cast<uint32_t>(floatVal * 1000.0);
s.hdmi.delayCompUsec = delay_comp;
param.remove(kHDMIDelayCompParamKey);
}
if (param.getInt(kFixedHDMIOutputParamKey, intVal) == NO_ERROR) {
s.hdmi.isFixed = (intVal != 0);
param.remove(kFixedHDMIOutputParamKey);
}
if ((param.getFloat(kFixedHDMIOutputLevelParamKey, floatVal) == NO_ERROR)
&& (floatVal <= 0.0)) {
s.hdmi.fixedLvl = floatVal;
param.remove(kFixedHDMIOutputLevelParamKey);
}
/***************************************************************
* Other Options *
***************************************************************/
if ((param.getFloat(kVideoDelayCompParamKey, floatVal) == NO_ERROR) &&
(floatVal >= 0.0) &&
(floatVal <= AudioOutput::kMaxDelayCompensationMSec)) {
s.videoDelayCompUsec = static_cast<uint32_t>(floatVal * 1000.0);
param.remove(kVideoDelayCompParamKey);
}
if (param.size())
status = BAD_VALUE;
// If there was a change made to settings, go ahead and apply it now.
bool allowedOutputsChanged = false;
if (memcmp(&initial, &s, sizeof(initial))) {
Mutex::Autolock _l1(mOutputLock);
Mutex::Autolock _l2(mSettingsLock);
if (memcmp(&initial.hdmi, &s.hdmi, sizeof(initial.hdmi)))
allowedOutputsChanged = allowedOutputsChanged ||
applyOutputSettings_l(initial.hdmi, s.hdmi, mSettings.hdmi,
HDMIAudioOutput::classDevMask());
if (initial.videoDelayCompUsec != s.videoDelayCompUsec)
mSettings.videoDelayCompUsec = s.videoDelayCompUsec;
uint32_t tmp = 0;
if (mSettings.hdmi.allowed && (tmp < mSettings.hdmi.delayCompUsec))
tmp = mSettings.hdmi.delayCompUsec;
if (mMaxDelayCompUsec != tmp)
mMaxDelayCompUsec = tmp;
}
if (allowedOutputsChanged) {
Mutex::Autolock _l(mStreamLock);
updateTgtDevices_l();
}
return status;
}
bool AudioHardwareOutput::applyOutputSettings_l(
const AudioHardwareOutput::OutputSettings& initial,
const AudioHardwareOutput::OutputSettings& current,
AudioHardwareOutput::OutputSettings& updateMe,
uint32_t outDevMask) {
// ASSERT(holding mOutputLock and mSettingsLock)
sp<AudioOutput> out;
// Check for a change in the allowed/not-allowed state. Update if needed
// and return true if there was a change made.
bool ret = false;
if (initial.allowed != current.allowed) {
updateMe.allowed = current.allowed;
ret = true;
}
// Look for an instance of the output to be updated in case other changes
// were made.
AudioOutputList::iterator I;
for (I = mPhysOutputs.begin(); I != mPhysOutputs.end(); ++I) {
if (outDevMask == (*I)->devMask()) {
out = (*I);
break;
}
}
// Update the other settings, if needed.
if (initial.delayCompUsec != current.delayCompUsec) {
updateMe.delayCompUsec = current.delayCompUsec;
if (out != NULL)
out->setExternalDelay_uSec(current.delayCompUsec);
}
if (initial.isFixed != current.isFixed) {
updateMe.isFixed = current.isFixed;
if (out != NULL)
out->setOutputIsFixed(current.isFixed);
}
if (initial.fixedLvl != current.fixedLvl) {
updateMe.fixedLvl = current.fixedLvl;
if (out != NULL)
out->setFixedOutputLevel(current.fixedLvl);
}
return ret;
}
char* AudioHardwareOutput::getParameters(const char* keys) {
Settings s;
// Explicit scope for auto-lock pattern.
{
// Snapshot the current settings so we don't have to hold the settings
// lock while formatting the results.
Mutex::Autolock _l(mSettingsLock);
s = mSettings;
}
AudioParameter param = AudioParameter(String8(keys));
String8 tmp;
/***************************************************************
* HDMI Audio Options *
***************************************************************/
if (param.get(kHDMIAllowedParamKey, tmp) == NO_ERROR)
param.addInt(kHDMIAllowedParamKey, s.hdmi.allowed ? 1 : 0);
if (param.get(kHDMIDelayCompParamKey, tmp) == NO_ERROR)
param.addFloat(kHDMIDelayCompParamKey,
static_cast<float>(s.hdmi.delayCompUsec) / 1000.0);
if (param.get(kFixedHDMIOutputParamKey, tmp) == NO_ERROR)
param.addInt(kFixedHDMIOutputParamKey, s.hdmi.isFixed ? 1 : 0);
if (param.get(kFixedHDMIOutputLevelParamKey, tmp) == NO_ERROR)
param.addFloat(kFixedHDMIOutputLevelParamKey, s.hdmi.fixedLvl);
/***************************************************************
* Other Options *
***************************************************************/
if (param.get(kVideoDelayCompParamKey, tmp) == NO_ERROR)
param.addFloat(kVideoDelayCompParamKey,
static_cast<float>(s.videoDelayCompUsec) / 1000.0);
return strdup(param.toString().string());
}
void AudioHardwareOutput::updateRouting(uint32_t devMask) {
Mutex::Autolock _l(mStreamLock);
bool hasHDMI = 0 != (devMask & HDMIAudioOutput::classDevMask());
ALOGI("%s: hasHDMI = %d, mHDMIConnected = %d", __func__, hasHDMI, mHDMIConnected);
if (mHDMIConnected != hasHDMI) {
mHDMIConnected = hasHDMI;
if (mHDMIConnected)
mHDMIAudioCaps.loadCaps(mHDMICardID);
else
mHDMIAudioCaps.reset();
updateTgtDevices_l();
}
}
status_t AudioHardwareOutput::obtainOutput(const AudioStreamOut& tgtStream,
uint32_t devMask,
sp<AudioOutput>* newOutput) {
Mutex::Autolock _l1(mOutputLock);
// Sanity check the device mask passed to us. There should exactly one bit
// set, no less, no more.
if (popcount(devMask) != 1) {
ALOGW("bad device mask in obtainOutput, %08x", devMask);
return INVALID_OPERATION;
}
// Start by checking to see if the requested output is currently busy.
AudioOutputList::iterator I;
for (I = mPhysOutputs.begin(); I != mPhysOutputs.end(); ++I)
if (devMask & (*I)->devMask())
return OK; // Yup; its busy.
// Looks like we don't currently have an output of the requested type.
// Figure out which type is being requested and try to construct one.
OutputSettings* S = NULL;
if (devMask & HDMIAudioOutput::classDevMask()) {
*newOutput = new HDMIAudioOutput();
S = &mSettings.hdmi;
}
else {
ALOGW("%s stream out requested output of unknown type %08x",
tgtStream.getName(), devMask);
return BAD_VALUE;
}
if (*newOutput == NULL)
return NO_MEMORY;
status_t res = (*newOutput)->setupForStream(tgtStream);
if (res != OK) {
ALOGE("%s setupForStream() returned %d",
tgtStream.getName(), res);
*newOutput = NULL;
} else {
ALOGI("%s stream out adding %s output.",
tgtStream.getName(), (*newOutput)->getOutputName());
mPhysOutputs.push_back(*newOutput);
{ // Apply current settings
Mutex::Autolock _l2(mSettingsLock);
(*newOutput)->setVolume(mSettings.masterVolume);
(*newOutput)->setMute(mSettings.masterMute);
(*newOutput)->setExternalDelay_uSec(S->delayCompUsec);
(*newOutput)->setOutputIsFixed(S->isFixed);
(*newOutput)->setFixedOutputLevel(S->fixedLvl);
}
}
return res;
}
void AudioHardwareOutput::releaseOutput(const AudioStreamOut& tgtStream,
const sp<AudioOutput>& releaseMe) {
Mutex::Autolock _l(mOutputLock);
ALOGI("%s stream out removing %s output.",
tgtStream.getName(), releaseMe->getOutputName());
// Immediately release any resources associated with this output (In
// particular, make sure to close any ALSA device driver handles ASAP)
releaseMe->cleanupResources();
// Now, clear our internal bookkeeping.
AudioOutputList::iterator I;
for (I = mPhysOutputs.begin(); I != mPhysOutputs.end(); ++I) {
if (releaseMe.get() == (*I).get()) {
mPhysOutputs.erase(I);
break;
}
}
}
void AudioHardwareOutput::updateTgtDevices_l() {
// ASSERT(holding mStreamLock)
uint32_t mcMask = 0;
uint32_t mainMask = 0;
{
Mutex::Autolock _l(mSettingsLock);
if (mSettings.hdmi.allowed && mHDMIConnected) {
if (NULL != mMCOutput)
mcMask |= HDMIAudioOutput::classDevMask();
else
mainMask |= HDMIAudioOutput::classDevMask();
}
}
if (NULL != mMainOutput)
mMainOutput->setTgtDevices(mainMask);
if (NULL != mMCOutput)
mMCOutput->setTgtDevices(mcMask);
}
void AudioHardwareOutput::standbyStatusUpdate(bool isInStandby, bool isMCStream) {
Mutex::Autolock _l1(mStreamLock);
bool hdmiAllowed;
{
Mutex::Autolock _l2(mSettingsLock);
hdmiAllowed = mSettings.hdmi.allowed;
}
// If there is no HDMI, do nothing
if (hdmiAllowed && mHDMIConnected) {
// If a multi-channel stream goes to standy state, we must switch
// to stereo stream. If MC comes out of standby, we must switch
// back to MC. No special processing needed for main stream.
// AudioStreamOut class handles that correctly
if (isMCStream) {
uint32_t mcMask;
uint32_t mainMask;
if (isInStandby) {
mainMask = HDMIAudioOutput::classDevMask();
mcMask = 0;
} else {
mainMask = 0;
mcMask = HDMIAudioOutput::classDevMask();
}
if (NULL != mMainOutput)
mMainOutput->setTgtDevices(mainMask);
if (NULL != mMCOutput)
mMCOutput->setTgtDevices(mcMask);
}
}
}
#define DUMP(a...) \
snprintf(buffer, SIZE, a); \
buffer[SIZE - 1] = 0; \
result.append(buffer);
#define B2STR(b) b ? "true" : "false"
status_t AudioHardwareOutput::dump(int fd)
{
const size_t SIZE = 256;
char buffer[SIZE];
String8 result;
Settings s;
// Explicit scope for auto-lock pattern.
{
// Snapshot the current settings so we don't have to hold the settings
// lock while formatting the results.
Mutex::Autolock _l(mSettingsLock);
s = mSettings;
}
DUMP("AudioHardwareOutput::dump\n");
DUMP("\tMaster Volume : %0.3f\n", s.masterVolume);
DUMP("\tMaster Mute : %s\n", B2STR(s.masterMute));
DUMP("\tHDMI Output Allowed : %s\n", B2STR(s.hdmi.allowed));
DUMP("\tHDMI Delay Comp : %u uSec\n", s.hdmi.delayCompUsec);
DUMP("\tHDMI Output Fixed : %s\n", B2STR(s.hdmi.isFixed));
DUMP("\tHDMI Fixed Level : %.1f dB\n", s.hdmi.fixedLvl);
DUMP("\tVideo Delay Comp : %u uSec\n", s.videoDelayCompUsec);
::write(fd, result.string(), result.size());
// Explicit scope for auto-lock pattern.
{
Mutex::Autolock _l(mOutputLock);
if (mMainOutput)
mMainOutput->dump(fd);
if (mMCOutput)
mMCOutput->dump(fd);
}
return NO_ERROR;
}
#undef B2STR
#undef DUMP
}; // namespace android

View file

@ -0,0 +1,158 @@
/*
**
** Copyright 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_AUDIO_HARDWARE_OUTPUT_H
#define ANDROID_AUDIO_HARDWARE_OUTPUT_H
#include <stdint.h>
#include <sys/types.h>
#include <hardware/audio.h>
#include <utils/String8.h>
#include <utils/threads.h>
#include "alsa_utils.h"
#include "AudioOutput.h"
namespace android {
class AudioStreamOut;
class AudioOutput;
class AudioHardwareOutput {
public:
AudioHardwareOutput();
virtual ~AudioHardwareOutput();
status_t initCheck();
status_t setMasterVolume(float volume);
status_t getMasterVolume(float* volume);
status_t setMasterMute(bool mute);
status_t getMasterMute(bool* mute);
status_t setParameters(const char* kvpairs);
char* getParameters(const char* keys);
status_t dump(int fd);
void updateRouting(uint32_t devMask);
uint32_t getMaxDelayCompUsec() const { return mMaxDelayCompUsec; }
uint32_t getVideoDelayCompUsec() const {
return mSettings.videoDelayCompUsec;
}
HDMIAudioCaps& getHDMIAudioCaps() { return mHDMIAudioCaps; }
// Interface to allow streams to obtain and release various physical
// outputs.
status_t obtainOutput(const AudioStreamOut& tgtStream,
uint32_t devMask,
sp<AudioOutput>* newOutput);
void releaseOutput(const AudioStreamOut& tgtStream,
const sp<AudioOutput>& releaseMe);
// create I/O streams
AudioStreamOut* openOutputStream(uint32_t devices,
audio_format_t *format,
uint32_t *channels,
uint32_t *sampleRate,
audio_output_flags_t flags,
status_t *status);
void closeOutputStream(AudioStreamOut* out);
void standbyStatusUpdate(bool isInStandby, bool isMCStream);
private:
struct OutputSettings {
bool allowed;
uint32_t delayCompUsec;
bool isFixed;
float fixedLvl;
void setDefaults();
};
struct Settings {
OutputSettings hdmi;
uint32_t videoDelayCompUsec;
float masterVolume;
bool masterMute;
void setDefaults();
};
void updateTgtDevices_l();
bool applyOutputSettings_l(const OutputSettings& initial,
const OutputSettings& current,
OutputSettings& updateMe,
uint32_t outDevMask);
// Notes on locking:
// There are 3 locks in the AudioHardware class; mStreamLock, mOutputLock
// and mSettingsLock.
//
// mStreamLock is held when interacting with AudioStreamOuts, in particular
// during creation and destruction of streams, and during routing changes
// (HDMI connecting and disconnecting) which (potentially) end up effecting
// the target device masks of the output streams.
//
// mOutputLock is held while interacting with AudioOutputs (which represent
// the physical outputs of the system). AudioStreamOuts grab this lock
// during calls to (obtain|release)Output which can trigger instantiation
// and destruction of AudioOutputs. During this operation, the
// AudioStreamOut instance will be holding its own "routing" lock. Care
// should be taken to never hold the output lock or setting lock while making
// a call into an AudioStreamOut which may obtain the routing lock.
// Currently, the set of publicly accessible calls in AudioStreamOut which
// may obtain the routing lock are...
// 1) ~AudioStreamOut (calls releaseAllOutputs)
// 2) standby (calls releaseAllOutputs)
// 3) pause (calls releaseAllOutputs)
// 4) setTgtDevices
// 5) getPresentationPosition
// 6) write
//
// mSettingsLock is held while reading settings and while writing/applying
// settings to existing outputs. Lock ordering is important when applying
// settings to outputs as the both the output and settings lock need to be
// held at the same time. Whenever settings need to be applied to outputs,
// the output lock should always obtained first, followed by the settings
// lock.
Mutex mStreamLock;
AudioStreamOut *mMainOutput;
AudioStreamOut *mMCOutput;
bool mHDMIConnected;
Mutex mOutputLock;
AudioOutputList mPhysOutputs;
Mutex mSettingsLock;
Settings mSettings;
uint32_t mMaxDelayCompUsec;
HDMIAudioCaps mHDMIAudioCaps;
int mHDMICardID;
static const String8 kHDMIAllowedParamKey;
static const String8 kHDMIDelayCompParamKey;
static const String8 kFixedHDMIOutputParamKey;
static const String8 kFixedHDMIOutputLevelParamKey;
static const String8 kVideoDelayCompParamKey;
static const float kDefaultMasterVol;
};
// ----------------------------------------------------------------------------
}; // namespace android
#endif // ANDROID_AUDIO_HARDWARE_OUTPUT_H

View file

@ -0,0 +1,386 @@
/*
**
** Copyright 2012, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
#define LOG_TAG "AudioHAL:AudioHotplugThread"
#include <utils/Log.h>
#include <assert.h>
#include <dirent.h>
#include <poll.h>
#include <sys/eventfd.h>
#include <sys/inotify.h>
#include <sys/ioctl.h>
#include <sound/asound.h>
#include <utils/misc.h>
#include <utils/String8.h>
#include "AudioHotplugThread.h"
// This name is used to recognize the AndroidTV Remote mic so we can
// use it for voice recognition.
#define ANDROID_TV_REMOTE_AUDIO_DEVICE_NAME "ATVRAudio"
namespace android {
/*
* ALSA parameter manipulation routines
*
* TODO: replace this when TinyAlsa offers a suitable API
*/
static inline int param_is_mask(int p)
{
return (p >= SNDRV_PCM_HW_PARAM_FIRST_MASK) &&
(p <= SNDRV_PCM_HW_PARAM_LAST_MASK);
}
static inline int param_is_interval(int p)
{
return (p >= SNDRV_PCM_HW_PARAM_FIRST_INTERVAL) &&
(p <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL);
}
static inline struct snd_interval *param_to_interval(
struct snd_pcm_hw_params *p, int n)
{
assert(p->intervals);
assert(param_is_interval(n));
return &(p->intervals[n - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL]);
}
static inline struct snd_mask *param_to_mask(struct snd_pcm_hw_params *p, int n)
{
assert(p->masks);
assert(param_is_mask(n));
return &(p->masks[n - SNDRV_PCM_HW_PARAM_FIRST_MASK]);
}
static inline void snd_mask_any(struct snd_mask *mask)
{
memset(mask, 0xff, sizeof(struct snd_mask));
}
static inline void snd_interval_any(struct snd_interval *i)
{
i->min = 0;
i->openmin = 0;
i->max = UINT_MAX;
i->openmax = 0;
i->integer = 0;
i->empty = 0;
}
static void param_init(struct snd_pcm_hw_params *p)
{
int n, k;
memset(p, 0, sizeof(*p));
for (n = SNDRV_PCM_HW_PARAM_FIRST_MASK;
n <= SNDRV_PCM_HW_PARAM_LAST_MASK; n++) {
struct snd_mask *m = param_to_mask(p, n);
snd_mask_any(m);
}
for (n = SNDRV_PCM_HW_PARAM_FIRST_INTERVAL;
n <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; n++) {
struct snd_interval *i = param_to_interval(p, n);
snd_interval_any(i);
}
p->rmask = 0xFFFFFFFF;
}
/*
* Hotplug thread
*/
const char* AudioHotplugThread::kThreadName = "ATVRemoteAudioHotplug";
// directory where ALSA device nodes appear
const char* AudioHotplugThread::kAlsaDeviceDir = "/dev/snd";
// filename suffix for ALSA nodes representing capture devices
const char AudioHotplugThread::kDeviceTypeCapture = 'c';
AudioHotplugThread::AudioHotplugThread(Callback& callback)
: mCallback(callback)
, mShutdownEventFD(-1)
{
}
AudioHotplugThread::~AudioHotplugThread()
{
if (mShutdownEventFD != -1) {
::close(mShutdownEventFD);
}
}
bool AudioHotplugThread::start()
{
mShutdownEventFD = eventfd(0, EFD_NONBLOCK);
if (mShutdownEventFD == -1) {
return false;
}
return (run(kThreadName) == NO_ERROR);
}
void AudioHotplugThread::shutdown()
{
requestExit();
uint64_t tmp = 1;
::write(mShutdownEventFD, &tmp, sizeof(tmp));
join();
}
bool AudioHotplugThread::parseCaptureDeviceName(const char* name,
unsigned int* card,
unsigned int* device)
{
char deviceType;
int ret = sscanf(name, "pcmC%uD%u%c", card, device, &deviceType);
return (ret == 3 && deviceType == kDeviceTypeCapture);
}
static inline void getAlsaParamInterval(const struct snd_pcm_hw_params& params,
int n, unsigned int* min,
unsigned int* max)
{
struct snd_interval* interval = param_to_interval(
const_cast<struct snd_pcm_hw_params*>(&params), n);
*min = interval->min;
*max = interval->max;
}
// This was hacked out of "alsa_utils.cpp".
static int s_get_alsa_card_name(char *name, size_t len, int card_id)
{
int fd;
int amt = -1;
snprintf(name, len, "/proc/asound/card%d/id", card_id);
fd = open(name, O_RDONLY);
if (fd >= 0) {
amt = read(fd, name, len - 1);
if (amt > 0) {
// replace the '\n' at the end of the proc file with '\0'
name[amt - 1] = 0;
}
close(fd);
}
return amt;
}
bool AudioHotplugThread::getDeviceInfo(unsigned int pcmCard,
unsigned int pcmDevice,
DeviceInfo* info)
{
bool result = false;
int ret;
int len;
char cardName[64] = "";
String8 devicePath = String8::format("%s/pcmC%dD%d%c",
kAlsaDeviceDir, pcmCard, pcmDevice, kDeviceTypeCapture);
ALOGD("AudioHotplugThread::getDeviceInfo opening %s", devicePath.string());
int alsaFD = open(devicePath.string(), O_RDONLY);
if (alsaFD == -1) {
ALOGE("AudioHotplugThread::getDeviceInfo open failed for %s", devicePath.string());
goto done;
}
// query the device's ALSA configuration space
struct snd_pcm_hw_params params;
param_init(&params);
ret = ioctl(alsaFD, SNDRV_PCM_IOCTL_HW_REFINE, &params);
if (ret == -1) {
ALOGE("AudioHotplugThread: refine ioctl failed");
goto done;
}
info->pcmCard = pcmCard;
info->pcmDevice = pcmDevice;
getAlsaParamInterval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
&info->minSampleBits, &info->maxSampleBits);
getAlsaParamInterval(params, SNDRV_PCM_HW_PARAM_CHANNELS,
&info->minChannelCount, &info->maxChannelCount);
getAlsaParamInterval(params, SNDRV_PCM_HW_PARAM_RATE,
&info->minSampleRate, &info->maxSampleRate);
// Ugly hack to recognize Remote mic and mark it for voice recognition
info->forVoiceRecognition = false;
len = s_get_alsa_card_name(cardName, sizeof(cardName), pcmCard);
ALOGD("AudioHotplugThread get_alsa_card_name returned %d, %s", len, cardName);
if (len > 0) {
if (strcmp(ANDROID_TV_REMOTE_AUDIO_DEVICE_NAME, cardName) == 0) {
ALOGD("AudioHotplugThread found Android TV remote mic on Card %d, for VOICE_RECOGNITION", pcmCard);
info->forVoiceRecognition = true;
}
}
result = true;
done:
if (alsaFD != -1) {
close(alsaFD);
}
return result;
}
// scan the ALSA device directory for a usable capture device
void AudioHotplugThread::scanForDevice()
{
DIR* alsaDir;
DeviceInfo deviceInfo;
alsaDir = opendir(kAlsaDeviceDir);
if (alsaDir == NULL)
return;
while (true) {
struct dirent entry, *result;
int ret = readdir_r(alsaDir, &entry, &result);
if (ret != 0 || result == NULL)
break;
unsigned int pcmCard, pcmDevice;
if (parseCaptureDeviceName(entry.d_name, &pcmCard, &pcmDevice)) {
if (getDeviceInfo(pcmCard, pcmDevice, &deviceInfo)) {
mCallback.onDeviceFound(deviceInfo);
}
}
}
closedir(alsaDir);
}
bool AudioHotplugThread::threadLoop()
{
int inotifyFD = -1;
int watchFD = -1;
int flags;
// watch for changes to the ALSA device directory
inotifyFD = inotify_init();
if (inotifyFD == -1) {
ALOGE("AudioHotplugThread: inotify_init failed");
goto done;
}
flags = fcntl(inotifyFD, F_GETFL, 0);
if (flags == -1) {
ALOGE("AudioHotplugThread: F_GETFL failed");
goto done;
}
if (fcntl(inotifyFD, F_SETFL, flags | O_NONBLOCK) == -1) {
ALOGE("AudioHotplugThread: F_SETFL failed");
goto done;
}
watchFD = inotify_add_watch(inotifyFD, kAlsaDeviceDir,
IN_CREATE | IN_DELETE);
if (watchFD == -1) {
ALOGE("AudioHotplugThread: inotify_add_watch failed");
goto done;
}
// check for any existing capture devices
scanForDevice();
while (!exitPending()) {
// wait for a change to the ALSA directory or a shutdown signal
struct pollfd fds[2] = {
{ inotifyFD, POLLIN, 0 },
{ mShutdownEventFD, POLLIN, 0 }
};
int ret = poll(fds, NELEM(fds), -1);
if (ret == -1) {
ALOGE("AudioHotplugThread: poll failed");
break;
} else if (fds[1].revents & POLLIN) {
// shutdown requested
break;
}
if (!(fds[0].revents & POLLIN)) {
continue;
}
// parse the filesystem change events
char eventBuf[256];
ret = read(inotifyFD, eventBuf, sizeof(eventBuf));
if (ret == -1) {
ALOGE("AudioHotplugThread: read failed");
break;
}
for (int i = 0; i < ret;) {
if ((ret - i) < (int)sizeof(struct inotify_event)) {
ALOGE("AudioHotplugThread: read an invalid inotify_event");
break;
}
struct inotify_event *event =
reinterpret_cast<struct inotify_event*>(eventBuf + i);
if ((ret - i) < (int)(sizeof(struct inotify_event) + event->len)) {
ALOGE("AudioHotplugThread: read a bad inotify_event length");
break;
}
char *name = ((char *) event) +
offsetof(struct inotify_event, name);
unsigned int pcmCard, pcmDevice;
if (parseCaptureDeviceName(name, &pcmCard, &pcmDevice)) {
if (event->mask & IN_CREATE) {
// Some devices can not be opened immediately after the
// inotify event occurs. Add a delay to avoid these
// races. (50ms was chosen arbitrarily)
const int kOpenTimeoutMs = 50;
struct pollfd pfd = {mShutdownEventFD, POLLIN, 0};
if (poll(&pfd, 1, kOpenTimeoutMs) == -1) {
ALOGE("AudioHotplugThread: poll failed");
break;
} else if (pfd.revents & POLLIN) {
// shutdown requested
break;
}
DeviceInfo deviceInfo;
if (getDeviceInfo(pcmCard, pcmDevice, &deviceInfo)) {
mCallback.onDeviceFound(deviceInfo);
}
} else if (event->mask & IN_DELETE) {
mCallback.onDeviceRemoved(pcmCard, pcmDevice);
}
}
i += sizeof(struct inotify_event) + event->len;
}
}
done:
if (watchFD != -1) {
inotify_rm_watch(inotifyFD, watchFD);
}
if (inotifyFD != -1) {
close(inotifyFD);
}
return false;
}
}; // namespace android

View file

@ -0,0 +1,69 @@
/*
**
** Copyright 2012, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
#ifndef ANDROID_AUDIO_HOTPLUG_THREAD_H
#define ANDROID_AUDIO_HOTPLUG_THREAD_H
#include <utils/threads.h>
namespace android {
class AudioHotplugThread : public Thread {
public:
struct DeviceInfo {
unsigned int pcmCard;
unsigned int pcmDevice;
unsigned int minSampleBits, maxSampleBits;
unsigned int minChannelCount, maxChannelCount;
unsigned int minSampleRate, maxSampleRate;
bool valid;
bool forVoiceRecognition;
};
class Callback {
public:
virtual ~Callback() {}
virtual void onDeviceFound(const DeviceInfo& devInfo) = 0;
virtual void onDeviceRemoved(unsigned int pcmCard, unsigned int pcmDevice) = 0;
};
AudioHotplugThread(Callback& callback);
virtual ~AudioHotplugThread();
bool start();
void shutdown();
private:
static const char* kThreadName;
static const char* kAlsaDeviceDir;
static const char kDeviceTypeCapture;
static bool parseCaptureDeviceName(const char *name, unsigned int *pcmCard,
unsigned int *pcmDevice);
static bool getDeviceInfo(unsigned int pcmCard, unsigned int pcmDevice,
DeviceInfo* info);
virtual bool threadLoop();
void scanForDevice();
Callback& mCallback;
int mShutdownEventFD;
};
}; // namespace android
#endif // ANDROID_AUDIO_HOTPLUG_THREAD_H

View file

@ -0,0 +1,524 @@
/*
**
** Copyright 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.
*/
#define LOG_TAG "AudioHAL:AudioOutput"
// #define LOG_NDEBUG 0
#include <utils/Log.h>
#include <assert.h>
#include <limits.h>
#include <semaphore.h>
#include <sys/ioctl.h>
#include <audio_utils/primitives.h>
#include <common_time/local_clock.h>
#define __DO_FUNCTION_IMPL__
#include "alsa_utils.h"
#undef __DO_FUNCTION_IMPL__
#include "AudioOutput.h"
// TODO: Consider using system/media/alsa_utils for the future.
namespace android {
const uint32_t AudioOutput::kMaxDelayCompensationMSec = 300;
const uint32_t AudioOutput::kPrimeTimeoutChunks = 10; // 100ms
AudioOutput::AudioOutput(const char* alsa_name,
enum pcm_format alsa_pcm_format)
: mState(OUT_OF_SYNC)
, mFramesPerChunk(0)
, mFramesPerSec(0)
, mBufferChunks(0)
, mChannelCnt(0)
, mALSAName(alsa_name)
, mALSAFormat(alsa_pcm_format)
, mBytesPerSample(0)
, mBytesPerFrame(0)
, mBytesPerChunk(0)
, mStagingSize(0)
, mStagingBuf(NULL)
, mSilenceSize(0)
, mSilenceBuf(NULL)
, mPrimeTimeoutChunks(0)
, mReportedWriteFail(false)
, mVolume(0.0)
, mFixedLvl(0.0)
, mMute(false)
, mOutputFixed(false)
, mVolParamsDirty(true)
{
mLastNextWriteTimeValid = false;
mMaxDelayCompFrames = 0;
mExternalDelayUSec = 0;
mDevice = NULL;
mDeviceExtFd = -1;
mALSACardID = -1;
mFramesQueuedToDriver = 0;
}
AudioOutput::~AudioOutput() {
cleanupResources();
free(mStagingBuf);
free(mSilenceBuf);
}
status_t AudioOutput::initCheck() {
if (!mDevice) {
ALOGE("Unable to open PCM device for %s output.", getOutputName());
return NO_INIT;
}
if (!pcm_is_ready(mDevice)) {
ALOGE("PCM device %s is not ready.", getOutputName());
ALOGE("PCM error: %s", pcm_get_error(mDevice));
return NO_INIT;
}
return OK;
}
void AudioOutput::setupInternal() {
LocalClock lc;
mMaxDelayCompFrames = kMaxDelayCompensationMSec * mFramesPerSec / 1000;
switch (mALSAFormat) {
case PCM_FORMAT_S16_LE:
mBytesPerSample = 2;
break;
case PCM_FORMAT_S24_3LE:
mBytesPerSample = 3;
break;
case PCM_FORMAT_S24_LE: // fall through
case PCM_FORMAT_S32_LE:
mBytesPerSample = 4;
break;
default:
LOG_ALWAYS_FATAL("Unexpected alsa format %d", mALSAFormat);
break;
}
mBytesPerFrame = mBytesPerSample * mChannelCnt;
mBytesPerChunk = mBytesPerFrame * mFramesPerChunk;
memset(&mFramesToLocalTime, 0, sizeof(mFramesToLocalTime));
mFramesToLocalTime.a_to_b_numer = lc.getLocalFreq();
mFramesToLocalTime.a_to_b_denom = mFramesPerSec ? mFramesPerSec : 1;
LinearTransform::reduce(
&mFramesToLocalTime.a_to_b_numer,
&mFramesToLocalTime.a_to_b_denom);
openPCMDevice();
}
void AudioOutput::primeOutput(bool hasActiveOutputs) {
ALOGI("primeOutput %s", getOutputName());
if (hasFatalError())
return;
// See comments in AudioStreamOut::write for the reasons behind the
// different priming levels.
uint32_t primeAmt = mFramesPerChunk * mBufferChunks;
if (hasActiveOutputs)
primeAmt /= 2;
pushSilence(primeAmt);
mPrimeTimeoutChunks = 0;
mState = PRIMED;
}
void AudioOutput::adjustDelay(int32_t nFrames) {
if (hasFatalError())
return;
if (nFrames >= 0) {
ALOGI("adjustDelay %s %d", getOutputName(), nFrames);
pushSilence(nFrames);
mState = ACTIVE;
} else {
ALOGW("adjustDelay %s %d, ignoring negative adjustment",
getOutputName(), nFrames);
}
}
void AudioOutput::pushSilence(uint32_t nFrames)
{
if (nFrames == 0 || hasFatalError())
return;
// choose 8_24_BIT instead of 16_BIT as it is native to Fugu
const audio_format_t format = AUDIO_FORMAT_PCM_8_24_BIT;
const size_t frameSize = audio_bytes_per_sample(format) * mChannelCnt;
const size_t writeSize = nFrames * frameSize;
if (mSilenceSize < writeSize) {
// for zero initialized memory calloc is much faster than malloc or realloc.
void *sbuf = calloc(nFrames, frameSize);
if (sbuf == NULL) return;
free(mSilenceBuf);
mSilenceBuf = sbuf;
mSilenceSize = writeSize;
}
doPCMWrite((const uint8_t*)mSilenceBuf, writeSize, format);
mFramesQueuedToDriver += nFrames;
}
void AudioOutput::cleanupResources() {
Mutex::Autolock _l(mDeviceLock);
if (NULL != mDevice)
pcm_close(mDevice);
mDevice = NULL;
mDeviceExtFd = -1;
mALSACardID = -1;
}
void AudioOutput::openPCMDevice() {
Mutex::Autolock _l(mDeviceLock);
if (NULL == mDevice) {
struct pcm_config config;
int dev_id = 0;
int retry = 0;
static const int MAX_RETRY_COUNT = 3;
mALSACardID = find_alsa_card_by_name(mALSAName);
if (mALSACardID < 0)
return;
memset(&config, 0, sizeof(config));
config.channels = mChannelCnt;
config.rate = mFramesPerSec;
config.period_size = mFramesPerChunk;
config.period_count = mBufferChunks;
config.format = mALSAFormat;
// start_threshold is in audio frames. The default behavior
// is to fill period_size*period_count frames before outputing
// audio. Setting to 1 will start the DMA immediately. Our first
// write is a full chunk, so we have 10ms to get back with the next
// chunk before we underflow. This number could be increased if
// problems arise.
config.start_threshold = 1;
ALOGI("calling pcm_open() for output, mALSACardID = %d, dev_id %d, rate = %u, "
"%d channels, framesPerChunk = %d, alsaFormat = %d",
mALSACardID, dev_id, config.rate, config.channels, config.period_size, config.format);
while (1) {
// Use PCM_MONOTONIC clock for get_presentation_position.
mDevice = pcm_open(mALSACardID, dev_id,
PCM_OUT | PCM_NORESTART | PCM_MONOTONIC, &config);
if (initCheck() == OK)
break;
if (retry++ >= MAX_RETRY_COUNT) {
ALOGI("out of retries, giving up");
break;
}
/* try again after a delay. on hotplug, there appears to
* be a race where the pcm device node isn't available on
* first open try.
*/
pcm_close(mDevice);
mDevice = NULL;
sleep(1);
ALOGI("retrying pcm_open() after delay");
}
mDeviceExtFd = mDevice
? *(reinterpret_cast<int*>(mDevice))
: -1;
mState = OUT_OF_SYNC;
}
}
status_t AudioOutput::getNextWriteTimestamp(int64_t* timestamp,
bool* discon) {
int64_t dma_start_time;
int64_t frames_queued_to_driver;
status_t ret;
*discon = false;
if (hasFatalError())
return UNKNOWN_ERROR;
ret = getDMAStartData(&dma_start_time,
&frames_queued_to_driver);
if (OK != ret) {
if (mLastNextWriteTimeValid) {
if (!hasFatalError())
ALOGE("Underflow detected for output \"%s\"", getOutputName());
*discon = true;
}
goto bailout;
}
if (mLastNextWriteTimeValid && (mLastDMAStartTime != dma_start_time)) {
*discon = true;
ret = UNKNOWN_ERROR;
ALOGE("Discontinuous DMA start time detected for output \"%s\"."
"DMA start time is %lld, but last DMA start time was %lld.",
getOutputName(), dma_start_time, mLastDMAStartTime);
goto bailout;
}
mLastDMAStartTime = dma_start_time;
mFramesToLocalTime.a_zero = 0;
mFramesToLocalTime.b_zero = dma_start_time;
if (!mFramesToLocalTime.doForwardTransform(frames_queued_to_driver,
timestamp)) {
ALOGE("Overflow when attempting to compute next write time for output"
" \"%s\". Frames Queued To Driver = %lld, DMA Start Time = %lld",
getOutputName(), frames_queued_to_driver, dma_start_time);
ret = UNKNOWN_ERROR;
goto bailout;
}
mLastNextWriteTime = *timestamp;
mLastNextWriteTimeValid = true;
// If we have a valuid timestamp, DMA has started so advance the state.
if (mState == PRIMED)
mState = DMA_START;
return OK;
bailout:
mLastNextWriteTimeValid = false;
// If we underflow, reset this output now.
if (mState > PRIMED) {
reset();
}
return ret;
}
bool AudioOutput::getLastNextWriteTSValid() const {
return mLastNextWriteTimeValid;
}
int64_t AudioOutput::getLastNextWriteTS() const {
return mLastNextWriteTime;
}
uint32_t AudioOutput::getExternalDelay_uSec() const {
return mExternalDelayUSec;
}
void AudioOutput::setExternalDelay_uSec(uint32_t delay_usec) {
mExternalDelayUSec = delay_usec;
}
void AudioOutput::reset() {
if (hasFatalError())
return;
// Flush the driver level.
cleanupResources();
openPCMDevice();
mFramesQueuedToDriver = 0;
mLastNextWriteTimeValid = false;
if (OK == initCheck()) {
ALOGE("Reset %s", mALSAName);
} else {
ALOGE("Reset for %s failed, device is a zombie pending cleanup.", mALSAName);
cleanupResources();
mState = FATAL;
}
}
status_t AudioOutput::getDMAStartData(
int64_t* dma_start_time,
int64_t* frames_queued_to_driver) {
int ret;
#if 1 /* not implemented in driver yet, just fake it */
*dma_start_time = mLastDMAStartTime;
ret = 0;
#endif
// If the get start time ioctl fails with an error of EBADFD, then our
// underlying audio device is in the DISCONNECTED state. The only reason
// this should happen is that HDMI was unplugged while we were running, and
// the audio driver needed to immediately shut down the driver without
// involving the application level. We should enter the fatal state, and
// wait until the app level catches up to our view of the world (at which
// point in time we will go through a plug/unplug cycle which should clean
// things up).
if (ret < 0) {
if (EBADFD == errno) {
ALOGI("Failed to ioctl to %s, output is probably disconnected."
" Going into zombie state to await cleanup.", mALSAName);
cleanupResources();
mState = FATAL;
}
return UNKNOWN_ERROR;
}
*frames_queued_to_driver = mFramesQueuedToDriver;
return OK;
}
void AudioOutput::processOneChunk(const uint8_t* data, size_t len,
bool hasActiveOutputs, audio_format_t format) {
switch (mState) {
case OUT_OF_SYNC:
primeOutput(hasActiveOutputs);
break;
case PRIMED:
if (mPrimeTimeoutChunks < kPrimeTimeoutChunks)
mPrimeTimeoutChunks++;
else
// Uh-oh, DMA didn't start. Reset and try again.
reset();
break;
case DMA_START:
// Don't push data when primed and waiting for buffer alignment.
// We need to align the ALSA buffers first.
break;
case ACTIVE: {
doPCMWrite(data, len, format);
// we use input frame size here (mBytesPerFrame is alsa device frame size)
const size_t frameSize = mChannelCnt * audio_bytes_per_sample(format);
mFramesQueuedToDriver += len / frameSize;
} break;
default:
// Do nothing.
break;
}
}
void AudioOutput::doPCMWrite(const uint8_t* data, size_t len, audio_format_t format) {
if (len == 0 || hasFatalError())
return;
// If write fails with an error of EBADFD, then our underlying audio
// device is in a pretty bad state. This common cause of this is
// that HDMI was unplugged while we were running, and the audio
// driver needed to immediately shut down the driver without
// involving the application level. When this happens, the HDMI
// audio device is put into the DISCONNECTED state, and calls to
// write will return EBADFD.
#if 1
/* Intel HDMI appears to be locked at 24bit PCM, but Android
* will send data in the format specified in adev_open_output_stream().
*/
LOG_ALWAYS_FATAL_IF(mALSAFormat != PCM_FORMAT_S24_LE,
"Fugu alsa device format(%d) must be PCM_FORMAT_S24_LE", mALSAFormat);
int err = BAD_VALUE;
switch(format) {
case AUDIO_FORMAT_IEC61937:
case AUDIO_FORMAT_PCM_16_BIT: {
const size_t outputSize = len * 2;
if (outputSize > mStagingSize) {
void *buf = realloc(mStagingBuf, outputSize);
if (buf == NULL) {
ALOGE("%s: memory allocation for conversion buffer failed", __func__);
return;
}
mStagingBuf = buf;
mStagingSize = outputSize;
}
memcpy_to_q8_23_from_i16((int32_t*)mStagingBuf, (const int16_t*)data, len >> 1);
err = pcm_write(mDevice, mStagingBuf, outputSize);
} break;
case AUDIO_FORMAT_PCM_8_24_BIT:
err = pcm_write(mDevice, data, len);
break;
default:
LOG_ALWAYS_FATAL("Fugu input format(%#x) should be 16 bit or 8_24 bit pcm", format);
break;
}
#else
int err = pcm_write(mDevice, data, len);
#endif
if ((err < 0) && (EBADFD == errno)) {
ALOGI("Failed to write to %s, output is probably disconnected."
" Going into zombie state to await cleanup.", mALSAName);
cleanupResources();
mState = FATAL;
}
else if (err < 0) {
ALOGW_IF(!mReportedWriteFail, "pcm_write failed err %d", err);
mReportedWriteFail = true;
}
else {
mReportedWriteFail = false;
#if 1 /* not implemented in driver yet, just fake it */
LocalClock lc;
mLastDMAStartTime = lc.getLocalTime();
#endif
}
}
void AudioOutput::setVolume(float vol) {
Mutex::Autolock _l(mVolumeLock);
if (mVolume != vol) {
mVolume = vol;
mVolParamsDirty = true;
}
}
void AudioOutput::setMute(bool mute) {
Mutex::Autolock _l(mVolumeLock);
if (mMute != mute) {
mMute = mute;
mVolParamsDirty = true;
}
}
void AudioOutput::setOutputIsFixed(bool fixed) {
Mutex::Autolock _l(mVolumeLock);
if (mOutputFixed != fixed) {
mOutputFixed = fixed;
mVolParamsDirty = true;
}
}
void AudioOutput::setFixedOutputLevel(float level) {
Mutex::Autolock _l(mVolumeLock);
if (mFixedLvl != level) {
mFixedLvl = level;
mVolParamsDirty = true;
}
}
int AudioOutput::getHardwareTimestamp(size_t *pAvail,
struct timespec *pTimestamp)
{
Mutex::Autolock _l(mDeviceLock);
if (!mDevice) {
ALOGW("pcm device unavailable - reinitialize timestamp");
return -1;
}
return pcm_get_htimestamp(mDevice, pAvail, pTimestamp);
}
} // namespace android

View file

@ -0,0 +1,177 @@
/*
**
** Copyright 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_OUTPUT_H
#define ANDROID_AUDIO_OUTPUT_H
#include <semaphore.h>
#include <tinyalsa/asoundlib.h>
#include <utils/String16.h>
#include <utils/String8.h>
#include <utils/threads.h>
#include <utils/Vector.h>
#include "LinearTransform.h"
namespace android {
class AudioStreamOut;
class AudioOutput : public RefBase {
public:
// Audio ouput state machine states.
enum State {
// Ouput not yet started or synchronized.
OUT_OF_SYNC,
// Silence primed to output to start DMA.
PRIMED,
// DMA started, ready to align to other inputs.
DMA_START,
// DMA active.
ACTIVE,
// Fatal, unrecoverable error.
FATAL,
};
AudioOutput(const char* alsa_name,
enum pcm_format alsa_pcm_format);
virtual ~AudioOutput();
virtual status_t initCheck();
virtual status_t setupForStream(const AudioStreamOut& stream) = 0;
// State machine transition functions.
State getState() { return mState; };
bool hasFatalError() { return mState == FATAL; }
// Prime data to output device, go to PRIMED state.
void primeOutput(bool hasActiveOutputs);
// Adjust for write timestamp difference, go to ACTIVE state.
void adjustDelay(int32_t nFrames);
// Send one chunk of data to ALSA, if state machine permits. This is called
// for every chunk sent down, regardless of the state of the output.
void processOneChunk(const uint8_t* data, size_t len,
bool hasActiveOutputs, audio_format_t format);
status_t getNextWriteTimestamp(int64_t* timestamp,
bool* discon);
bool getLastNextWriteTSValid() const;
int64_t getLastNextWriteTS() const;
uint32_t getExternalDelay_uSec() const;
void setExternalDelay_uSec(uint32_t delay);
void setDelayComp_uSec(uint32_t delay_usec);
void setVolume(float vol);
void setMute(bool mute);
void setOutputIsFixed(bool fixed);
void setFixedOutputLevel(float level);
float getVolume() const { return mVolume; }
bool getMute() const { return mMute; }
bool getOutputIsFixed() const { return mOutputFixed; }
float getFixedOutputLevel() const { return mFixedLvl; }
int getHardwareTimestamp(unsigned int *pAvail,
struct timespec *pTimestamp);
uint32_t getKernelBufferSize() { return mFramesPerChunk * mBufferChunks; }
virtual void dump(String8& result) = 0;
virtual const char* getOutputName() = 0;
virtual uint32_t devMask() const = 0;
virtual void cleanupResources();
static const uint32_t kMaxDelayCompensationMSec;
static const uint32_t kPrimeTimeoutChunks;
protected:
void pushSilence(uint32_t nFrames);
virtual void openPCMDevice();
virtual void reset();
virtual status_t getDMAStartData(int64_t* dma_start_time,
int64_t* frames_queued_to_driver);
void doPCMWrite(const uint8_t* data, size_t len, audio_format_t format);
void setupInternal();
// Current state machine state.
State mState;
// Output format
uint32_t mFramesPerChunk;
uint32_t mFramesPerSec;
uint32_t mBufferChunks;
uint32_t mChannelCnt;
const char* mALSAName;
enum pcm_format mALSAFormat;
// These numbers are relative to the ALSA output.
uint32_t mBytesPerSample;
uint32_t mBytesPerFrame;
uint32_t mBytesPerChunk;
size_t mStagingSize;
void* mStagingBuf;
size_t mSilenceSize;
void* mSilenceBuf;
// Get next write time stuff.
bool mLastNextWriteTimeValid;
int64_t mLastNextWriteTime;
int64_t mLastDMAStartTime;
// External delay compensation.
uint32_t mMaxDelayCompFrames;
uint32_t mExternalDelayUSec;
uint32_t mExternalDelayLocalTicks;
LinearTransform mFramesToLocalTime;
// ALSA device stuff.
Mutex mDeviceLock;
struct pcm* mDevice;
int mDeviceExtFd;
int mALSACardID;
uint64_t mFramesQueuedToDriver;
uint32_t mPrimeTimeoutChunks;
// reduce log spew
bool mReportedWriteFail;
// Volume stuff
Mutex mVolumeLock;
float mVolume;
float mFixedLvl;
bool mMute;
bool mOutputFixed;
bool mVolParamsDirty;
virtual void applyPendingVolParams() = 0;
};
typedef Vector< sp<AudioOutput> > AudioOutputList;
} // namespace android
#endif // ANDROID_AUDIO_OUTPUT_H

View file

@ -0,0 +1,550 @@
/*
**
** Copyright 2012, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
#define LOG_TAG "AudioHAL:AudioStreamIn"
#include <utils/Log.h>
#include "AudioStreamIn.h"
#include "AudioHardwareInput.h"
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <utils/String8.h>
#include <media/AudioParameter.h>
// for turning Remote mic on/off
#ifdef REMOTE_CONTROL_INTERFACE
#include <IRemoteControlService.h>
#endif
namespace android {
const audio_format_t AudioStreamIn::kAudioFormat = AUDIO_FORMAT_PCM_16_BIT;
const uint32_t AudioStreamIn::kChannelMask = AUDIO_CHANNEL_IN_MONO;
// number of periods in the ALSA buffer
const int AudioStreamIn::kPeriodCount = 32;
AudioStreamIn::AudioStreamIn(AudioHardwareInput& owner)
: mOwnerHAL(owner)
, mCurrentDeviceInfo(NULL)
, mRequestedSampleRate(0)
, mStandby(true)
, mDisabled(false)
, mPcm(NULL)
, mResampler(NULL)
, mBuffer(NULL)
, mBufferSize(0)
, mInputSource(AUDIO_SOURCE_DEFAULT)
, mReadStatus(0)
, mFramesIn(0)
, mLastReadFinishedNs(-1)
, mLastBytesRead(0)
, mMinAllowedReadTimeNs(0)
{
struct resampler_buffer_provider& provider =
mResamplerProviderWrapper.provider;
provider.get_next_buffer = getNextBufferThunk;
provider.release_buffer = releaseBufferThunk;
mResamplerProviderWrapper.thiz = this;
}
AudioStreamIn::~AudioStreamIn()
{
Mutex::Autolock _l(mLock);
standby_l();
}
// Perform stream initialization that may fail.
// Must only be called once at construction time.
status_t AudioStreamIn::set(audio_format_t *pFormat, uint32_t *pChannelMask,
uint32_t *pRate)
{
Mutex::Autolock _l(mLock);
assert(mRequestedSampleRate == 0);
// Respond with a request for mono if a different format is given.
if (*pChannelMask != kChannelMask) {
*pChannelMask = kChannelMask;
return BAD_VALUE;
}
if (*pFormat != kAudioFormat) {
*pFormat = kAudioFormat;
return BAD_VALUE;
}
mRequestedSampleRate = *pRate;
return NO_ERROR;
}
uint32_t AudioStreamIn::getSampleRate()
{
Mutex::Autolock _l(mLock);
return mRequestedSampleRate;
}
status_t AudioStreamIn::setSampleRate(uint32_t rate)
{
(void) rate;
// this is a no-op in other audio HALs
return NO_ERROR;
}
size_t AudioStreamIn::getBufferSize()
{
Mutex::Autolock _l(mLock);
size_t size = AudioHardwareInput::calculateInputBufferSize(
mRequestedSampleRate, kAudioFormat, getChannelCount());
return size;
}
uint32_t AudioStreamIn::getChannelMask()
{
return kChannelMask;
}
audio_format_t AudioStreamIn::getFormat()
{
return kAudioFormat;
}
status_t AudioStreamIn::setFormat(audio_format_t format)
{
(void) format;
// other audio HALs fail any call to this API (even if the format matches
// the current format)
return INVALID_OPERATION;
}
status_t AudioStreamIn::standby()
{
Mutex::Autolock _l(mLock);
return standby_l();
}
status_t AudioStreamIn::standby_l()
{
if (mStandby) {
return NO_ERROR;
}
if (mPcm) {
ALOGD("AudioStreamIn::standby_l, call pcm_close()");
pcm_close(mPcm);
mPcm = NULL;
}
// Turn OFF Remote MIC if we were recording from Remote.
if (mCurrentDeviceInfo != NULL) {
if (mCurrentDeviceInfo->forVoiceRecognition) {
setRemoteControlMicEnabled(false);
}
}
if (mResampler) {
release_resampler(mResampler);
mResampler = NULL;
}
if (mBuffer) {
delete [] mBuffer;
mBuffer = NULL;
}
mCurrentDeviceInfo = NULL;
mStandby = true;
mDisabled = false;
return NO_ERROR;
}
#define DUMP(a...) \
snprintf(buffer, SIZE, a); \
buffer[SIZE - 1] = 0; \
result.append(buffer);
status_t AudioStreamIn::dump(int fd)
{
const size_t SIZE = 256;
char buffer[SIZE];
String8 result;
DUMP("\n AudioStreamIn::dump\n");
{
DUMP("\toutput sample rate: %d\n", mRequestedSampleRate);
if (mPcm) {
DUMP("\tinput sample rate: %d\n", mPcmConfig.rate);
DUMP("\tinput channels: %d\n", mPcmConfig.channels);
}
}
::write(fd, result.string(), result.size());
return NO_ERROR;
}
status_t AudioStreamIn::setParameters(struct audio_stream* stream,
const char* kvpairs)
{
(void) stream;
AudioParameter param = AudioParameter(String8(kvpairs));
status_t status = NO_ERROR;
String8 keySource = String8(AudioParameter::keyInputSource);
int intVal;
if (param.getInt(keySource, intVal) == NO_ERROR) {
ALOGI("AudioStreamIn::setParameters, mInputSource set to %d", intVal);
mInputSource = intVal;
}
return status;
}
char* AudioStreamIn::getParameters(const char* keys)
{
(void) keys;
return strdup("");
}
status_t AudioStreamIn::setGain(float gain)
{
(void) gain;
// In other HALs, this is a no-op and returns success.
return NO_ERROR;
}
uint32_t AudioStreamIn::getInputFramesLost()
{
return 0;
}
status_t AudioStreamIn::addAudioEffect(effect_handle_t effect)
{
(void) effect;
// In other HALs, this is a no-op and returns success.
return 0;
}
status_t AudioStreamIn::removeAudioEffect(effect_handle_t effect)
{
(void) effect;
// In other HALs, this is a no-op and returns success.
return 0;
}
ssize_t AudioStreamIn::read(void* buffer, size_t bytes)
{
Mutex::Autolock _l(mLock);
status_t status = NO_ERROR;
if (mStandby) {
status = startInputStream_l();
// Only try to start once to prevent pointless spew.
// If mic is not available then read will return silence.
// This is needed to prevent apps from hanging.
mStandby = false;
if (status != NO_ERROR) {
mDisabled = true;
}
}
if ((status == NO_ERROR) && !mDisabled) {
int ret = readFrames_l(buffer, bytes / getFrameSize());
status = (ret < 0) ? INVALID_OPERATION : NO_ERROR;
}
if ((status != NO_ERROR) || mDisabled) {
memset(buffer, 0, bytes);
// TODO: This code needs to project a timeline based on the number
// of audio frames synthesized from the last time we returned data
// from an actual audio device (or establish a fake timeline to obey
// if we have never returned any data from an actual device and need
// to synth on the first call to read)
usleep(bytes * 1000000 / getFrameSize() / mRequestedSampleRate);
mLastReadFinishedNs = -1;
} else {
bool mute;
mOwnerHAL.getMicMute(&mute);
if (mute) {
memset(buffer, 0, bytes);
}
nsecs_t now = systemTime();
if (mLastReadFinishedNs != -1) {
const nsecs_t kMinsleeptimeNs = 1000000; // don't sleep less than 1ms
const nsecs_t deltaNs = now - mLastReadFinishedNs;
if (bytes != mLastBytesRead) {
mMinAllowedReadTimeNs =
(((nsecs_t)bytes * 1000000000) / getFrameSize()) / mRequestedSampleRate / 2;
mLastBytesRead = bytes;
}
// Make sure total read time is at least the duration corresponding to half the amount
// of data requested.
// Note: deltaNs is always > 0 here
if (mMinAllowedReadTimeNs > deltaNs + kMinsleeptimeNs) {
usleep((mMinAllowedReadTimeNs - deltaNs) / 1000);
// Throttle must be attributed to the previous read time to allow
// back-to-back throttling.
now = systemTime();
}
}
mLastReadFinishedNs = now;
}
return bytes;
}
void AudioStreamIn::setRemoteControlMicEnabled(bool flag)
{
#ifdef REMOTE_CONTROL_INTERFACE
sp<IRemoteControlService> service = IRemoteControlService::getInstance();
if (service == NULL) {
ALOGE("%s: No RemoteControl service detected, ignoring\n", __func__);
return;
}
service->setMicEnabled(flag);
#else
(void)flag;
#endif
}
status_t AudioStreamIn::startInputStream_l()
{
ALOGI("AudioStreamIn::startInputStream_l, entry");
// Get the most appropriate device for the given input source, eg VOICE_RECOGNITION
const AudioHotplugThread::DeviceInfo *deviceInfo = mOwnerHAL.getBestDevice(mInputSource);
if (deviceInfo == NULL) {
return INVALID_OPERATION;
}
memset(&mPcmConfig, 0, sizeof(mPcmConfig));
unsigned int requestedChannelCount = getChannelCount();
// Clip to min/max available.
if (requestedChannelCount < deviceInfo->minChannelCount ) {
mPcmConfig.channels = deviceInfo->minChannelCount;
} else if (requestedChannelCount > deviceInfo->maxChannelCount ) {
mPcmConfig.channels = deviceInfo->maxChannelCount;
} else {
mPcmConfig.channels = requestedChannelCount;
}
ALOGD("AudioStreamIn::startInputStream_l, mRequestedSampleRate = %d",
mRequestedSampleRate);
// Clip to min/max available from driver.
uint32_t chosenSampleRate = mRequestedSampleRate;
if (chosenSampleRate < deviceInfo->minSampleRate) {
chosenSampleRate = deviceInfo->minSampleRate;
} else if (chosenSampleRate > deviceInfo->maxSampleRate) {
chosenSampleRate = deviceInfo->maxSampleRate;
}
// Turn on RemoteControl MIC if we are recording from it.
if (deviceInfo->forVoiceRecognition) {
setRemoteControlMicEnabled(true);
}
mPcmConfig.rate = chosenSampleRate;
mPcmConfig.period_size =
AudioHardwareInput::kPeriodMsec * mPcmConfig.rate / 1000;
mPcmConfig.period_count = kPeriodCount;
mPcmConfig.format = PCM_FORMAT_S16_LE;
ALOGD("AudioStreamIn::startInputStream_l, call pcm_open()");
struct pcm* pcm = pcm_open(deviceInfo->pcmCard, deviceInfo->pcmDevice,
PCM_IN, &mPcmConfig);
if (!pcm_is_ready(pcm)) {
ALOGE("ERROR AudioStreamIn::startInputStream_l, pcm_open failed");
pcm_close(pcm);
if (deviceInfo->forVoiceRecognition) {
setRemoteControlMicEnabled(false);
}
return NO_MEMORY;
}
mCurrentDeviceInfo = deviceInfo;
mBufferSize = pcm_frames_to_bytes(pcm, mPcmConfig.period_size);
if (mBuffer) {
delete [] mBuffer;
}
mBuffer = new int16_t[mBufferSize / sizeof(uint16_t)];
mLastReadFinishedNs = -1;
mLastBytesRead = 0;
if (mResampler) {
release_resampler(mResampler);
mResampler = NULL;
}
if (mPcmConfig.rate != mRequestedSampleRate) {
ALOGD("AudioStreamIn::startInputStream_l, call create_resampler( %d to %d)",
mPcmConfig.rate, mRequestedSampleRate);
int ret = create_resampler(mPcmConfig.rate,
mRequestedSampleRate,
1,
RESAMPLER_QUALITY_DEFAULT,
&mResamplerProviderWrapper.provider,
&mResampler);
if (ret != 0) {
ALOGW("AudioStreamIn: unable to create resampler");
pcm_close(pcm);
return static_cast<status_t>(ret);
}
}
mPcm = pcm;
return NO_ERROR;
}
// readFrames() reads frames from kernel driver, down samples to the capture
// rate if necessary and outputs the number of frames requested to the buffer
// specified
ssize_t AudioStreamIn::readFrames_l(void* buffer, ssize_t frames)
{
ssize_t framesWr = 0;
size_t frameSize = getFrameSize();
while (framesWr < frames) {
size_t framesRd = frames - framesWr;
if (mResampler) {
char* outFrame = static_cast<char*>(buffer) +
(framesWr * frameSize);
mResampler->resample_from_provider(
mResampler,
reinterpret_cast<int16_t*>(outFrame),
&framesRd);
} else {
struct resampler_buffer buf;
buf.raw = NULL;
buf.frame_count = framesRd;
getNextBuffer(&buf);
if (buf.raw != NULL) {
memcpy(static_cast<char*>(buffer) + (framesWr * frameSize),
buf.raw,
buf.frame_count * frameSize);
framesRd = buf.frame_count;
}
releaseBuffer(&buf);
}
// mReadStatus is updated by getNextBuffer(), which is called by the
// resampler
if (mReadStatus != 0)
return mReadStatus;
framesWr += framesRd;
}
return framesWr;
}
int AudioStreamIn::getNextBufferThunk(
struct resampler_buffer_provider* bufferProvider,
struct resampler_buffer* buffer)
{
ResamplerBufferProviderWrapper* wrapper =
reinterpret_cast<ResamplerBufferProviderWrapper*>(
reinterpret_cast<char*>(bufferProvider) -
offsetof(ResamplerBufferProviderWrapper, provider));
return wrapper->thiz->getNextBuffer(buffer);
}
void AudioStreamIn::releaseBufferThunk(
struct resampler_buffer_provider* bufferProvider,
struct resampler_buffer* buffer)
{
ResamplerBufferProviderWrapper* wrapper =
reinterpret_cast<ResamplerBufferProviderWrapper*>(
reinterpret_cast<char*>(bufferProvider) -
offsetof(ResamplerBufferProviderWrapper, provider));
wrapper->thiz->releaseBuffer(buffer);
}
// called while holding mLock
int AudioStreamIn::getNextBuffer(struct resampler_buffer* buffer)
{
if (buffer == NULL) {
return -EINVAL;
}
if (mPcm == NULL) {
buffer->raw = NULL;
buffer->frame_count = 0;
mReadStatus = -ENODEV;
return -ENODEV;
}
if (mFramesIn == 0) {
mReadStatus = pcm_read(mPcm, mBuffer, mBufferSize);
if (mReadStatus) {
ALOGE("get_next_buffer() pcm_read error %d", mReadStatus);
buffer->raw = NULL;
buffer->frame_count = 0;
return mReadStatus;
}
mFramesIn = mPcmConfig.period_size;
if (mPcmConfig.channels == 2) {
// Discard the right channel.
// TODO: this is what other HALs are doing to handle stereo input
// devices. Need to verify if this is appropriate for ATV Remote.
for (unsigned int i = 1; i < mFramesIn; i++) {
mBuffer[i] = mBuffer[i * 2];
}
}
}
buffer->frame_count = (buffer->frame_count > mFramesIn) ?
mFramesIn : buffer->frame_count;
buffer->i16 = mBuffer + (mPcmConfig.period_size - mFramesIn);
return mReadStatus;
}
// called while holding mLock
void AudioStreamIn::releaseBuffer(struct resampler_buffer* buffer)
{
if (buffer == NULL) {
return;
}
mFramesIn -= buffer->frame_count;
}
}; // namespace android

View file

@ -0,0 +1,125 @@
/*
**
** Copyright 2012, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
#ifndef ANDROID_AUDIO_STREAM_IN_H
#define ANDROID_AUDIO_STREAM_IN_H
#include <audio_utils/resampler.h>
#include <hardware/audio.h>
#include <tinyalsa/asoundlib.h>
#include <utils/Errors.h>
#include <utils/threads.h>
#include "AudioHotplugThread.h"
namespace android {
class AudioHardwareInput;
class AudioStreamIn {
public:
AudioStreamIn(AudioHardwareInput& owner);
~AudioStreamIn();
uint32_t getSampleRate();
status_t setSampleRate(uint32_t rate);
size_t getBufferSize();
uint32_t getChannelMask();
audio_format_t getFormat();
status_t setFormat(audio_format_t format);
status_t standby();
status_t dump(int fd);
status_t setParameters(struct audio_stream* stream,
const char* kvpairs);
char* getParameters(const char* keys);
status_t setGain(float gain);
ssize_t read(void* buffer, size_t bytes);
uint32_t getInputFramesLost();
status_t addAudioEffect(effect_handle_t effect);
status_t removeAudioEffect(effect_handle_t effect);
status_t set(audio_format_t *pFormat,
uint32_t *pChannelMask,
uint32_t *pRate);
const AudioHotplugThread::DeviceInfo* getDeviceInfo() { return mCurrentDeviceInfo; };
private:
static const uint32_t kChannelMask;
static const uint32_t kChannelCount;
static const audio_format_t kAudioFormat;
static uint32_t getChannelCount() {
return audio_channel_count_from_in_mask(kChannelMask);
}
static uint32_t getFrameSize() {
return getChannelCount() * audio_bytes_per_sample(kAudioFormat);
}
void setRemoteControlMicEnabled(bool flag);
status_t startInputStream_l();
status_t standby_l();
ssize_t readFrames_l(void* buffer, ssize_t frames);
// resampler buffer provider thunks
static int getNextBufferThunk(
struct resampler_buffer_provider* bufferProvider,
struct resampler_buffer* buffer);
static void releaseBufferThunk(
struct resampler_buffer_provider* bufferProvider,
struct resampler_buffer* buffer);
// resampler buffer provider methods
int getNextBuffer(struct resampler_buffer* buffer);
void releaseBuffer(struct resampler_buffer* buffer);
static const int kPeriodCount;
AudioHardwareInput& mOwnerHAL;
const AudioHotplugThread::DeviceInfo* mCurrentDeviceInfo;
Mutex mLock;
uint32_t mRequestedSampleRate;
bool mStandby;
bool mDisabled;
struct pcm* mPcm;
struct pcm_config mPcmConfig;
struct resampler_itfe* mResampler;
struct ResamplerBufferProviderWrapper {
struct resampler_buffer_provider provider;
AudioStreamIn* thiz;
} mResamplerProviderWrapper;
int16_t* mBuffer;
size_t mBufferSize;
int mInputSource;
int mReadStatus;
unsigned int mFramesIn;
nsecs_t mLastReadFinishedNs;
size_t mLastBytesRead;
nsecs_t mMinAllowedReadTimeNs;
};
}; // namespace android
#endif // ANDROID_AUDIO_STREAM_IN_H

View file

@ -0,0 +1,785 @@
/*
**
** Copyright 2012, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
#define LOG_TAG "AudioHAL_AudioStreamOut"
#include <inttypes.h>
#include <utils/Log.h>
#include "AudioHardwareOutput.h"
#include "AudioStreamOut.h"
// Set to 1 to print timestamp data in CSV format.
#ifndef HAL_PRINT_TIMESTAMP_CSV
#define HAL_PRINT_TIMESTAMP_CSV 0
#endif
//#define VERY_VERBOSE_LOGGING
#ifdef VERY_VERBOSE_LOGGING
#define ALOGVV ALOGV
#else
#define ALOGVV(a...) do { } while(0)
#endif
namespace android {
AudioStreamOut::AudioStreamOut(AudioHardwareOutput& owner, bool mcOut, bool isIec958NonAudio)
: mRenderPosition(0)
, mFramesPresented(0)
, mLastPresentationPosition(0)
, mLastPresentationValid(false)
, mOwnerHAL(owner)
, mFramesWritten(0)
, mTgtDevices(0)
, mAudioFlingerTgtDevices(0)
, mIsMCOutput(mcOut)
, mInStandby(false)
, mIsIec958NonAudio(isIec958NonAudio)
, mReportedAvailFail(false)
{
assert(mLocalClock.initCheck());
mPhysOutputs.setCapacity(3);
// Set some reasonable defaults for these. All of this should eventually
// be overwritten by a specific audio flinger configuration, but it does not
// hurt to have something here by default.
mInputSampleRate = 48000;
mInputChanMask = AUDIO_CHANNEL_OUT_STEREO;
mInputFormat = AUDIO_FORMAT_PCM_16_BIT;
mInputNominalChunksInFlight = 4; // pcm_open() fails if not 4!
updateInputNums();
mThrottleValid = false;
memset(&mUSecToLocalTime, 0, sizeof(mUSecToLocalTime));
mUSecToLocalTime.a_to_b_numer = mLocalClock.getLocalFreq();
mUSecToLocalTime.a_to_b_denom = 1000000;
LinearTransform::reduce(&mUSecToLocalTime.a_to_b_numer,
&mUSecToLocalTime.a_to_b_denom);
}
AudioStreamOut::~AudioStreamOut()
{
releaseAllOutputs();
}
status_t AudioStreamOut::set(
audio_format_t *pFormat,
uint32_t *pChannels,
uint32_t *pRate)
{
Mutex::Autolock _l(mRoutingLock);
audio_format_t lFormat = pFormat ? *pFormat : AUDIO_FORMAT_DEFAULT;
uint32_t lChannels = pChannels ? *pChannels : 0;
uint32_t lRate = pRate ? *pRate : 0;
// fix up defaults
if (lFormat == AUDIO_FORMAT_DEFAULT) lFormat = format();
if (lChannels == 0) lChannels = chanMask();
if (lRate == 0) lRate = sampleRate();
if (pFormat) *pFormat = lFormat;
if (pChannels) *pChannels = lChannels;
if (pRate) *pRate = lRate;
if (!audio_has_proportional_frames(lFormat)) {
ALOGW("set: format 0x%08X needs to be wrapped in SPDIF data burst", lFormat);
return BAD_VALUE;
}
if (!mIsMCOutput) {
// If this is the primary stream out, then demand our defaults.
if ((lFormat != AUDIO_FORMAT_PCM_16_BIT && lFormat != AUDIO_FORMAT_PCM_8_24_BIT) ||
(lChannels != chanMask()) ||
(lRate != sampleRate())) {
ALOGW("set: parameters incompatible with defaults");
return BAD_VALUE;
}
} else {
// Else check to see if our HDMI sink supports this format before proceeding.
if (!mOwnerHAL.getHDMIAudioCaps().supportsFormat(
lFormat, lRate, audio_channel_count_from_out_mask(lChannels),
mIsIec958NonAudio)) {
ALOGW("set: parameters incompatible with hdmi capabilities");
return BAD_VALUE;
}
}
mInputFormat = lFormat;
mInputChanMask = lChannels;
mInputSampleRate = lRate;
ALOGI("AudioStreamOut::set: rate = %u, format = 0x%08X\n", lRate, lFormat);
updateInputNums();
return NO_ERROR;
}
void AudioStreamOut::setTgtDevices(uint32_t tgtDevices)
{
Mutex::Autolock _l(mRoutingLock);
if (mTgtDevices != tgtDevices) {
mTgtDevices = tgtDevices;
}
}
status_t AudioStreamOut::standbyHardware()
{
releaseAllOutputs();
mOwnerHAL.standbyStatusUpdate(true, mIsMCOutput);
mInStandby = true;
return NO_ERROR;
}
status_t AudioStreamOut::standby()
{
ALOGI("standby: ==========================");
mRenderPosition = 0;
mLastPresentationValid = false;
// Don't reset the presentation position.
return standbyHardware();
}
void AudioStreamOut::releaseAllOutputs() {
Mutex::Autolock _l(mRoutingLock);
ALOGI("releaseAllOutputs: releasing %d mPhysOutputs", mPhysOutputs.size());
AudioOutputList::iterator I;
for (I = mPhysOutputs.begin(); I != mPhysOutputs.end(); ++I)
mOwnerHAL.releaseOutput(*this, *I);
mPhysOutputs.clear();
}
status_t AudioStreamOut::pause()
{
ALOGI("pause: ==========================");
mLastPresentationValid = false;
return standbyHardware();
}
status_t AudioStreamOut::resume()
{
ALOGI("resume: ==========================");
return NO_ERROR;
}
status_t AudioStreamOut::flush()
{
ALOGI("flush: ==========================");
mRenderPosition = 0;
mFramesPresented = 0;
Mutex::Autolock _l(mPresentationLock);
mLastPresentationPosition = 0;
mLastPresentationValid = false;
return NO_ERROR;
}
void AudioStreamOut::updateInputNums()
{
assert(mLocalClock.initCheck());
mInputChanCount = audio_channel_count_from_out_mask(mInputChanMask);
// 512 is good for AC3 and DTS passthrough.
mInputChunkFrames = 512 * ((outputSampleRate() + 48000 - 1) / 48000);
ALOGV("updateInputNums: chunk size %u from output rate %u\n",
mInputChunkFrames, outputSampleRate());
mInputFrameSize = mInputChanCount * audio_bytes_per_sample(mInputFormat);
// Buffer size is just the frame size multiplied by the number of
// frames per chunk.
mInputBufSize = mInputChunkFrames * mInputFrameSize;
// The nominal latency is just the duration of a chunk * the number of
// chunks we nominally keep in flight at any given point in time.
mInputNominalLatencyUSec = static_cast<uint32_t>(((
static_cast<uint64_t>(mInputChunkFrames)
* 1000000 * mInputNominalChunksInFlight)
/ mInputSampleRate));
memset(&mLocalTimeToFrames, 0, sizeof(mLocalTimeToFrames));
mLocalTimeToFrames.a_to_b_numer = mInputSampleRate;
mLocalTimeToFrames.a_to_b_denom = mLocalClock.getLocalFreq();
LinearTransform::reduce(
&mLocalTimeToFrames.a_to_b_numer,
&mLocalTimeToFrames.a_to_b_denom);
}
void AudioStreamOut::finishedWriteOp(size_t framesWritten,
bool needThrottle)
{
assert(mLocalClock.initCheck());
int64_t now = mLocalClock.getLocalTime();
if (!mThrottleValid || !needThrottle) {
mThrottleValid = true;
mWriteStartLT = now;
mFramesWritten = 0;
}
mFramesWritten += framesWritten;
mFramesPresented += framesWritten;
mRenderPosition += framesWritten;
if (needThrottle) {
int64_t deltaLT;
mLocalTimeToFrames.doReverseTransform(mFramesWritten, &deltaLT);
deltaLT += mWriteStartLT;
deltaLT -= now;
int64_t deltaUSec;
mUSecToLocalTime.doReverseTransform(deltaLT, &deltaUSec);
if (deltaUSec > 0) {
useconds_t sleep_time;
// We should never be a full second ahead of schedule; sanity check
// our throttle time and cap the max sleep time at 1 second.
if (deltaUSec > 1000000) {
ALOGW("throttle time clipped! deltaLT = %" PRIi64 " deltaUSec = %" PRIi64,
deltaLT, deltaUSec);
sleep_time = 1000000;
} else {
sleep_time = static_cast<useconds_t>(deltaUSec);
}
usleep(sleep_time);
}
}
}
static const String8 keyRouting(AudioParameter::keyRouting);
static const String8 keyFormat(AudioParameter::keyFormat);
static const String8 keySupSampleRates(AudioParameter::keyStreamSupportedSamplingRates);
static const String8 keySupFormats(AudioParameter::keyStreamSupportedFormats);
static const String8 keySupChannels(AudioParameter::keyStreamSupportedChannels);
status_t AudioStreamOut::setParameters(__unused struct audio_stream *stream, const char *kvpairs)
{
AudioParameter param = AudioParameter(String8(kvpairs));
String8 key = String8(AudioParameter::keyRouting);
int tmpInt;
if (param.getInt(key, tmpInt) == NO_ERROR) {
// The audio HAL handles routing to physical devices entirely
// internally and mostly ignores what audio flinger tells it to do. JiC
// there is something (now or in the future) in audio flinger which
// cares about the routing value in a call to getParameters, we hang on
// to the last routing value set by audio flinger so we can at least be
// consistent when we lie to the upper levels about doing what they told
// us to do.
mAudioFlingerTgtDevices = static_cast<uint32_t>(tmpInt);
}
return NO_ERROR;
}
char* AudioStreamOut::getParameters(const char* k)
{
AudioParameter param = AudioParameter(String8(k));
String8 stringValue;
int intValue;
if (param.get(keyRouting, stringValue) == NO_ERROR) {
param.addInt(keyRouting, (int)mAudioFlingerTgtDevices);
}
HDMIAudioCaps& hdmiCaps = mOwnerHAL.getHDMIAudioCaps();
if (param.get(keySupFormats, stringValue) == NO_ERROR) {
if (mIsMCOutput) {
hdmiCaps.getFmtsForAF(stringValue);
param.add(keySupFormats, stringValue);
} else {
param.add(keySupFormats, String8("AUDIO_FORMAT_PCM_16_BIT|AUDIO_FORMAT_PCM_8_24_BIT"));
}
}
audio_format_t format = AUDIO_FORMAT_INVALID;
if (param.getInt(keyFormat, intValue) == NO_ERROR) {
format = (audio_format_t)intValue;
}
if (param.get(keySupSampleRates, stringValue) == NO_ERROR) {
if (mIsMCOutput) {
hdmiCaps.getRatesForAF(stringValue, format);
param.add(keySupSampleRates, stringValue);
} else {
param.add(keySupSampleRates, String8("48000"));
}
}
if (param.get(keySupChannels, stringValue) == NO_ERROR) {
if (mIsMCOutput) {
hdmiCaps.getChannelMasksForAF(stringValue, format);
param.add(keySupChannels, stringValue);
} else {
param.add(keySupChannels, String8("AUDIO_CHANNEL_OUT_STEREO"));
}
}
return strdup(param.toString().string());
}
uint32_t AudioStreamOut::outputSampleRate() const
{
return mInputSampleRate;
}
uint32_t AudioStreamOut::latency() const {
uint32_t uSecLatency = mInputNominalLatencyUSec;
uint32_t vcompDelay = mOwnerHAL.getVideoDelayCompUsec();
if (uSecLatency < vcompDelay)
return 0;
return ((uSecLatency - vcompDelay) / 1000);
}
// Used to implement get_presentation_position() for Audio HAL.
// According to the prototype in audio.h, the frame count should not get
// reset on standby().
status_t AudioStreamOut::getPresentationPosition(uint64_t *frames,
struct timespec *timestamp)
{
status_t result = -ENODEV;
// If we cannot get a lock then try to return a cached position and timestamp.
// It is better to return an old timestamp then to wait for a fresh one.
if (mRoutingLock.tryLock() != OK) {
// We failed to get the lock. It is probably held by a blocked write().
if (mLastPresentationValid) {
// Use cached position.
// Use mutex because this cluster of variables may be getting
// updated by the write thread.
Mutex::Autolock _l(mPresentationLock);
*frames = mLastPresentationPosition;
*timestamp = mLastPresentationTime;
result = NO_ERROR;
}
return result;
}
// Lock succeeded so it is safe to call this.
result = getPresentationPosition_l(frames, timestamp);
mRoutingLock.unlock();
return result;
}
// Used to implement get_presentation_position() for Audio HAL.
// According to the prototype in audio.h, the frame count should not get
// reset on standby().
// mRoutingLock should be locked before calling this method.
status_t AudioStreamOut::getPresentationPosition_l(uint64_t *frames,
struct timespec *timestamp)
{
status_t result = -ENODEV;
// The presentation timestamp should be the same for all devices.
// Also Molly only has one output device at the moment.
// So just use the first one in the list.
if (!mPhysOutputs.isEmpty()) {
unsigned int avail = 0;
sp<AudioOutput> audioOutput = mPhysOutputs.itemAt(0);
if (audioOutput->getHardwareTimestamp(&avail, timestamp) == OK) {
int64_t framesInDriverBuffer = (int64_t)audioOutput->getKernelBufferSize() - (int64_t)avail;
if (framesInDriverBuffer >= 0) {
// FIXME av sync fudge factor
// Use a fudge factor to account for hidden buffering in the
// HDMI output path. This is a hack until we can determine the
// actual buffer sizes.
// Increasing kFudgeMSec will move the audio earlier in
// relation to the video.
const int kFudgeMSec = 50;
int fudgeFrames = kFudgeMSec * sampleRate() / 1000;
int64_t pendingFrames = framesInDriverBuffer + fudgeFrames;
int64_t signedFrames = mFramesPresented - pendingFrames;
if (signedFrames < 0) {
ALOGV("getPresentationPosition: playing silent preroll"
", mFramesPresented = %" PRIu64 ", pendingFrames = %" PRIi64,
mFramesPresented, pendingFrames);
} else {
#if HAL_PRINT_TIMESTAMP_CSV
// Print comma separated values for spreadsheet analysis.
uint64_t nanos = (((uint64_t)timestamp->tv_sec) * 1000000000L)
+ timestamp->tv_nsec;
ALOGI("getPresentationPosition, %" PRIu64 ", %4u, %" PRIi64 ", %" PRIu64,
mFramesPresented, avail, signedFrames, nanos);
#endif
uint64_t unsignedFrames = (uint64_t) signedFrames;
{
Mutex::Autolock _l(mPresentationLock);
// Check for retrograde timestamps.
if (unsignedFrames < mLastPresentationPosition) {
ALOGW("getPresentationPosition: RETROGRADE timestamp, diff = %" PRId64,
(int64_t)(unsignedFrames - mLastPresentationPosition));
if (mLastPresentationValid) {
// Use previous presentation position and time.
*timestamp = mLastPresentationTime;
*frames = mLastPresentationPosition;
result = NO_ERROR;
}
// else return error
} else {
*frames = unsignedFrames;
// Save cached data that we can use when the HAL is locked.
mLastPresentationPosition = unsignedFrames;
mLastPresentationTime = *timestamp;
result = NO_ERROR;
}
}
}
} else {
ALOGE("getPresentationPosition: avail too large = %u", avail);
}
mReportedAvailFail = false;
} else {
ALOGW_IF(!mReportedAvailFail,
"getPresentationPosition: getHardwareTimestamp returned non-zero");
mReportedAvailFail = true;
}
} else {
ALOGVV("getPresentationPosition: no physical outputs! This HAL is inactive!");
}
mLastPresentationValid = result == NO_ERROR;
return result;
}
status_t AudioStreamOut::getRenderPosition(__unused uint32_t *dspFrames)
{
if (dspFrames == NULL) {
return -EINVAL;
}
*dspFrames = (uint32_t) mRenderPosition;
return NO_ERROR;
}
void AudioStreamOut::updateTargetOutputs()
{
Mutex::Autolock _l(mRoutingLock);
AudioOutputList::iterator I;
uint32_t cur_outputs = 0;
for (I = mPhysOutputs.begin(); I != mPhysOutputs.end(); ++I)
cur_outputs |= (*I)->devMask();
if (cur_outputs == mTgtDevices)
return;
uint32_t outputsToObtain = mTgtDevices & ~cur_outputs;
uint32_t outputsToRelease = cur_outputs & ~mTgtDevices;
// Start by releasing any outputs we should no longer have back to the HAL.
if (outputsToRelease) {
I = mPhysOutputs.begin();
while (I != mPhysOutputs.end()) {
if (!(outputsToRelease & (*I)->devMask())) {
++I;
continue;
}
outputsToRelease &= ~((*I)->devMask());
mOwnerHAL.releaseOutput(*this, *I);
I = mPhysOutputs.erase(I);
}
}
if (outputsToRelease) {
ALOGW("Bookkeeping error! Still have outputs to release (%08x), but"
" none of them appear to be in the mPhysOutputs list!",
outputsToRelease);
}
// Now attempt to obtain any outputs we should be using, but are not
// currently.
if (outputsToObtain) {
uint32_t mask;
// Buffer configuration may need updating now that we have decoded
// the start of a stream. For example, EAC3, needs 4X sampleRate.
updateInputNums();
for (mask = 0x1; outputsToObtain; mask <<= 1) {
if (!(mask & outputsToObtain))
continue;
sp<AudioOutput> newOutput;
status_t res;
res = mOwnerHAL.obtainOutput(*this, mask, &newOutput);
outputsToObtain &= ~mask;
if (OK != res) {
// If we get an error back from obtain output, it means that
// something went really wrong at a lower level (probably failed
// to open the driver). We should not try to obtain this output
// again, at least until the next routing change.
ALOGW("Failed to obtain output %08x for %s audio stream out."
" (res %d)", mask, getName(), res);
mTgtDevices &= ~mask;
continue;
}
if (newOutput != NULL) {
// If we actually got an output, go ahead and add it to our list
// of physical outputs. The rest of the system will handle
// starting it up. If we didn't get an output, but also got no
// error code, it just means that the output is currently busy
// and should become available soon.
ALOGI("updateTargetOutputs: adding output back to mPhysOutputs");
mPhysOutputs.push_back(newOutput);
}
}
}
}
void AudioStreamOut::adjustOutputs(int64_t maxTime)
{
int64_t a_zero_original = mLocalTimeToFrames.a_zero;
int64_t b_zero_original = mLocalTimeToFrames.b_zero;
AudioOutputList::iterator I;
// Check to see if any outputs are active and see what their buffer levels
// are.
for (I = mPhysOutputs.begin(); I != mPhysOutputs.end(); ++I) {
if ((*I)->getState() == AudioOutput::DMA_START) {
int64_t lastWriteTS = (*I)->getLastNextWriteTS();
int64_t padAmt;
mLocalTimeToFrames.a_zero = lastWriteTS;
mLocalTimeToFrames.b_zero = 0;
if (mLocalTimeToFrames.doForwardTransform(maxTime,
&padAmt)) {
(*I)->adjustDelay(((int32_t)padAmt));
}
}
}
// Restore original offset so that the sleep time calculation for
// throttling is not broken in finishedWriteOp().
mLocalTimeToFrames.a_zero = a_zero_original;
mLocalTimeToFrames.b_zero = b_zero_original;
}
ssize_t AudioStreamOut::write(const void* buffer, size_t bytes)
{
uint8_t *data = (uint8_t *)buffer;
ALOGVV("AudioStreamOut::write_l(%u) 0x%02X, 0x%02X, 0x%02X, 0x%02X,"
" 0x%02X, 0x%02X, 0x%02X, 0x%02X,"
" 0x%02X, 0x%02X, 0x%02X, 0x%02X,"
" 0x%02X, 0x%02X, 0x%02X, 0x%02X",
bytes, data[0], data[1], data[2], data[3],
data[4], data[5], data[6], data[7],
data[8], data[9], data[10], data[11],
data[12], data[13], data[14], data[15]
);
//
// Note that only calls to write change the contents of the mPhysOutputs
// collection (during the call to updateTargetOutputs). updateTargetOutputs
// will hold the routing lock during the operation, as should any reader of
// mPhysOutputs, unless the reader is a call to write or
// getNextWriteTimestamp (we know that it is safe for write and gnwt to read
// the collection because the only collection mutator is the same thread
// which calls write and gnwt).
// If the stream is in standby, then the first write should bring it out
// of standby
if (mInStandby) {
mOwnerHAL.standbyStatusUpdate(false, mIsMCOutput);
mInStandby = false;
}
updateTargetOutputs(); // locks mRoutingLock
// If any of our outputs is in the PRIMED state when ::write is called, it
// means one of two things. First, it could be that the DMA output really
// has not started yet. This is odd, but certainly not impossible. The
// other possibility is that AudioFlinger is in its silence-pushing mode and
// is not calling getNextWriteTimestamp. After an output is primed, its in
// GNWTS where the amount of padding to compensate for different DMA start
// times is taken into account. Go ahead and force a call to GNWTS, just to
// be certain that we have checked recently and are not stuck in silence
// fill mode. Failure to do this will cause the AudioOutput state machine
// to eventually give up on DMA starting and reset the output over and over
// again (spamming the log and producing general confusion).
//
// While we are in the process of checking our various output states, check
// to see if any outputs have made it to the ACTIVE state. Pass this
// information along to the call to processOneChunk. If any of our outputs
// are waiting to be primed while other outputs have made it to steady
// state, we need to change our priming behavior slightly. Instead of
// filling an output's buffer completely, we want to fill it to slightly
// less than full and let the adjustDelay mechanism take care of the rest.
//
// Failure to do this during steady state operation will almost certainly
// lead to the new output being over-filled relative to the other outputs
// causing it to be slightly out of sync.
AudioOutputList::iterator I;
bool checkDMAStart = false;
bool hasActiveOutputs = false;
{
Mutex::Autolock _l(mRoutingLock);
for (I = mPhysOutputs.begin(); I != mPhysOutputs.end(); ++I) {
if (AudioOutput::PRIMED == (*I)->getState())
checkDMAStart = true;
if ((*I)->getState() == AudioOutput::ACTIVE)
hasActiveOutputs = true;
}
}
if (checkDMAStart) {
int64_t junk;
getNextWriteTimestamp_internal(&junk);
}
// We always call processOneChunk on the outputs, as it is the
// tick for their state machines.
{
Mutex::Autolock _l(mRoutingLock);
for (I = mPhysOutputs.begin(); I != mPhysOutputs.end(); ++I) {
(*I)->processOneChunk((uint8_t *)buffer, bytes, hasActiveOutputs, mInputFormat);
}
// If we don't actually have any physical outputs to write to, just sleep
// for the proper amount of time in order to simulate the throttle that writing
// to the hardware would impose.
uint32_t framesWritten = bytes / mInputFrameSize;
finishedWriteOp(framesWritten, (0 == mPhysOutputs.size()));
}
// Load presentation position cache because we will normally be locked when it is called.
{
Mutex::Autolock _l(mRoutingLock);
uint64_t frames;
struct timespec timestamp;
getPresentationPosition_l(&frames, &timestamp);
}
return static_cast<ssize_t>(bytes);
}
status_t AudioStreamOut::getNextWriteTimestamp(int64_t *timestamp)
{
return getNextWriteTimestamp_internal(timestamp);
}
status_t AudioStreamOut::getNextWriteTimestamp_internal(
int64_t *timestamp)
{
int64_t max_time = LLONG_MIN;
bool max_time_valid = false;
bool need_adjust = false;
// Across all of our physical outputs, figure out the max time when
// a write operation will hit the speakers. Assume that if an
// output cannot answer the question, its because it has never
// started or because it has recently underflowed and needs to be
// restarted. If this is the case, we will need to prime the
// pipeline with a chunk's worth of data before proceeding.
// If any of the outputs indicate a discontinuity (meaning that the
// DMA start time was valid and is now invalid, or was and is valid
// but was different from before; almost certainly caused by a low
// level underfow), then just stop now. We will need to reset and
// re-prime all of the outputs in order to make certain that the
// lead-times on all of the outputs match.
AudioOutputList::iterator I;
bool discon = false;
// Find the largest next write timestamp. The goal is to make EVERY
// output have the same value, but we also need this to pass back
// up the layers.
for (I = mPhysOutputs.begin(); I != mPhysOutputs.end(); ++I) {
int64_t tmp;
if (OK == (*I)->getNextWriteTimestamp(&tmp, &discon)) {
if (!max_time_valid || (max_time < tmp)) {
max_time = tmp;
max_time_valid = true;
}
}
}
// Check the state of each output and determine if we need to align them.
// Make sure to do this after we have called each outputs'
// getNextWriteTimestamp as the transition from PRIMED to DMA_START happens
// there.
for (I = mPhysOutputs.begin(); I != mPhysOutputs.end(); ++I) {
if ((*I)->getState() == AudioOutput::DMA_START) {
need_adjust = true;
break;
}
}
// At this point, if we still have not found at least one output
// who knows when their data is going to hit the speakers, then we
// just can't answer the getNextWriteTimestamp question and we
// should give up.
if (!max_time_valid) {
return INVALID_OPERATION;
}
// Stuff silence into the non-aligned outputs so that the effective
// timestamp is the same for all the outputs.
if (need_adjust)
adjustOutputs(max_time);
// We are done. The time at which the next written audio should
// hit the speakers is just max_time plus the maximum amt of delay
// compensation in the system.
*timestamp = max_time;
return OK;
}
#define DUMP(a...) \
snprintf(buffer, SIZE, a); \
buffer[SIZE - 1] = 0; \
result.append(buffer);
#define B2STR(b) b ? "true" : "false"
status_t AudioStreamOut::dump(int fd)
{
const size_t SIZE = 256;
char buffer[SIZE];
String8 result;
DUMP("\n%s AudioStreamOut::dump\n", getName());
DUMP("\tsample rate : %d\n", sampleRate());
DUMP("\tbuffer size : %d\n", bufferSize());
DUMP("\tchannel mask : 0x%04x\n", chanMask());
DUMP("\tformat : %d\n", format());
DUMP("\tdevice mask : 0x%04x\n", mTgtDevices);
DUMP("\tIn standby : %s\n", mInStandby? "yes" : "no");
mRoutingLock.lock();
AudioOutputList outSnapshot(mPhysOutputs);
mRoutingLock.unlock();
AudioOutputList::iterator I;
for (I = outSnapshot.begin(); I != outSnapshot.end(); ++I)
(*I)->dump(result);
::write(fd, result.string(), result.size());
return NO_ERROR;
}
#undef B2STR
#undef DUMP
} // android

View file

@ -0,0 +1,148 @@
/*
**
** Copyright 2012, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
#ifndef ANDROID_AUDIO_STREAM_OUT_H
#define ANDROID_AUDIO_STREAM_OUT_H
#include <stdint.h>
#include <sys/types.h>
#include <common_time/local_clock.h>
#include <hardware/audio.h>
#include <media/AudioParameter.h>
#include "AudioOutput.h"
namespace android {
class AudioHardwareOutput;
class AudioStreamOut {
public:
AudioStreamOut(AudioHardwareOutput& owner, bool mcOut, bool isIec958NonAudio);
~AudioStreamOut();
uint32_t latency() const;
status_t getRenderPosition(uint32_t *dspFrames);
status_t getPresentationPosition(uint64_t *frames, struct timespec *timestamp);
status_t getNextWriteTimestamp(int64_t *timestamp);
status_t standby();
status_t pause();
status_t resume();
status_t flush();
status_t dump(int fd);
uint32_t sampleRate() const { return mInputSampleRate; }
uint32_t outputSampleRate() const;
size_t bufferSize() const { return mInputBufSize; }
uint32_t chanMask() const { return mInputChanMask; }
audio_format_t format() const { return mInputFormat; }
uint32_t framesPerChunk() const { return mInputChunkFrames; }
uint32_t nomChunksInFlight() const { return mInputNominalChunksInFlight; }
status_t set(audio_format_t *pFormat,
uint32_t *pChannels,
uint32_t *pRate);
void setTgtDevices(uint32_t tgtDevices);
status_t setParameters(struct audio_stream *stream,
const char *kvpairs);
char* getParameters(const char* keys);
const char* getName() const { return mIsMCOutput ? "Multi-channel"
: "Main"; }
ssize_t write(const void* buffer, size_t bytes);
bool isIec958NonAudio() const { return mIsIec958NonAudio; }
protected:
// Lock in this order to avoid deadlock.
// mRoutingLock
// mPresentationLock
// Track frame position for timestamps, etc.
uint64_t mRenderPosition; // in frames, increased by write
uint64_t mFramesPresented; // increased by write
// Cache of the last PresentationPosition.
// This cache is used in case of retrograde timestamps or if the mRoutingLock is held.
Mutex mPresentationLock; // protects these mLastPresentation* variables
uint64_t mLastPresentationPosition; // frames
struct timespec mLastPresentationTime;
bool mLastPresentationValid;
// Our HAL, used as the middle-man to collect and trade AudioOutputs.
AudioHardwareOutput& mOwnerHAL;
// Details about the format of the audio we have been configured to receive
// from audio flinger.
uint32_t mInputSampleRate;
uint32_t mInputChanMask;
audio_format_t mInputFormat;
uint32_t mInputNominalChunksInFlight;
// Handy values pre-computed from the audio configuration.
uint32_t mInputBufSize;
uint32_t mInputChanCount;
uint32_t mInputFrameSize;
uint32_t mInputChunkFrames;
uint32_t mInputNominalLatencyUSec;
LinearTransform mLocalTimeToFrames;
// Bookkeeping used to throttle audio flinger when this audio stream has no
// actual physical outputs.
LocalClock mLocalClock;
bool mThrottleValid;
int64_t mWriteStartLT;
int64_t mFramesWritten; // application rate frames, not device rate frames
LinearTransform mUSecToLocalTime;
// State to track which actual outputs are assigned to this output stream.
Mutex mRoutingLock; // This protects mPhysOutputs and mTgtDevices
AudioOutputList mPhysOutputs;
uint32_t mTgtDevices;
bool mTgtDevicesDirty;
uint32_t mAudioFlingerTgtDevices;
// Flag to track if this StreamOut was created to sink a direct output
// multichannel stream.
bool mIsMCOutput;
// Is the stream on standby?
bool mInStandby;
// Is the stream compressed audio in SPDIF data bursts?
const bool mIsIec958NonAudio;
// reduce log spew
bool mReportedAvailFail;
status_t standbyHardware();
void releaseAllOutputs(); // locks mRoutingLock
void updateTargetOutputs(); // locks mRoutingLock
void updateInputNums();
void finishedWriteOp(size_t framesWritten, bool needThrottle);
void resetThrottle() { mThrottleValid = false; }
status_t getNextWriteTimestamp_internal(int64_t *timestamp);
void adjustOutputs(int64_t maxTime);
ssize_t writeInternal(const void* buffer, size_t bytes);
// mRoutingLock should be held before calling this.
status_t getPresentationPosition_l(uint64_t *frames, struct timespec *timestamp);
};
} // android
#endif // ANDROID_AUDIO_STREAM_OUT_H

View file

@ -0,0 +1,135 @@
/*
**
** Copyright 2014, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
#define LOG_TAG "AudioHAL_HDMIAudioOutput"
#include <utils/Log.h>
#include <stdint.h>
#include <sound/asound.h> // bionic
#include "AudioHardwareOutput.h"
#include "AudioStreamOut.h"
#include "HDMIAudioOutput.h"
namespace android {
extern AudioHardwareOutput gAudioHardwareOutput;
HDMIAudioOutput::HDMIAudioOutput()
: AudioOutput(kHDMI_ALSADeviceName, PCM_FORMAT_S24_LE)
{
}
HDMIAudioOutput::~HDMIAudioOutput()
{
}
status_t HDMIAudioOutput::setupForStream(const AudioStreamOut& stream)
{
mFramesPerChunk = stream.framesPerChunk();
mFramesPerSec = stream.outputSampleRate();
mBufferChunks = stream.nomChunksInFlight();
mChannelCnt = audio_channel_count_from_out_mask(stream.chanMask());
ALOGI("setupForStream format %08x, rate = %u", stream.format(), mFramesPerSec);
if (!gAudioHardwareOutput.getHDMIAudioCaps().supportsFormat(
stream.format(),
stream.sampleRate(),
mChannelCnt,
stream.isIec958NonAudio())) {
ALOGE("HDMI Sink does not support format = 0x%0X, srate = %d, #channels = 0%d",
stream.format(), mFramesPerSec, mChannelCnt);
return BAD_VALUE;
}
setupInternal();
setChannelStatusToCompressed(stream.isIec958NonAudio());
return initCheck();
}
void HDMIAudioOutput::applyPendingVolParams()
{
}
#define IEC958_AES0_NONAUDIO (1<<1) /* 0 = audio, 1 = non-audio */
void HDMIAudioOutput::setChannelStatusToCompressed(bool compressed)
{
struct snd_aes_iec958 iec958;
struct mixer* mixer;
int err;
const size_t count = 1;
ALOGI("setChannelStatusToCompressed %d", compressed);
mixer = mixer_open(mALSACardID);
if (mixer == NULL) {
ALOGE("Couldn't open mixer on alsa id %d", mALSACardID);
return;
}
const char *ctlName = "IEC958 Playback Default";
struct mixer_ctl *ctl = mixer_get_ctl_by_name(mixer, ctlName);
if (ctl == NULL) {
ALOGE("Couldn't get mixer ctl %s", ctlName);
goto finish;
}
// Set count to 1 so we get one complete iec958 structure.
err = mixer_ctl_get_array(ctl, &iec958, count);
if (err < 0) {
ALOGE("Channel Status bit get has failed\n");
goto finish;
}
if (compressed) {
iec958.status[0] |= IEC958_AES0_NONAUDIO;
} else {
iec958.status[0] &= ~IEC958_AES0_NONAUDIO;
}
err = mixer_ctl_set_array(ctl, &iec958, count);
if (err < 0) {
ALOGE("Channel Status bit set has failed\n");
}
finish:
mixer_close(mixer);
}
void HDMIAudioOutput::dump(String8& result)
{
const size_t SIZE = 256;
char buffer[SIZE];
snprintf(buffer, SIZE,
"\t%s Audio Output\n"
"\t\tSample Rate : %d\n"
"\t\tChannel Count : %d\n"
"\t\tState : %d\n",
getOutputName(),
mFramesPerSec,
mChannelCnt,
mState);
result.append(buffer);
}
} // namespace android

View file

@ -0,0 +1,45 @@
/*
**
** Copyright 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_HDMI_AUDIO_OUTPUT_H
#define ANDROID_HDMI_AUDIO_OUTPUT_H
#include <hardware/audio.h>
#include "AudioOutput.h"
namespace android {
class AudioStreamOut;
class HDMIAudioOutput : public AudioOutput {
public:
HDMIAudioOutput();
virtual ~HDMIAudioOutput();
virtual status_t setupForStream(const AudioStreamOut& stream);
virtual const char* getOutputName() { return "HDMI"; }
static uint32_t classDevMask() { return AUDIO_DEVICE_OUT_AUX_DIGITAL; }
virtual uint32_t devMask() const { return classDevMask(); }
virtual void dump(String8& result);
protected:
virtual void applyPendingVolParams();
void setChannelStatusToCompressed(bool compressed);
};
} // namespace android
#endif // ANDROID_HDMI_AUDIO_OUTPUT_H

View file

@ -0,0 +1,281 @@
/*
* 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.
*/
#define __STDC_LIMIT_MACROS
#include "LinearTransform.h"
#include <assert.h>
// disable sanitize as these functions may intentionally overflow (see comments below).
// the ifdef can be removed when host builds use clang.
#if defined(__clang__)
#define ATTRIBUTE_NO_SANITIZE_INTEGER __attribute__((no_sanitize("integer")))
#else
#define ATTRIBUTE_NO_SANITIZE_INTEGER
#endif
namespace android {
// sanitize failure with T = int32_t and x = 0x80000000
template<class T>
ATTRIBUTE_NO_SANITIZE_INTEGER
static inline T ABS(T x) { return (x < 0) ? -x : x; }
// Static math methods involving linear transformations
// remote sanitize failure on overflow case.
ATTRIBUTE_NO_SANITIZE_INTEGER
static bool scale_u64_to_u64(
uint64_t val,
uint32_t N,
uint32_t D,
uint64_t* res,
bool round_up_not_down) {
uint64_t tmp1, tmp2;
uint32_t r;
assert(res);
assert(D);
// Let U32(X) denote a uint32_t containing the upper 32 bits of a 64 bit
// integer X.
// Let L32(X) denote a uint32_t containing the lower 32 bits of a 64 bit
// integer X.
// Let X[A, B] with A <= B denote bits A through B of the integer X.
// Let (A | B) denote the concatination of two 32 bit ints, A and B.
// IOW X = (A | B) => U32(X) == A && L32(X) == B
//
// compute M = val * N (a 96 bit int)
// ---------------------------------
// tmp2 = U32(val) * N (a 64 bit int)
// tmp1 = L32(val) * N (a 64 bit int)
// which means
// M = val * N = (tmp2 << 32) + tmp1
tmp2 = (val >> 32) * N;
tmp1 = (val & UINT32_MAX) * N;
// compute M[32, 95]
// tmp2 = tmp2 + U32(tmp1)
// = (U32(val) * N) + U32(L32(val) * N)
// = M[32, 95]
tmp2 += tmp1 >> 32;
// if M[64, 95] >= D, then M/D has bits > 63 set and we have
// an overflow.
if ((tmp2 >> 32) >= D) {
*res = UINT64_MAX;
return false;
}
// Divide. Going in we know
// tmp2 = M[32, 95]
// U32(tmp2) < D
r = tmp2 % D;
tmp2 /= D;
// At this point
// tmp1 = L32(val) * N
// tmp2 = M[32, 95] / D
// = (M / D)[32, 95]
// r = M[32, 95] % D
// U32(tmp2) = 0
//
// compute tmp1 = (r | M[0, 31])
tmp1 = (tmp1 & UINT32_MAX) | ((uint64_t)r << 32);
// Divide again. Keep the remainder around in order to round properly.
r = tmp1 % D;
tmp1 /= D;
// At this point
// tmp2 = (M / D)[32, 95]
// tmp1 = (M / D)[ 0, 31]
// r = M % D
// U32(tmp1) = 0
// U32(tmp2) = 0
// Pack the result and deal with the round-up case (As well as the
// remote possiblility over overflow in such a case).
*res = (tmp2 << 32) | tmp1;
if (r && round_up_not_down) {
++(*res);
if (!(*res)) {
*res = UINT64_MAX;
return false;
}
}
return true;
}
// at least one known sanitize failure (see comment below)
ATTRIBUTE_NO_SANITIZE_INTEGER
static bool linear_transform_s64_to_s64(
int64_t val,
int64_t basis1,
int32_t N,
uint32_t D,
bool invert_frac,
int64_t basis2,
int64_t* out) {
uint64_t scaled, res;
uint64_t abs_val;
bool is_neg;
if (!out)
return false;
// Compute abs(val - basis_64). Keep track of whether or not this delta
// will be negative after the scale opertaion.
if (val < basis1) {
is_neg = true;
abs_val = basis1 - val;
} else {
is_neg = false;
abs_val = val - basis1;
}
if (N < 0)
is_neg = !is_neg;
if (!scale_u64_to_u64(abs_val,
invert_frac ? D : ABS(N),
invert_frac ? ABS(N) : D,
&scaled,
is_neg))
return false; // overflow/undeflow
// if scaled is >= 0x8000<etc>, then we are going to overflow or
// underflow unless ABS(basis2) is large enough to pull us back into the
// non-overflow/underflow region.
if (scaled & INT64_MIN) {
if (is_neg && (basis2 < 0))
return false; // certain underflow
if (!is_neg && (basis2 >= 0))
return false; // certain overflow
if (ABS(basis2) <= static_cast<int64_t>(scaled & INT64_MAX))
return false; // not enough
// Looks like we are OK
*out = (is_neg ? (-scaled) : scaled) + basis2;
} else {
// Scaled fits within signed bounds, so we just need to check for
// over/underflow for two signed integers. Basically, if both scaled
// and basis2 have the same sign bit, and the result has a different
// sign bit, then we have under/overflow. An easy way to compute this
// is
// (scaled_signbit XNOR basis_signbit) &&
// (scaled_signbit XOR res_signbit)
// ==
// (scaled_signbit XOR basis_signbit XOR 1) &&
// (scaled_signbit XOR res_signbit)
if (is_neg)
scaled = -scaled; // known sanitize failure
res = scaled + basis2;
if ((scaled ^ basis2 ^ INT64_MIN) & (scaled ^ res) & INT64_MIN)
return false;
*out = res;
}
return true;
}
bool LinearTransform::doForwardTransform(int64_t a_in, int64_t* b_out) const {
if (0 == a_to_b_denom)
return false;
return linear_transform_s64_to_s64(a_in,
a_zero,
a_to_b_numer,
a_to_b_denom,
false,
b_zero,
b_out);
}
bool LinearTransform::doReverseTransform(int64_t b_in, int64_t* a_out) const {
if (0 == a_to_b_numer)
return false;
return linear_transform_s64_to_s64(b_in,
b_zero,
a_to_b_numer,
a_to_b_denom,
true,
a_zero,
a_out);
}
template <class T> void LinearTransform::reduce(T* N, T* D) {
T a, b;
if (!N || !D || !(*D)) {
assert(false);
return;
}
a = *N;
b = *D;
if (a == 0) {
*D = 1;
return;
}
// This implements Euclid's method to find GCD.
if (a < b) {
T tmp = a;
a = b;
b = tmp;
}
while (1) {
// a is now the greater of the two.
const T remainder = a % b;
if (remainder == 0) {
*N /= b;
*D /= b;
return;
}
// by swapping remainder and b, we are guaranteeing that a is
// still the greater of the two upon entrance to the loop.
a = b;
b = remainder;
}
};
template void LinearTransform::reduce<uint64_t>(uint64_t* N, uint64_t* D);
template void LinearTransform::reduce<uint32_t>(uint32_t* N, uint32_t* D);
// sanitize failure if *N = 0x80000000
ATTRIBUTE_NO_SANITIZE_INTEGER
void LinearTransform::reduce(int32_t* N, uint32_t* D) {
if (N && D && *D) {
if (*N < 0) {
*N = -(*N);
reduce(reinterpret_cast<uint32_t*>(N), D);
*N = -(*N);
} else {
reduce(reinterpret_cast<uint32_t*>(N), D);
}
}
}
} // namespace android

View file

@ -0,0 +1,61 @@
/*
* 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.
*/
#pragma once
#include <stdint.h>
namespace android {
// LinearTransform defines a structure which hold the definition of a
// transformation from single dimensional coordinate system A into coordinate
// system B (and back again). Values in A and in B are 64 bit, the linear
// scale factor is expressed as a rational number using two 32 bit values.
//
// Specifically, let
// f(a) = b
// F(b) = f^-1(b) = a
// then
//
// f(a) = (((a - a_zero) * a_to_b_numer) / a_to_b_denom) + b_zero;
//
// and
//
// F(b) = (((b - b_zero) * a_to_b_denom) / a_to_b_numer) + a_zero;
//
struct LinearTransform {
int64_t a_zero;
int64_t b_zero;
int32_t a_to_b_numer;
uint32_t a_to_b_denom;
// Transform from A->B
// Returns true on success, or false in the case of a singularity or an
// overflow.
bool doForwardTransform(int64_t a_in, int64_t* b_out) const;
// Transform from B->A
// Returns true on success, or false in the case of a singularity or an
// overflow.
bool doReverseTransform(int64_t b_in, int64_t* a_out) const;
// Helpers which will reduce the fraction N/D using Euclid's method.
template <class T> static void reduce(T* N, T* D);
static void reduce(int32_t* N, uint32_t* D);
};
}

View file

@ -0,0 +1,579 @@
/*
**
** Copyright 2014, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
#define LOG_TAG "AudioHAL:alsa_utils"
#include "alsa_utils.h"
#ifndef ALSA_UTILS_PRINT_FORMATS
#define ALSA_UTILS_PRINT_FORMATS 1
#endif
int find_alsa_card_by_name(const char* name) {
int card_id = 0;
int ret = -1;
int fd;
do {
int fd;
int amt;
char tmp[256];
snprintf(tmp, sizeof(tmp), "/proc/asound/card%d/id", card_id);
tmp[sizeof(tmp) - 1] = 0;
fd = open(tmp, O_RDONLY);
if (fd < 0)
break;
amt = read(fd, tmp, sizeof(tmp) - 1);
if (amt > 0) {
// replace the '\n' at the end of the proc file with '\0'
tmp[amt - 1] = 0;
if (!strcmp(name, tmp))
ret = card_id;
}
close(fd);
card_id++;
} while (ret < 0);
ALOGI("%s: returning card %d for name %s", __func__, ret, name);
return ret;
}
#ifdef __cplusplus
#include <tinyalsa/asoundlib.h>
#include <utils/misc.h>
namespace android {
static const char *kCtrlNames[] = {
"Basic Audio Supported",
"Speaker Allocation",
"Audio Mode Count",
"Audio Mode To Query",
"Query Mode : Format",
"Query Mode : Max Ch Count",
"Query Mode : Sample Rate Mask",
"Query Mode : PCM Bits/Sample Mask",
"Query Mode : Max Compressed Bitrate"
};
static const size_t kCtrlCount = sizeof(kCtrlNames)/sizeof(*kCtrlNames);
static const size_t kBasicAudNdx = 0;
static const size_t kSpeakerAlloc = 1;
static const size_t kModeCntNdx = 2;
static const size_t kModeSelNdx = 3;
static const size_t kFmtNdx = 4;
static const size_t kMaxChCntNdx = 5;
static const size_t kSampRateNdx = 6;
static const size_t kBPSNdx = 7;
static const size_t kMaxCompBRNdx = 8;
HDMIAudioCaps::HDMIAudioCaps()
{
// Its unlikely we will need storage for more than 16 modes, but if we do,
// the vector will resize for us.
mModes.setCapacity(16);
reset();
}
bool HDMIAudioCaps::loadCaps(int ALSADeviceID) {
bool ret = false;
struct mixer* mixer = NULL;
struct mixer_ctl* ctrls[kCtrlCount] = {NULL};
int tmp, mode_cnt;
Mutex::Autolock _l(mLock);
ALOGE("%s: start", __func__);
reset_l();
// Open the mixer for the chosen ALSA device
if (NULL == (mixer = mixer_open(ALSADeviceID))) {
ALOGE("%s: mixer_open(%d) failed", __func__, ALSADeviceID);
goto bailout;
}
// Gather handles to all of the controls we will need in order to enumerate
// the audio capabilities of this HDMI link. No need to free/release these
// later, they are just pointers into the tinyalsa mixer structure itself.
for (size_t i = 0; i < kCtrlCount; ++i) {
ctrls[i] = mixer_get_ctl_by_name(mixer, kCtrlNames[i]);
if (NULL == ctrls[i]) {
ALOGE("%s: mixer_get_ctrl_by_name(%s) failed", __func__, kCtrlNames[i]);
goto bailout;
}
}
// Start by checking to see if this HDMI connection supports even basic
// audio. If it does not, there is no point in proceeding.
if ((tmp = mixer_ctl_get_value(ctrls[kBasicAudNdx], 0)) <= 0) {
ALOGI("%s: Basic audio not supported by attached device", __func__);
goto bailout;
}
// Looks like we support basic audio. Get a count of the available
// non-basic modes.
mBasicAudioSupported = true;
if ((mode_cnt = mixer_ctl_get_value(ctrls[kModeCntNdx], 0)) < 0)
goto bailout;
// Fetch the speaker allocation data block, if available.
if ((tmp = mixer_ctl_get_value(ctrls[kSpeakerAlloc], 0)) < 0)
goto bailout;
mSpeakerAlloc = static_cast<uint16_t>(tmp);
ALOGI("%s: Speaker Allocation Map for attached device is: 0x%hx", __func__, mSpeakerAlloc);
// If there are no non-basic modes available, then we are done. Be sure to
// flag this as a successful operation.
if (!mode_cnt) {
ret = true;
goto bailout;
}
// Now enumerate the non-basic modes. Any errors at this point in time
// should indicate that the HDMI cable was unplugged and we should just
// abort with an empty set of audio capabilities.
for (int i = 0; i < mode_cnt; ++i) {
Mode m;
// Pick the mode we want to fetch info for.
if (mixer_ctl_set_value(ctrls[kModeSelNdx], 0, i) < 0)
goto bailout;
// Now fetch the common fields.
if ((tmp = mixer_ctl_get_value(ctrls[kFmtNdx], 0)) < 0)
goto bailout;
m.fmt = static_cast<AudFormat>(tmp);
ALOGI("Got mode %d from ALSA driver.", m.fmt);
if ((tmp = mixer_ctl_get_value(ctrls[kMaxChCntNdx], 0)) < 0)
goto bailout;
m.max_ch = static_cast<uint32_t>(tmp);
if ((tmp = mixer_ctl_get_value(ctrls[kSampRateNdx], 0)) < 0)
goto bailout;
m.sr_bitmask = static_cast<uint32_t>(tmp);
// Now for the mode dependent fields. Only LPCM has the bits-per-sample
// mask. Only AC3 through ATRAC have the compressed bitrate field.
m.bps_bitmask = 0;
m.comp_bitrate = 0;
if (m.fmt == kFmtLPCM) {
if ((tmp = mixer_ctl_get_value(ctrls[kBPSNdx], 0)) < 0)
goto bailout;
m.bps_bitmask = static_cast<uint32_t>(tmp);
} else if ((m.fmt >= kFmtAC3) && (m.fmt <= kFmtATRAC)) { // FIXME ATRAC is not last format!?
// FIXME SHould we extend the range up to kFmtDTSHD or kFmtMPGSUR?
if ((tmp = mixer_ctl_get_value(ctrls[kMaxCompBRNdx], 0)) < 0)
goto bailout;
m.comp_bitrate = static_cast<uint32_t>(tmp);
}
// Finally, sanity check the info. If it passes, add it to the vector
// of available modes.
if (sanityCheckMode(m)) {
ALOGI("Passed sanity check for mode %d from ALSA driver.", m.fmt);
mModes.add(m);
}
}
// Looks like we managed to enumerate all of the modes before someone
// unplugged the HDMI cable. Signal success and get out.
ret = true;
bailout:
if (NULL != mixer)
mixer_close(mixer);
if (!ret)
reset_l();
return ret;
}
void HDMIAudioCaps::reset() {
Mutex::Autolock _l(mLock);
reset_l();
}
void HDMIAudioCaps::reset_l() {
mBasicAudioSupported = false;
mSpeakerAlloc = 0;
mModes.clear();
}
void HDMIAudioCaps::getFmtsForAF(String8& fmts) {
Mutex::Autolock _l(mLock);
fmts.clear();
// If the sink does not support basic audio, then it supports no audio.
if (!mBasicAudioSupported) {
ALOGI("ALSAFORMATS: basic audio not supported");
return;
}
// These names must match formats in android.media.AudioFormat
fmts.append("AUDIO_FORMAT_PCM_16_BIT|AUDIO_FORMAT_PCM_8_24_BIT");
// TODO: when we can start to expect 20 and 24 bit audio modes coming from
// AF, we need to implement support to enumerate those modes.
for (size_t i = 0; i < mModes.size(); ++i) {
switch (mModes[i].fmt) {
case kFmtAC3:
fmts.append("|AUDIO_FORMAT_AC3");
break;
case kFmtEAC3:
fmts.append("|AUDIO_FORMAT_E_AC3");
break;
case kFmtDTS:
fmts.append("|AUDIO_FORMAT_DTS");
break;
case kFmtDTSHD:
fmts.append("|AUDIO_FORMAT_DTS_HD");
break;
default:
break;
}
}
// HDMI supports IEC61937 S/PDIF audio wrapper.
fmts.append("|AUDIO_FORMAT_IEC61937");
#if ALSA_UTILS_PRINT_FORMATS
ALOGI("ALSAFORMATS: formats = %s", fmts.string());
for (size_t i = 0; i < mModes.size(); ++i) {
ALOGI("ALSAFORMATS: ------- fmt[%d] = 0x%08X = %s",
i, mModes[i].fmt, fmtToString(mModes[i].fmt));
ALOGI("ALSAFORMATS: comp_bitrate[%d] = 0x%08X = %d",
i, mModes[i].comp_bitrate, mModes[i].comp_bitrate);
ALOGI("ALSAFORMATS: max_ch[%d] = 0x%08X = %d",
i, mModes[i].max_ch, mModes[i].max_ch);
ALOGI("ALSAFORMATS: bps_bitmask[%d] = 0x%08X", i, mModes[i].bps_bitmask);
uint32_t bpsm = mModes[i].bps_bitmask;
while(bpsm) {
uint32_t bpsm_next = bpsm & (bpsm - 1);
uint32_t bpsm_single = bpsm ^ bpsm_next;
if (bpsm_single) {
ALOGI("ALSAFORMATS: bits = %d", bpsMaskToBPS(bpsm_single));
}
bpsm = bpsm_next;
}
ALOGI("ALSAFORMATS: sr_bitmask[%d] = 0x%08X", i, mModes[i].sr_bitmask);
uint32_t srs = mModes[i].sr_bitmask;
while(srs) {
uint32_t srs_next = srs & (srs - 1);
uint32_t srs_single = srs ^ srs_next;
if (srs_single) {
ALOGI("ALSAFORMATS: srate = %d", srMaskToSR(srs_single));
}
srs = srs_next;
}
}
#endif /* ALSA_UTILS_PRINT_FORMATS */
}
/* static */
HDMIAudioCaps::AudFormat HDMIAudioCaps::alsaFormatFromAndroidFormat(audio_format_t format)
{
AudFormat alsaFormat = kFmtInvalid;
switch (audio_get_main_format(format)) {
case AUDIO_FORMAT_PCM: alsaFormat = kFmtLPCM; break;
case AUDIO_FORMAT_AC3: alsaFormat = kFmtAC3; break;
case AUDIO_FORMAT_E_AC3: alsaFormat = kFmtAC3; break; // FIXME should this be kFmtEAC3?
case AUDIO_FORMAT_DTS: alsaFormat = kFmtDTS; break;
case AUDIO_FORMAT_DTS_HD: alsaFormat = kFmtDTSHD; break;
case AUDIO_FORMAT_IEC61937: alsaFormat = kFmtLPCM; break;
default:
ALOGE("supportsFormat() says format %#x not supported", format);
break;
}
return alsaFormat;
}
const HDMIAudioCaps::Mode *HDMIAudioCaps::getModeForFormat(HDMIAudioCaps::AudFormat format)
{
for (size_t i = 0; i < mModes.size(); ++i) {
if (mModes[i].fmt == format) {
return &mModes[i];
}
}
return nullptr;
}
void HDMIAudioCaps::getRatesForAF(String8& rates, audio_format_t format) {
Mutex::Autolock _l(mLock);
rates.clear();
// If the sink does not support basic audio, then it supports no audio.
if (!mBasicAudioSupported)
return;
uint32_t tmp = 0;
// No format provided: returns rates for format with max channels
if (format == AUDIO_FORMAT_INVALID) {
ssize_t ndx = getMaxChModeNdx_l();
if (ndx >= 0)
tmp = mModes[ndx].sr_bitmask;
} else {
AudFormat alsaFormat = alsaFormatFromAndroidFormat(format);
if (alsaFormat == kFmtInvalid) {
return;
}
const Mode *mode = getModeForFormat(alsaFormat);
if (mode == nullptr) {
return;
}
tmp = mode->sr_bitmask;
}
bool first = true;
for (uint32_t i = 1; tmp; i <<= 1) {
if (i & tmp) {
rates.appendFormat(first ? "%d" : "|%d", srMaskToSR(i));
first = false;
tmp &= ~i;
}
}
}
void HDMIAudioCaps::getChannelMasksForAF(String8& masks, audio_format_t format) {
Mutex::Autolock _l(mLock);
masks.clear();
const Mode *mode = nullptr;
// If the sink does not support basic audio, then it supports no audio.
if (!mBasicAudioSupported)
return;
if (format == AUDIO_FORMAT_INVALID) {
// To keep things simple, only report mode information for the mode
// which supports the maximum number of channels.
ssize_t ndx = getMaxChModeNdx_l();
if (ndx < 0)
return;
mode = &mModes[ndx];
} else {
AudFormat alsaFormat = alsaFormatFromAndroidFormat(format);
if (alsaFormat == kFmtInvalid) {
return;
}
mode = getModeForFormat(alsaFormat);
if (mode == nullptr) {
return;
}
}
if (mode != nullptr) {
// allow mono for non-pcm formats, e.g. AC3
if (mode->max_ch >= 1 && mode->fmt != kFmtLPCM) {
masks.append("AUDIO_CHANNEL_OUT_MONO");
}
if (mode->max_ch >= 2) {
if (masks.length()) masks.append("|");
masks.append("AUDIO_CHANNEL_OUT_STEREO");
}
if (mode->max_ch >= 4) {
if (masks.length()) masks.append("|");
masks.append("AUDIO_CHANNEL_OUT_QUAD");
}
if (mode->max_ch >= 6) {
if (masks.length()) masks.append("|");
masks.append("AUDIO_CHANNEL_OUT_5POINT1");
}
if (mode->max_ch >= 8) {
if (masks.length()) masks.append("|");
masks.append("AUDIO_CHANNEL_OUT_7POINT1");
}
}
}
ssize_t HDMIAudioCaps::getMaxChModeNdx_l() {
ssize_t max_ch_ndx = -1;
uint32_t max_ch = 0;
for (size_t i = 0; i < mModes.size(); ++i) {
if (max_ch < mModes[i].max_ch) {
max_ch = mModes[i].max_ch;
max_ch_ndx = i;
}
}
return max_ch_ndx;
}
bool HDMIAudioCaps::supportsFormat(audio_format_t format,
uint32_t sampleRate,
uint32_t channelCount,
bool isIec958NonAudio) {
Mutex::Autolock _l(mLock);
ALOGV("supportsFormat() format = 0x%08X, sampleRate = %u, channels = 0x%08X, iec958 = %d",
format, sampleRate, channelCount, isIec958NonAudio ? 1 : 0);
// If the sink does not support basic audio, then it supports no audio.
if (!mBasicAudioSupported)
return false;
AudFormat alsaFormat = alsaFormatFromAndroidFormat(format);
if (alsaFormat == kFmtInvalid)
return false;
isIec958NonAudio |= (format == AUDIO_FORMAT_IEC61937);
// EAC3 uses a PCM sample rate of 4X the base rate.
// We try to detect that situation and allow 4X rate even if the
// EDID does not report that it is supported.
// This rate was chosen because it is between the region of typical PCM rates
// and the extreme rates used for IEC61973.
// It is > 96000 and < 4*32000.
const uint32_t maxReasonableRate = 100000; // FIXME review for N
if (isIec958NonAudio && (alsaFormat == kFmtLPCM) && (sampleRate > maxReasonableRate)) {
ALOGI("supportsFormat() dividing sample %u by 4 to test support for EAC3 over HDMI",
sampleRate);
sampleRate = sampleRate / 4;
}
SRMask srMask;
switch (sampleRate) {
case 32000: srMask = kSR_32000; break;
case 44100: srMask = kSR_44100; break;
case 48000: srMask = kSR_48000; break;
case 88200: srMask = kSR_88200; break;
case 96000: srMask = kSR_96000; break;
case 176400: srMask = kSR_176400; break;
case 192000: srMask = kSR_192000; break;
default: return false;
}
// if PCM then determine actual bits per sample.
if (alsaFormat == kFmtLPCM) {
BPSMask bpsMask;
switch (format) {
// FIXME: (legacy code). We match on 16 bits, but on Fugu we hard code to use
// PCM_FORMAT_S24_LE.
case AUDIO_FORMAT_PCM_16_BIT: // fall through
case AUDIO_FORMAT_PCM_8_24_BIT:
case AUDIO_FORMAT_IEC61937:
bpsMask = kBPS_16bit;
break;
default:
return false;
}
// Is the caller requesting basic audio? If so, we should be good to go.
// Otherwise, we need to check the mode table.
if ((2 == channelCount) && (sampleRate <= 48000))
return true;
// Check the modes in the table to see if there is one which
// supports the caller's format.
for (size_t i = 0; i < mModes.size(); ++i) {
const Mode& m = mModes[i];
if ((m.fmt == kFmtLPCM) &&
(m.max_ch >= channelCount) &&
(m.sr_bitmask & srMask) &&
(m.bps_bitmask & bpsMask))
return true;
}
} else {
// Check the modes in the table to see if there is one which
// supports the caller's format.
for (size_t i = 0; i < mModes.size(); ++i) {
const Mode& m = mModes[i];
// ignore bps_bitmask
if ((m.fmt == alsaFormat) &&
(m.max_ch >= channelCount) &&
(m.sr_bitmask & srMask))
return true;
}
}
// Looks like no compatible modes were found.
return false;
}
bool HDMIAudioCaps::sanityCheckMode(const Mode& m) {
if ((m.fmt < kFmtLPCM) || (m.fmt > kFmtMPGSUR))
return false;
if (m.max_ch > 8)
return false;
if (m.sr_bitmask & ~(kSR_32000 | kSR_44100 | kSR_48000 | kSR_88200 |
kSR_96000 | kSR_176400 | kSR_192000))
return false;
if (m.bps_bitmask & ~(kBPS_16bit | kBPS_20bit | kBPS_24bit))
return false;
return true;
}
const char* HDMIAudioCaps::fmtToString(AudFormat fmt) {
static const char* fmts[] = {
"invalid", "LPCM", "AC-3", "MPEG-1", "MPEG-1 Layer 3",
"MPEG-2", "AAC-LC", "DTS", "ATRAC", "DSD", "E-AC3",
"DTS-HD", "MLP", "DST", "WMA Pro", "Extended" };
if (fmt >= NELEM(fmts))
return "invalid";
return fmts[fmt];
}
uint32_t HDMIAudioCaps::srMaskToSR(uint32_t mask) {
switch (mask) {
case kSR_32000: return 32000;
case kSR_44100: return 44100;
case kSR_48000: return 48000;
case kSR_88200: return 88200;
case kSR_96000: return 96000;
case kSR_176400: return 176400;
case kSR_192000: return 192000;
default: return 0;
}
}
uint32_t HDMIAudioCaps::bpsMaskToBPS(uint32_t mask) {
switch (mask) {
case kBPS_16bit: return 16;
case kBPS_20bit: return 20;
case kBPS_24bit: return 24;
default: return 0;
}
}
const char* HDMIAudioCaps::saMaskToString(uint32_t mask) {
switch (mask) {
case kSA_FLFR: return "Front Left/Right";
case kSA_LFE: return "LFE";
case kSA_FC: return "Front Center";
case kSA_RLRR: return "Rear Left/Right";
case kSA_RC: return "Rear Center";
case kSA_FLCFRC: return "Front Left/Right Center";
case kSA_RLCRRC: return "Rear Left/Right Center";
case kSA_FLWFRW: return "Front Left/Right Wide";
case kSA_FLHFRH: return "Front Left/Right High";
case kSA_TC: return "Top Center (overhead)";
case kSA_FCH: return "Front Center High";
default: return "unknown";
}
}
} // namespace android
#endif // __cplusplus

View file

@ -0,0 +1,138 @@
/*
**
** Copyright 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_ALSA_UTILS_H
#define ANDROID_ALSA_UTILS_H
#include <fcntl.h>
#include <stdint.h>
#include <hardware/audio.h>
#define kHDMI_ALSADeviceName "IntelHDMI"
#ifdef __cplusplus
extern "C"
#endif
int find_alsa_card_by_name(const char* name);
#ifdef __cplusplus
#include <utils/Vector.h>
#include <utils/Mutex.h>
#include <utils/String8.h>
namespace android {
class HDMIAudioCaps {
public:
enum AudFormat {
kFmtInvalid = 0,
kFmtLPCM,
kFmtAC3,
kFmtMP1,
kFmtMP1L3,
kFmtMP2,
kFmtAACLC,
kFmtDTS,
kFmtATRAC,
kFmtDSD,
kFmtEAC3,
kFmtDTSHD,
kFmtMLP,
kFmtDST,
kFmtWMAPRO,
kFmtRefCxt,
kFmtHEAAC,
kFmtHEAAC2,
kFmtMPGSUR
};
enum SRMask {
kSR_32000 = (1 << 5),
kSR_44100 = (1 << 6),
kSR_48000 = (1 << 7),
kSR_88200 = (1 << 9),
kSR_96000 = (1 << 10),
kSR_176400 = (1 << 11),
kSR_192000 = (1 << 12),
};
enum BPSMask {
kBPS_16bit = (1 << 17),
kBPS_20bit = (1 << 18),
kBPS_24bit = (1 << 19),
};
enum SAMask {
kSA_FLFR = (1 << 0), // Front Left/Right
kSA_LFE = (1 << 1), // LFE (aka, subwoofer)
kSA_FC = (1 << 2), // Front Center
kSA_RLRR = (1 << 3), // Rear Left/Right
kSA_RC = (1 << 4), // Rear Center
kSA_FLCFRC = (1 << 5), // Front Left/Right Center
kSA_RLCRRC = (1 << 6), // Rear Left/Right Center
kSA_FLWFRW = (1 << 7), // Front Left/Right Wide
kSA_FLHFRH = (1 << 8), // Front Left/Right High
kSA_TC = (1 << 9), // Top Center (overhead)
kSA_FCH = (1 << 10), // Front Center High
};
typedef struct {
AudFormat fmt;
uint32_t max_ch;
uint32_t sr_bitmask;
uint32_t bps_bitmask;
uint32_t comp_bitrate;
} Mode;
HDMIAudioCaps();
~HDMIAudioCaps() { reset(); }
bool loadCaps(int ALSADeviceID);
void reset();
void getRatesForAF(String8& rates, audio_format_t format);
void getFmtsForAF(String8& fmts);
void getChannelMasksForAF(String8& masks, audio_format_t format);
bool supportsFormat(audio_format_t format,
uint32_t sampleRate,
uint32_t channelCount,
bool isIec958NonAudio);
bool basicAudioSupport() const { return mBasicAudioSupported; }
uint16_t speakerAllocation() const { return mSpeakerAlloc; }
size_t modeCnt() const { return mModes.size(); }
const Mode& getMode(size_t ndx) const { return mModes[ndx]; }
static const char* fmtToString(AudFormat fmt);
static uint32_t srMaskToSR(uint32_t mask);
static uint32_t bpsMaskToBPS(uint32_t mask);
static const char* saMaskToString(uint32_t mask);
private:
Mutex mLock;
bool mBasicAudioSupported;
uint16_t mSpeakerAlloc;
Vector<Mode> mModes;
void reset_l();
ssize_t getMaxChModeNdx_l();
static bool sanityCheckMode(const Mode& m);
static AudFormat alsaFormatFromAndroidFormat(audio_format_t format);
const Mode *getModeForFormat(AudFormat format);
};
} // namespace android
#endif // __cplusplus
#endif // ANDROID_ALSA_UTILS_H

View file

@ -0,0 +1,36 @@
/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <hardware/hardware.h>
#include <hardware/audio.h>
extern int atv_audiodev_open(const hw_module_t*, const char*, hw_device_t**);
static struct hw_module_methods_t hal_module_methods = {
.open = atv_audiodev_open,
};
struct audio_module HAL_MODULE_INFO_SYM = {
.common = {
.tag = HARDWARE_MODULE_TAG,
.module_api_version = AUDIO_MODULE_API_VERSION_0_1,
.hal_api_version = HARDWARE_HAL_API_VERSION,
.id = AUDIO_HARDWARE_MODULE_ID,
.name = "Audio HW HAL",
.author = "The Android Open Source Project",
.methods = &hal_module_methods,
},
};

View file

@ -0,0 +1,724 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_TAG "AudioHAL:audio_hal_thunks"
#include <utils/Log.h>
#include <errno.h>
#include <stdlib.h>
#include <hardware/hardware.h>
#include <hardware/audio.h>
#include "AudioHardwareInput.h"
#include "AudioHardwareOutput.h"
#include "AudioStreamIn.h"
#include "AudioStreamOut.h"
namespace android {
extern AudioHardwareInput gAudioHardwareInput;
extern AudioHardwareOutput gAudioHardwareOutput;
struct atv_audio_device {
struct audio_hw_device device;
AudioHardwareOutput* output;
AudioHardwareInput* input;
};
struct atv_stream_out {
struct audio_stream_out stream;
AudioHardwareOutput* hw;
AudioStreamOut* impl;
};
struct atv_stream_in {
struct audio_stream_in stream;
AudioStreamIn* impl;
};
/*******************************************************************************
*
* Audio output stream stubs.
*
******************************************************************************/
static int out_set_volume(struct audio_stream_out *stream,
float left,
float right)
{
(void) stream;
(void) left;
(void) right;
return 0;
}
static int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
{
(void) stream;
(void) effect;
return 0;
}
static int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
{
(void) stream;
(void) effect;
return 0;
}
/*******************************************************************************
*
* Audio output stream implementation
*
******************************************************************************/
static uint32_t out_get_sample_rate(const struct audio_stream *stream)
{
const struct atv_stream_out* tstream =
reinterpret_cast<const struct atv_stream_out*>(stream);
return tstream->impl->sampleRate();
}
static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate)
{
const struct atv_stream_out* tstream =
reinterpret_cast<const struct atv_stream_out*>(stream);
if (rate != tstream->impl->sampleRate())
return -EINVAL;
return 0;
}
static size_t out_get_buffer_size(const struct audio_stream *stream)
{
const struct atv_stream_out* tstream =
reinterpret_cast<const struct atv_stream_out*>(stream);
return tstream->impl->bufferSize();
}
static audio_channel_mask_t out_get_channels(const struct audio_stream *stream)
{
const struct atv_stream_out* tstream =
reinterpret_cast<const struct atv_stream_out*>(stream);
return tstream->impl->chanMask();
}
static audio_format_t out_get_format(const struct audio_stream *stream)
{
const struct atv_stream_out* tstream =
reinterpret_cast<const struct atv_stream_out*>(stream);
return tstream->impl->format();
}
static int out_set_format(struct audio_stream *stream, audio_format_t format)
{
const struct atv_stream_out* tstream =
reinterpret_cast<const struct atv_stream_out*>(stream);
if (format != tstream->impl->format())
return -EINVAL;
return 0;
}
static uint32_t out_get_latency(const struct audio_stream_out *stream)
{
const struct atv_stream_out* tstream =
reinterpret_cast<const struct atv_stream_out*>(stream);
return tstream->impl->latency();
}
static int out_standby(struct audio_stream *stream)
{
struct atv_stream_out* tstream =
reinterpret_cast<struct atv_stream_out*>(stream);
return tstream->impl->standby();
}
static int out_dump(const struct audio_stream *stream, int fd)
{
const struct atv_stream_out* tstream =
reinterpret_cast<const struct atv_stream_out*>(stream);
return tstream->impl->dump(fd);
}
static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
{
struct atv_stream_out* tstream =
reinterpret_cast<struct atv_stream_out*>(stream);
return tstream->impl->setParameters(stream, kvpairs);
}
static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
{
const struct atv_stream_out* tstream =
reinterpret_cast<const struct atv_stream_out*>(stream);
return tstream->impl->getParameters(keys);
}
static ssize_t out_write(struct audio_stream_out *stream, const void* buffer,
size_t bytes)
{
struct atv_stream_out* tstream =
reinterpret_cast<struct atv_stream_out*>(stream);
return tstream->impl->write(buffer, bytes);
}
static int out_get_render_position(const struct audio_stream_out *stream,
uint32_t *dsp_frames)
{
const struct atv_stream_out* tstream =
reinterpret_cast<const struct atv_stream_out*>(stream);
return tstream->impl->getRenderPosition(dsp_frames);
}
static int out_get_presentation_position(const struct audio_stream_out *stream,
uint64_t *frames, struct timespec *timestamp)
{
const struct atv_stream_out* tstream =
reinterpret_cast<const struct atv_stream_out*>(stream);
return tstream->impl->getPresentationPosition(frames, timestamp);
}
static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
int64_t *timestamp __unused)
{
return -ENOSYS;
}
static int out_pause(struct audio_stream_out* stream)
{
const struct atv_stream_out* tstream =
reinterpret_cast<const struct atv_stream_out*>(stream);
return tstream->impl->pause();
}
static int out_resume(struct audio_stream_out* stream)
{
const struct atv_stream_out* tstream =
reinterpret_cast<const struct atv_stream_out*>(stream);
return tstream->impl->resume();
}
static int out_flush(struct audio_stream_out* stream)
{
const struct atv_stream_out* tstream =
reinterpret_cast<const struct atv_stream_out*>(stream);
return tstream->impl->flush();
}
/*******************************************************************************
*
* Audio input stream implementation
*
******************************************************************************/
static uint32_t in_get_sample_rate(const struct audio_stream *stream)
{
const struct atv_stream_in* tstream =
reinterpret_cast<const struct atv_stream_in*>(stream);
return tstream->impl->getSampleRate();
}
static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate)
{
const struct atv_stream_in* tstream =
reinterpret_cast<const struct atv_stream_in*>(stream);
return tstream->impl->setSampleRate(rate);
}
static size_t in_get_buffer_size(const struct audio_stream *stream)
{
const struct atv_stream_in* tstream =
reinterpret_cast<const struct atv_stream_in*>(stream);
return tstream->impl->getBufferSize();
}
static uint32_t in_get_channels(const struct audio_stream *stream)
{
const struct atv_stream_in* tstream =
reinterpret_cast<const struct atv_stream_in*>(stream);
return tstream->impl->getChannelMask();
}
static audio_format_t in_get_format(const struct audio_stream *stream)
{
const struct atv_stream_in* tstream =
reinterpret_cast<const struct atv_stream_in*>(stream);
return tstream->impl->getFormat();
}
static int in_set_format(struct audio_stream *stream, audio_format_t format)
{
const struct atv_stream_in* tstream =
reinterpret_cast<const struct atv_stream_in*>(stream);
return tstream->impl->setFormat(format);
}
static int in_standby(struct audio_stream *stream)
{
const struct atv_stream_in* tstream =
reinterpret_cast<const struct atv_stream_in*>(stream);
return tstream->impl->standby();
}
static int in_dump(const struct audio_stream *stream, int fd)
{
const struct atv_stream_in* tstream =
reinterpret_cast<const struct atv_stream_in*>(stream);
return tstream->impl->dump(fd);
}
static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
{
const struct atv_stream_in* tstream =
reinterpret_cast<const struct atv_stream_in*>(stream);
return tstream->impl->setParameters(stream, kvpairs);
}
static char* in_get_parameters(const struct audio_stream *stream,
const char *keys)
{
const struct atv_stream_in* tstream =
reinterpret_cast<const struct atv_stream_in*>(stream);
return tstream->impl->getParameters(keys);
}
static int in_set_gain(struct audio_stream_in *stream, float gain)
{
const struct atv_stream_in* tstream =
reinterpret_cast<const struct atv_stream_in*>(stream);
return tstream->impl->setGain(gain);
}
static ssize_t in_read(struct audio_stream_in *stream, void* buffer,
size_t bytes)
{
const struct atv_stream_in* tstream =
reinterpret_cast<const struct atv_stream_in*>(stream);
return tstream->impl->read(buffer, bytes);
}
static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream)
{
const struct atv_stream_in* tstream =
reinterpret_cast<const struct atv_stream_in*>(stream);
return tstream->impl->getInputFramesLost();
}
static int in_add_audio_effect(const struct audio_stream *stream,
effect_handle_t effect)
{
const struct atv_stream_in* tstream =
reinterpret_cast<const struct atv_stream_in*>(stream);
return tstream->impl->addAudioEffect(effect);
}
static int in_remove_audio_effect(const struct audio_stream *stream,
effect_handle_t effect)
{
const struct atv_stream_in* tstream =
reinterpret_cast<const struct atv_stream_in*>(stream);
return tstream->impl->removeAudioEffect(effect);
}
/*******************************************************************************
*
* Audio device stubs
*
******************************************************************************/
static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
{
const struct atv_audio_device* adev =
reinterpret_cast<const struct atv_audio_device*>(dev);
return adev->output->setParameters(kvpairs);
}
static char * adev_get_parameters(const struct audio_hw_device *dev,
const char *keys)
{
const struct atv_audio_device* adev =
reinterpret_cast<const struct atv_audio_device*>(dev);
return adev->output->getParameters(keys);
}
static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
{
(void) dev;
(void) volume;
return 0;
}
static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
{
(void) dev;
(void) mode;
return 0;
}
static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
{
const struct atv_audio_device* adev =
reinterpret_cast<struct atv_audio_device*>(dev);
return adev->input->setMicMute(state);
}
static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
{
const struct atv_audio_device* adev =
reinterpret_cast<const struct atv_audio_device*>(dev);
return adev->input->getMicMute(state);
}
static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev,
const audio_config *config)
{
const struct atv_audio_device* adev =
reinterpret_cast<const struct atv_audio_device*>(dev);
return adev->input->getInputBufferSize(config);
}
static int adev_open_input_stream(struct audio_hw_device *dev,
audio_io_handle_t handle,
audio_devices_t devices,
struct audio_config *config,
struct audio_stream_in **stream_in,
audio_input_flags_t flags,
const char *address __unused,
audio_source_t source __unused)
{
(void) handle;
(void) flags;
int ret = 0;
struct atv_audio_device* adev =
reinterpret_cast<struct atv_audio_device*>(dev);
struct atv_stream_in *in = NULL;
*stream_in = NULL;
in = reinterpret_cast<struct atv_stream_in*>(
calloc(1, sizeof(struct atv_stream_in)));
if (!in) {
ret = -ENOMEM;
goto bailout;
}
in->stream.common.get_sample_rate = in_get_sample_rate;
in->stream.common.set_sample_rate = in_set_sample_rate;
in->stream.common.get_buffer_size = in_get_buffer_size;
in->stream.common.get_channels = in_get_channels;
in->stream.common.get_format = in_get_format;
in->stream.common.set_format = in_set_format;
in->stream.common.standby = in_standby;
in->stream.common.dump = in_dump;
in->stream.common.set_parameters = in_set_parameters;
in->stream.common.get_parameters = in_get_parameters;
in->stream.common.add_audio_effect = in_add_audio_effect;
in->stream.common.remove_audio_effect = in_remove_audio_effect;
in->stream.set_gain = in_set_gain;
in->stream.read = in_read;
in->stream.get_input_frames_lost = in_get_input_frames_lost;
in->impl = adev->input->openInputStream(devices,
&config->format,
&config->channel_mask,
&config->sample_rate,
reinterpret_cast<status_t*>(&ret));
if (NULL == in->impl) {
ret = -ENOMEM;
goto bailout;
}
if (0 == ret)
*stream_in = &in->stream;
bailout:
if ((0 != ret) && (NULL != in)) {
delete in->impl;
free(in);
}
return ret;
}
static void adev_close_input_stream(struct audio_hw_device *dev,
struct audio_stream_in *stream)
{
struct atv_audio_device* adev =
reinterpret_cast<struct atv_audio_device*>(dev);
struct atv_stream_in* tstream =
reinterpret_cast<struct atv_stream_in*>(stream);
adev->input->closeInputStream(tstream->impl);
free(stream);
}
static int adev_open_output_stream(struct audio_hw_device *dev,
audio_io_handle_t handle,
audio_devices_t devices,
audio_output_flags_t flags,
struct audio_config *config,
struct audio_stream_out **stream_out,
const char *address __unused)
{
(void) handle;
int ret = 0;
struct atv_audio_device* adev =
reinterpret_cast<struct atv_audio_device*>(dev);
struct atv_stream_out *out = NULL;
*stream_out = NULL;
out = reinterpret_cast<struct atv_stream_out*>(
calloc(1, sizeof(struct atv_stream_out)));
if (!out) {
ret = -ENOMEM;
goto bailout;
}
out->stream.common.get_sample_rate = out_get_sample_rate;
out->stream.common.set_sample_rate = out_set_sample_rate;
out->stream.common.get_buffer_size = out_get_buffer_size;
out->stream.common.get_channels = out_get_channels;
out->stream.common.get_format = out_get_format;
out->stream.common.set_format = out_set_format;
out->stream.common.standby = out_standby;
out->stream.common.dump = out_dump;
out->stream.common.set_parameters = out_set_parameters;
out->stream.common.get_parameters = out_get_parameters;
out->stream.common.add_audio_effect = out_add_audio_effect;
out->stream.common.remove_audio_effect = out_remove_audio_effect;
out->stream.get_latency = out_get_latency;
out->stream.set_volume = out_set_volume;
out->stream.write = out_write;
out->stream.get_render_position = out_get_render_position;
out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
out->stream.get_presentation_position = out_get_presentation_position;
out->stream.pause = out_pause;
out->stream.resume = out_resume;
out->stream.flush = out_flush;
out->impl = adev->output->openOutputStream(
devices,
&config->format,
&config->channel_mask,
&config->sample_rate,
flags,
reinterpret_cast<status_t*>(&ret));
if (NULL == out->impl) {
ret = -ENOMEM;
goto bailout;
}
if (0 == ret) {
out->hw = adev->output;
*stream_out = &out->stream;
}
bailout:
if ((0 != ret) && (NULL != out)) {
delete out->impl;
free(out);
}
return ret;
}
static void adev_close_output_stream(struct audio_hw_device *dev,
struct audio_stream_out *stream)
{
struct atv_audio_device* adev =
reinterpret_cast<struct atv_audio_device*>(dev);
struct atv_stream_out* tstream =
reinterpret_cast<struct atv_stream_out*>(stream);
adev->output->closeOutputStream(tstream->impl);
free(stream);
}
static int adev_init_check(const struct audio_hw_device *dev)
{
const struct atv_audio_device* adev =
reinterpret_cast<const struct atv_audio_device*>(dev);
return adev->output->initCheck();
}
static int adev_set_master_volume(struct audio_hw_device *dev, float volume)
{
struct atv_audio_device* adev =
reinterpret_cast<struct atv_audio_device*>(dev);
return adev->output->setMasterVolume(volume);
}
static int adev_get_master_volume(struct audio_hw_device *dev,
float *volume)
{
struct atv_audio_device* adev =
reinterpret_cast<struct atv_audio_device*>(dev);
return adev->output->getMasterVolume(volume);
}
static int adev_set_master_mute(struct audio_hw_device *dev, bool muted)
{
struct atv_audio_device* adev =
reinterpret_cast<struct atv_audio_device*>(dev);
return adev->output->setMasterMute(muted);
}
static int adev_get_master_mute(struct audio_hw_device *dev,
bool *muted)
{
struct atv_audio_device* adev =
reinterpret_cast<struct atv_audio_device*>(dev);
return adev->output->getMasterMute(muted);
}
static int adev_dump(const audio_hw_device* dev, int fd)
{
const struct atv_audio_device* adev =
reinterpret_cast<const struct atv_audio_device*>(dev);
int ret = adev->output->dump(fd);
if (ret == 0) {
ret = adev->input->dump(fd);
}
return ret;
}
static int adev_close(hw_device_t *device)
{
struct atv_audio_device* adev =
reinterpret_cast<struct atv_audio_device*>(device);
free(device);
return 0;
}
static int atv_audiodev_open_cpp(
const hw_module_t* module,
const char* name,
hw_device_t** device)
{
struct atv_audio_device* adev = NULL;
int ret = 0;
if (NULL == device) {
ret = -EINVAL;
goto bailout;
}
*device = NULL;
if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) {
ret = -EINVAL;
goto bailout;
}
adev = (struct atv_audio_device*)calloc(1,
sizeof(struct atv_audio_device));
if (NULL == adev) {
ret = -ENOMEM;
goto bailout;
}
adev->device.common.tag = HARDWARE_DEVICE_TAG;
adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
adev->device.common.module = (struct hw_module_t *) module;
adev->device.common.close = adev_close;
adev->device.init_check = adev_init_check;
adev->device.set_voice_volume = adev_set_voice_volume;
adev->device.set_master_volume = adev_set_master_volume;
adev->device.get_master_volume = adev_get_master_volume;
adev->device.set_master_mute = adev_set_master_mute;
adev->device.get_master_mute = adev_get_master_mute;
adev->device.set_mode = adev_set_mode;
adev->device.set_mic_mute = adev_set_mic_mute;
adev->device.get_mic_mute = adev_get_mic_mute;
adev->device.set_parameters = adev_set_parameters;
adev->device.get_parameters = adev_get_parameters;
adev->device.get_input_buffer_size = adev_get_input_buffer_size;
adev->device.open_output_stream = adev_open_output_stream;
adev->device.close_output_stream = adev_close_output_stream;
adev->device.open_input_stream = adev_open_input_stream;
adev->device.close_input_stream = adev_close_input_stream;
adev->device.dump = adev_dump;
adev->output = &gAudioHardwareOutput;
adev->input = &gAudioHardwareInput;
*device = &adev->device.common;
bailout:
if ((0 != ret) && (NULL != adev)) {
free(adev);
}
return 0;
}
} // namespace android
extern "C" int atv_audiodev_open(const hw_module_t* module,
const char* name,
hw_device_t** device) {
return android::atv_audiodev_open_cpp(module, name, device);
}

View file

@ -0,0 +1,40 @@
<manifest version="1.0" type="device">
<hal format="hidl">
<name>android.hardware.graphics.allocator</name>
<transport>hwbinder</transport>
<impl level="generic"></impl>
<version>2.0</version>
<interface>
<name>IAllocator</name>
<instance>default</instance>
</interface>
</hal>
<hal format="hidl">
<name>android.hardware.graphics.composer</name>
<transport arch="32+64">passthrough</transport>
<version>2.1</version>
<interface>
<name>IComposer</name>
<instance>default</instance>
</interface>
</hal>
<hal format="hidl">
<name>android.hardware.graphics.mapper</name>
<transport arch="32+64">passthrough</transport>
<impl level="generic"></impl>
<version>2.0</version>
<interface>
<name>IMapper</name>
<instance>default</instance>
</interface>
</hal>
<hal format="hidl">
<name>android.hardware.wifi.supplicant</name>
<transport>hwbinder</transport>
<version>1.0</version>
<interface>
<name>ISupplicant</name>
<instance>default</instance>
</interface>
</hal>
</manifest>

View file

@ -0,0 +1,191 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright (C) 2012 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!--
<!DOCTYPE MediaCodecs [
<!ELEMENT Include EMPTY>
<!ATTLIST Include href CDATA #REQUIRED>
<!ELEMENT MediaCodecs (Decoders|Encoders|Include)*>
<!ELEMENT Decoders (MediaCodec|Include)*>
<!ELEMENT Encoders (MediaCodec|Include)*>
<!ELEMENT MediaCodec (Type|Quirk|Include)*>
<!ATTLIST MediaCodec name CDATA #REQUIRED>
<!ATTLIST MediaCodec type CDATA>
<!ELEMENT Type EMPTY>
<!ATTLIST Type name CDATA #REQUIRED>
<!ELEMENT Quirk EMPTY>
<!ATTLIST Quirk name CDATA #REQUIRED>
]>
There's a simple and a complex syntax to declare the availability of a
media codec:
A codec that properly follows the OpenMax spec and therefore doesn't have any
quirks and that only supports a single content type can be declared like so:
<MediaCodec name="OMX.foo.bar" type="something/interesting" />
If a codec has quirks OR supports multiple content types, the following syntax
can be used:
<MediaCodec name="OMX.foo.bar" >
<Type name="something/interesting" />
<Type name="something/else" />
...
<Quirk name="requires-allocate-on-input-ports" />
<Quirk name="requires-allocate-on-output-ports" />
<Quirk name="output-buffers-are-unreadable" />
</MediaCodec>
Only the three quirks included above are recognized at this point:
"requires-allocate-on-input-ports"
must be advertised if the component does not properly support specification
of input buffers using the OMX_UseBuffer(...) API but instead requires
OMX_AllocateBuffer to be used.
"requires-allocate-on-output-ports"
must be advertised if the component does not properly support specification
of output buffers using the OMX_UseBuffer(...) API but instead requires
OMX_AllocateBuffer to be used.
"output-buffers-are-unreadable"
must be advertised if the emitted output buffers of a decoder component
are not readable, i.e. use a custom format even though abusing one of
the official OMX colorspace constants.
Clients of such decoders will not be able to access the decoded data,
naturally making the component much less useful. The only use for
a component with this quirk is to render the output to the screen.
Audio decoders MUST NOT advertise this quirk.
Video decoders that advertise this quirk must be accompanied by a
corresponding color space converter for thumbnail extraction,
matching surfaceflinger support that can render the custom format to
a texture and possibly other code, so just DON'T USE THIS QUIRK.
-->
<MediaCodecs>
<Include href="media_codecs_google_audio.xml" />
<Settings>
<Setting name="max-video-encoder-input-buffers" value="2" />
</Settings>
<Decoders>
<MediaCodec name="OMX.Intel.VideoDecoder.MPEG4" type="video/mp4v-es">
<Limit name="size" min="96x32" max="1920x1088" />
<Limit name="alignment" value="2x2" />
<Limit name="block-size" value="16x16" />
<Limit name="blocks-per-second" range="12-244800" />
<Limit name="bitrate" range="1-20000000" />
<Feature name="adaptive-playback" optional="yes" />
<Limit name="concurrent-instances" max="4" />
</MediaCodec>
<MediaCodec name="OMX.Intel.VideoDecoder.H263" type="video/3gpp">
<Limit name="size" min="96x32" max="720x576" />
<Limit name="alignment" value="2x2" />
<Limit name="block-size" value="16x16" />
<Limit name="blocks-per-second" range="12-48600" />
<Limit name="bitrate" range="1-16000000" />
<Feature name="adaptive-playback" optional="yes" />
<Limit name="concurrent-instances" max="1" />
</MediaCodec>
<MediaCodec name="OMX.Intel.VideoDecoder.AVC" type="video/avc">
<Limit name="size" min="96x32" max="2560x1440" />
<Limit name="alignment" value="2x2" />
<Limit name="block-size" value="16x16" />
<Limit name="blocks-per-second" range="12-864000" />
<Limit name="bitrate" range="1-50000000" />
<Feature name="adaptive-playback" />
<Limit name="concurrent-instances" max="5" />
</MediaCodec>
<MediaCodec name="OMX.Intel.VideoDecoder.AVC.secure" type="video/avc">
<Limit name="size" min="96x32" max="1920x1088" />
<Limit name="alignment" value="2x2" />
<Limit name="block-size" value="16x16" />
<Limit name="blocks-per-second" range="12-522240" />
<Limit name="bitrate" range="1-50000000" />
<Feature name="adaptive-playback" />
<Feature name="secure-playback" required="true" />
<Limit name="concurrent-instances" max="1" />
</MediaCodec>
<MediaCodec name="OMX.Intel.VideoDecoder.VP8" type="video/x-vnd.on2.vp8">
<Limit name="size" min="96x32" max="1920x1088" />
<Limit name="alignment" value="2x2" />
<Limit name="block-size" value="16x16" />
<Limit name="blocks-per-second" range="12-489600" />
<Limit name="bitrate" range="1-50000000" />
<Feature name="adaptive-playback" />
<Limit name="concurrent-instances" max="4" />
</MediaCodec>
<MediaCodec name="OMX.Intel.VideoDecoder.MPEG2" type="video/mpeg2">
<Limit name="size" min="96x32" max="1920x1088" />
<Limit name="alignment" value="2x2" />
<Limit name="block-size" value="16x16" />
<Limit name="blocks-per-second" range="12-489600" />
<Limit name="bitrate" range="1-80000000" />
<Feature name="adaptive-playback" />
<Limit name="concurrent-instances" max="3" />
</MediaCodec>
<MediaCodec name="OMX.Intel.VideoDecoder.VP9.hybrid" type="video/x-vnd.on2.vp9">
<Limit name="size" min="16x16" max="1920x1088" />
<Limit name="alignment" value="2x2" />
<Limit name="block-size" value="16x16" />
<Limit name="blocks-per-second" range="1-244800" />
<Limit name="bitrate" range="1-8000000" />
<Feature name="adaptive-playback" />
<Limit name="concurrent-instances" max="2" />
</MediaCodec>
<MediaCodec name="OMX.Intel.sw_vd.h265" type="video/hevc">
<Limit name="size" min="16x16" max="1920x1088" />
<Limit name="alignment" value="2x2" />
<Limit name="block-size" value="16x16" />
<Limit name="blocks-per-second" range="1-244800" />
<Limit name="bitrate" range="1-8000000" />
<Feature name="adaptive-playback" />
<Limit name="concurrent-instances" max="5" />
</MediaCodec>
<MediaCodec name="OMX.google.gsm.decoder" type="audio/gsm" />
<MediaCodec name="OMX.Intel.alac.decoder" type="audio/alac" />
</Decoders>
<Encoders>
<MediaCodec name="OMX.Intel.VideoEncoder.AVC" type="video/avc" >
<Quirk name="requires-allocate-on-input-ports" />
<Limit name="size" min="176x144" max="1920x1088" />
<Limit name="alignment" value="8x8" />
<Limit name="block-size" value="16x16" />
<Limit name="frame-rate" range="1-60" />
<Limit name="bitrate" range="1-50000000" />
<Limit name="concurrent-instances" max="3" />
<Feature name="intra-refresh" optional="yes"/>
</MediaCodec>
<MediaCodec name="OMX.Intel.VideoEncoder.VP8" type="video/x-vnd.on2.vp8" >
<Quirk name="requires-allocate-on-input-ports" />
<Limit name="size" min="176x144" max="1920x1088" />
<Limit name="alignment" value="8x8" />
<Limit name="block-size" value="16x16" />
<Limit name="frame-rate" range="1-30" />
<Limit name="bitrate" range="1-10000000" />
<Limit name="concurrent-instances" max="3" />
<Feature name="intra-refresh" optional="yes"/>
</MediaCodec>
</Encoders>
<Include href="media_codecs_google_tv.xml" />
<Include href="media_codecs_google_video_le.xml" />
</MediaCodecs>

View file

@ -0,0 +1,138 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright 2017 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.
-->
<!-- Generated file for fugu using measurements between OPR1.170623.019 and OPM1.170913.003 -->
<MediaCodecs>
<Encoders>
<MediaCodec name="OMX.Intel.VideoEncoder.AVC" type="video/avc" update="true">
<!-- measured 98%:33-35 med:34/34 N=94 -->
<Limit name="measured-frame-rate-320x240" range="34-34" /> <!-- v98%=1.0 -->
<!-- measured 98%:29-31 med:30/30 N=94 -->
<Limit name="measured-frame-rate-720x480" range="30-30" /> <!-- v98%=1.0 -->
<!-- measured 98%:24-33 med:31/28 N=94 -->
<Limit name="measured-frame-rate-1280x720" range="28-28" /> <!-- v98%=1.2 -->
<!-- measured 98%:17-18 med:17/17 N=94 -->
<Limit name="measured-frame-rate-1920x1080" range="17-17" /> <!-- v98%=1.0 -->
</MediaCodec>
<MediaCodec name="OMX.Intel.VideoEncoder.VP8" type="video/x-vnd.on2.vp8" update="true">
<!-- measured 98%:88-92 med:90/90 N=92 -->
<Limit name="measured-frame-rate-640x360" range="90-90" /> <!-- v98%=1.0 (OPR1.170623.014-) -->
<!-- measured 98%:36-43 med:37/39 N=94 -->
<Limit name="measured-frame-rate-1280x720" range="37-39" /> <!-- v98%=1.1 -->
<!-- measured 98%:18-26 med:25/22 N=92 -->
<Limit name="measured-frame-rate-1920x1080" range="22-22" /> <!-- v98%=1.2 -->
</MediaCodec>
<MediaCodec name="OMX.google.h263.encoder" type="video/3gpp" update="true">
<!-- measured 98%:481-578 med:539/539 N=94 -->
<Limit name="measured-frame-rate-176x144" range="539-539" /> <!-- v98%=1.1 -->
</MediaCodec>
<MediaCodec name="OMX.google.h264.encoder" type="video/avc" update="true">
<!-- measured 98%:220-307 med:257/257 N=94 -->
<Limit name="measured-frame-rate-320x240" range="257-257" /> <!-- v98%=1.2 (-OPM1.170908.002) -->
<!-- measured 98%:77-117 med:91/90 N=94 -->
<Limit name="measured-frame-rate-720x480" range="90-90" /> <!-- v98%=1.2 (-OPM1.170908.002) -->
</MediaCodec>
<MediaCodec name="OMX.google.mpeg4.encoder" type="video/mp4v-es" update="true">
<!-- measured 98%:557-670 med:601/601 N=94 -->
<Limit name="measured-frame-rate-176x144" range="601-601" /> <!-- v98%=1.1 -->
</MediaCodec>
<MediaCodec name="OMX.google.vp8.encoder" type="video/x-vnd.on2.vp8" update="true">
<Limit name="measured-frame-rate-320x180" range="132-132" /> <!-- N=108 v98%=1.1 -->
<Limit name="measured-frame-rate-640x360" range="54-54" /> <!-- N=108 v98%=1.0 -->
<Limit name="measured-frame-rate-1280x720" range="27-27" /> <!-- N=108 v98%=1.1 -->
</MediaCodec>
</Encoders>
<Decoders>
<MediaCodec name="OMX.Intel.VideoDecoder.H263" type="video/3gpp" update="true">
<Limit name="measured-frame-rate-176x144" range="563-563" /> <!-- N=422 v98%=1.2 -->
<Limit name="measured-frame-rate-352x288" range="550-550" /> <!-- N=422 v98%=1.2 -->
</MediaCodec>
<!-- Measurements between OPR1.170623.013 and OPM1.170913.003 -->
<MediaCodec name="OMX.Intel.VideoDecoder.AVC" type="video/avc" update="true">
<!-- measured 98%:505-1249 med:1079/1077 FLAKY(mn=376.4 < 505 - 2154) -->
<Limit name="measured-frame-rate-320x240" range="752-1077" /> <!-- TWEAKED N=424 v98%=1.6 -->
<Limit name="measured-frame-rate-720x480" range="693-693" /> <!-- N=424 v98%=1.0 -->
<Limit name="measured-frame-rate-1280x720" range="277-277" /> <!-- N=424 v98%=1.0 -->
<Limit name="measured-frame-rate-1920x1080" range="127-127" /> <!-- N=424 v98%=1.0 -->
</MediaCodec>
<MediaCodec name="OMX.Intel.sw_vd.h265" type="video/hevc" update="true">
<!-- measured 98%:215-404 med:395/395 FLAKY(mn=178.5 < 198 - 790) -->
<Limit name="measured-frame-rate-352x288" range="357-395" /> <!-- TWEAKED N=422 v98%=1.4 -->
<!-- measured 98%:98-203 med:198/198 FLAKY(mn=96.2 < 98 - 396) -->
<Limit name="measured-frame-rate-640x360" range="192-198" /> <!-- TWEAKED N=422 v98%=1.4 -->
<!-- measured 98%:86-179 med:174/174 FLAKY(mn=79.2 < 86 - 348) -->
<Limit name="measured-frame-rate-720x480" range="158-174" /> <!-- TWEAKED N=422 v98%=1.4 -->
<!-- measured 98%:38-74 med:67/67 FLAKY(mn=33.0 < 34 - 134) -->
<Limit name="measured-frame-rate-1280x720" range="66-67" /> <!-- TWEAKED N=422 v98%=1.4 -->
</MediaCodec>
<MediaCodec name="OMX.Intel.VideoDecoder.MPEG4" type="video/mp4v-es" update="true">
<Limit name="measured-frame-rate-176x144" range="370-370" /> <!-- N=424 v98%=1.1 -->
</MediaCodec>
<MediaCodec name="OMX.Intel.VideoDecoder.VP8" type="video/x-vnd.on2.vp8" update="true">
<Limit name="measured-frame-rate-320x180" range="424-424" /> <!-- N=422 v98%=1.1 -->
<Limit name="measured-frame-rate-640x360" range="275-275" /> <!-- N=422 v98%=1.1 -->
<Limit name="measured-frame-rate-1280x720" range="128-128" /> <!-- N=424 v98%=1.0 (OPR1.170623.013-) -->
<Limit name="measured-frame-rate-1920x1080" range="63-63" /> <!-- N=422 v98%=1.0 -->
</MediaCodec>
<MediaCodec name="OMX.Intel.VideoDecoder.VP9.hybrid" type="video/x-vnd.on2.vp9" update="true">
<Limit name="measured-frame-rate-320x180" range="318-318" /> <!-- N=420 v98%=1.4 -->
<!-- measured 90%:101-135 med:131/130 FLAKY(mn=62.7 < 65 - 260) -->
<Limit name="measured-frame-rate-640x360" range="125-130" /> <!-- TWEAKED N=420 v90%=1.2 -->
<Limit name="measured-frame-rate-1280x720" range="47-47" /> <!-- N=420 v98%=1.4 -->
<!-- measured 98%:17-35 med:34/34 FLAKY(mn=15.0 < 17 - 68) -->
<Limit name="measured-frame-rate-1920x1080" range="30-34" /> <!-- TWEAKED N=420 v98%=1.4 -->
</MediaCodec>
<MediaCodec name="OMX.google.h263.decoder" type="video/3gpp" update="true">
<!-- measured 98%:413-758 med:736/736 FLAKY(mn=298.9 < 368 - 1472) -->
<Limit name="measured-frame-rate-176x144" range="597-736" /> <!-- TWEAKED N=422 v98%=1.4 -->
</MediaCodec>
<!-- Measurements between OPR1.170623.013 and OPM1.170913.003 -->
<MediaCodec name="OMX.google.h264.decoder" type="video/avc" update="true">
<!-- measured 98%:171-325 med:307/307 FLAKY(mn=140.0 < 154 - 614) -->
<Limit name="measured-frame-rate-320x240" range="279-307" /> <!-- TWEAKED N=610 v98%=1.4 -->
<Limit name="measured-frame-rate-720x480" range="110-110" /> <!-- N=610 v98%=1.2 -->
<!-- measured 98%:20-42 med:39/39 FLAKY(mn=16.3 < 20 - 78) -->
<Limit name="measured-frame-rate-1280x720" range="32-39" /> <!-- TWEAKED N=610 v98%=1.4 -->
<!-- measured 98%:8-18 med:17/17 FLAKY(mn=6.9 < 8 - 34) -->
<Limit name="measured-frame-rate-1920x1080" range="15-17" /> <!-- TWEAKED N=517 v98%=1.5 -->
</MediaCodec>
<MediaCodec name="OMX.google.hevc.decoder" type="video/hevc" update="true">
<Limit name="measured-frame-rate-352x288" range="286-286" /> <!-- N=422 v98%=1.4 -->
<!-- measured 95%:99-142 med:130/130 FLAKY(mn=57.9 < 65 - 260) -->
<Limit name="measured-frame-rate-640x360" range="115-130" /> <!-- TWEAKED N=422 v95%=1.2 -->
<!-- measured 97%:86-125 med:118/118 FLAKY(mn=54.5 < 59 - 236) -->
<Limit name="measured-frame-rate-720x480" range="108-118" /> <!-- TWEAKED N=422 v97%=1.2 -->
<!-- measured 98%:24-54 med:52/51 FLAKY(mn=20.6 < 24 - 102) -->
<Limit name="measured-frame-rate-1280x720" range="41-51" /> <!-- TWEAKED N=422 v98%=1.5 -->
</MediaCodec>
<MediaCodec name="OMX.google.mpeg4.decoder" type="video/mp4v-es" update="true">
<!-- measured 98%:493-911 med:875/875 FLAKY(mn=392.0 < 438 - 1750) -->
<Limit name="measured-frame-rate-176x144" range="784-875" /> <!-- TWEAKED N=424 v98%=1.4 -->
</MediaCodec>
<MediaCodec name="OMX.google.vp8.decoder" type="video/x-vnd.on2.vp8" update="true">
<Limit name="measured-frame-rate-320x180" range="594-594" /> <!-- N=422 v98%=1.4 -->
<Limit name="measured-frame-rate-640x360" range="189-189" /> <!-- N=422 v98%=1.3 -->
<Limit name="measured-frame-rate-1280x720" range="45-45" /> <!-- N=422 v98%=1.3 -->
<Limit name="measured-frame-rate-1920x1080" range="18-18" /> <!-- N=422 v98%=1.3 -->
</MediaCodec>
<MediaCodec name="OMX.google.vp9.decoder" type="video/x-vnd.on2.vp9" update="true">
<Limit name="measured-frame-rate-320x180" range="459-459" /> <!-- N=420 v98%=1.2 -->
<!-- measured 97%:133-190 med:183/183 FLAKY(mn=85.1 < 92 - 366) -->
<Limit name="measured-frame-rate-640x360" range="170-183" /> <!-- TWEAKED N=420 v97%=1.2 -->
<Limit name="measured-frame-rate-1280x720" range="59-59" /> <!-- N=420 v98%=1.4 -->
</MediaCodec>
</Decoders>
</MediaCodecs>

View file

@ -0,0 +1,562 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2010 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!DOCTYPE MediaSettings [
<!ELEMENT MediaSettings (CamcorderProfiles,
EncoderOutputFileFormat+,
VideoEncoderCap+,
AudioEncoderCap+,
VideoDecoderCap,
AudioDecoderCap)>
<!ELEMENT CamcorderProfiles (EncoderProfile+, ImageEncoding+, ImageDecoding, Camera)>
<!ATTLIST CamcorderProfiles cameraId (0|1) #REQUIRED>
<!ELEMENT EncoderProfile (Video, Audio)>
<!ATTLIST EncoderProfile quality (high|low) #REQUIRED>
<!ATTLIST EncoderProfile fileFormat (mp4|3gp) #REQUIRED>
<!ATTLIST EncoderProfile duration (30|60) #REQUIRED>
<!ELEMENT Video EMPTY>
<!ATTLIST Video codec (h264|h263|m4v) #REQUIRED>
<!ATTLIST Video bitRate CDATA #REQUIRED>
<!ATTLIST Video width CDATA #REQUIRED>
<!ATTLIST Video height CDATA #REQUIRED>
<!ATTLIST Video frameRate CDATA #REQUIRED>
<!ELEMENT Audio EMPTY>
<!ATTLIST Audio codec (amrnb|amrwb|aac) #REQUIRED>
<!ATTLIST Audio bitRate CDATA #REQUIRED>
<!ATTLIST Audio sampleRate CDATA #REQUIRED>
<!ATTLIST Audio channels (1|2) #REQUIRED>
<!ELEMENT ImageEncoding EMPTY>
<!ATTLIST ImageEncoding quality (90|80|70|60|50|40) #REQUIRED>
<!ELEMENT ImageDecoding EMPTY>
<!ATTLIST ImageDecoding memCap CDATA #REQUIRED>
<!ELEMENT Camera EMPTY>
<!ATTLIST Camera previewFrameRate CDATA #REQUIRED>
<!ELEMENT EncoderOutputFileFormat EMPTY>
<!ATTLIST EncoderOutputFileFormat name (mp4|3gp) #REQUIRED>
<!ELEMENT VideoEncoderCap EMPTY>
<!ATTLIST VideoEncoderCap name (h264|h263|m4v|wmv) #REQUIRED>
<!ATTLIST VideoEncoderCap enabled (true|false) #REQUIRED>
<!ATTLIST VideoEncoderCap minBitRate CDATA #REQUIRED>
<!ATTLIST VideoEncoderCap maxBitRate CDATA #REQUIRED>
<!ATTLIST VideoEncoderCap minFrameWidth CDATA #REQUIRED>
<!ATTLIST VideoEncoderCap maxFrameWidth CDATA #REQUIRED>
<!ATTLIST VideoEncoderCap minFrameHeight CDATA #REQUIRED>
<!ATTLIST VideoEncoderCap maxFrameHeight CDATA #REQUIRED>
<!ATTLIST VideoEncoderCap minFrameRate CDATA #REQUIRED>
<!ATTLIST VideoEncoderCap maxFrameRate CDATA #REQUIRED>
<!ELEMENT AudioEncoderCap EMPTY>
<!ATTLIST AudioEncoderCap name (amrnb|amrwb|aac|heaac|aaceld) #REQUIRED>
<!ATTLIST AudioEncoderCap enabled (true|false) #REQUIRED>
<!ATTLIST AudioEncoderCap minBitRate CDATA #REQUIRED>
<!ATTLIST AudioEncoderCap maxBitRate CDATA #REQUIRED>
<!ATTLIST AudioEncoderCap minSampleRate CDATA #REQUIRED>
<!ATTLIST AudioEncoderCap maxSampleRate CDATA #REQUIRED>
<!ATTLIST AudioEncoderCap minChannels (1|2) #REQUIRED>
<!ATTLIST AudioEncoderCap maxChannels (1|2) #REQUIRED>
<!ELEMENT VideoDecoderCap EMPTY>
<!ATTLIST VideoDecoderCap name (wmv) #REQUIRED>
<!ATTLIST VideoDecoderCap enabled (true|false) #REQUIRED>
<!ELEMENT AudioDecoderCap EMPTY>
<!ATTLIST AudioDecoderCap name (wma) #REQUIRED>
<!ATTLIST AudioDecoderCap enabled (true|false) #REQUIRED>
]>
<!--
This file is used to declare the multimedia profiles and capabilities
on an android-powered device.
-->
<MediaSettings>
<!-- Each camcorder profile defines a set of predefined configuration parameters -->
<CamcorderProfiles cameraId="0">
<EncoderProfile quality="low" fileFormat="3gp" duration="30">
<Video codec="h263"
bitRate="128000"
width="176"
height="144"
frameRate="15" />
<Audio codec="amrnb"
bitRate="12200"
sampleRate="8000"
channels="1" />
</EncoderProfile>
<EncoderProfile quality="high" fileFormat="mp4" duration="60">
<Video codec="h264"
bitRate="15000000"
width="1920"
height="1080"
frameRate="30" />
<Audio codec="aac"
bitRate="192000"
sampleRate="48000"
channels="2" />
</EncoderProfile>
<EncoderProfile quality="qcif" fileFormat="3gp" duration="30">
<Video codec="h263"
bitRate="128000"
width="176"
height="144"
frameRate="15" />
<Audio codec="amrnb"
bitRate="12200"
sampleRate="8000"
channels="1" />
</EncoderProfile>
<EncoderProfile quality="cif" fileFormat="3gp" duration="30">
<Video codec="h264"
bitRate="640000"
width="352"
height="288"
frameRate="30" />
<Audio codec="amrnb"
bitRate="12200"
sampleRate="8000"
channels="1" />
</EncoderProfile>
<EncoderProfile quality="qvga" fileFormat="3gp" duration="30">
<Video codec="h264"
bitRate="640000"
width="320"
height="240"
frameRate="30" />
<Audio codec="aac"
bitRate="128000"
sampleRate="48000"
channels="2" />
</EncoderProfile>
<EncoderProfile quality="480p" fileFormat="mp4" duration="60">
<Video codec="h264"
bitRate="3000000"
width="720"
height="480"
frameRate="30" />
<Audio codec="aac"
bitRate="128000"
sampleRate="48000"
channels="2" />
</EncoderProfile>
<EncoderProfile quality="720p" fileFormat="mp4" duration="60">
<Video codec="h264"
bitRate="8000000"
width="1280"
height="720"
frameRate="30" />
<Audio codec="aac"
bitRate="192000"
sampleRate="48000"
channels="2" />
</EncoderProfile>
<EncoderProfile quality="1080p" fileFormat="mp4" duration="60">
<Video codec="h264"
bitRate="15000000"
width="1920"
height="1080"
frameRate="30" />
<Audio codec="aac"
bitRate="192000"
sampleRate="48000"
channels="2" />
</EncoderProfile>
<EncoderProfile quality="timelapselow" fileFormat="3gp" duration="30">
<Video codec="h263"
bitRate="128000"
width="176"
height="144"
frameRate="15" />
<Audio codec="amrnb"
bitRate="12200"
sampleRate="8000"
channels="1" />
</EncoderProfile>
<EncoderProfile quality="timelapsehigh" fileFormat="mp4" duration="30">
<Video codec="h264"
bitRate="15000000"
width="1920"
height="1080"
frameRate="30" />
<Audio codec="aac"
bitRate="192000"
sampleRate="48000"
channels="2" />
</EncoderProfile>
<EncoderProfile quality="timelapseqcif" fileFormat="3gp" duration="30">
<Video codec="h263"
bitRate="128000"
width="176"
height="144"
frameRate="15" />
<Audio codec="amrnb"
bitRate="12200"
sampleRate="8000"
channels="1" />
</EncoderProfile>
<EncoderProfile quality="timelapsecif" fileFormat="3gp" duration="30">
<Video codec="h264"
bitRate="640000"
width="352"
height="288"
frameRate="30" />
<Audio codec="amrnb"
bitRate="12200"
sampleRate="8000"
channels="1" />
</EncoderProfile>
<EncoderProfile quality="timelapse480p" fileFormat="mp4" duration="30">
<Video codec="h264"
bitRate="3000000"
width="720"
height="480"
frameRate="30" />
<Audio codec="amrnb"
bitRate="12200"
sampleRate="8000"
channels="1" />
</EncoderProfile>
<EncoderProfile quality="timelapse720p" fileFormat="mp4" duration="30">
<Video codec="h264"
bitRate="8000000"
width="1280"
height="720"
frameRate="30" />
<Audio codec="aac"
bitRate="192000"
sampleRate="48000"
channels="2" />
</EncoderProfile>
<EncoderProfile quality="timelapse1080p" fileFormat="mp4" duration="30">
<Video codec="h264"
bitRate="15000000"
width="1920"
height="1080"
frameRate="30" />
<Audio codec="aac"
bitRate="192000"
sampleRate="48000"
channels="2" />
</EncoderProfile>
<ImageEncoding quality="90" />
<ImageEncoding quality="80" />
<ImageEncoding quality="70" />
<ImageDecoding memCap="20000000" />
<Camera previewFrameRate="30" />
</CamcorderProfiles>
<CamcorderProfiles cameraId="1">
<EncoderProfile quality="high" fileFormat="mp4" duration="60">
<Video codec="h264"
bitRate="15000000"
width="1920"
height="1080"
frameRate="30" />
<Audio codec="aac"
bitRate="192000"
sampleRate="48000"
channels="2" />
</EncoderProfile>
<EncoderProfile quality="low" fileFormat="3gp" duration="30">
<Video codec="h263"
bitRate="128000"
width="176"
height="144"
frameRate="15" />
<Audio codec="amrnb"
bitRate="12200"
sampleRate="8000"
channels="1" />
</EncoderProfile>
<EncoderProfile quality="qcif" fileFormat="3gp" duration="30">
<Video codec="h263"
bitRate="128000"
width="176"
height="144"
frameRate="15" />
<Audio codec="amrnb"
bitRate="12200"
sampleRate="8000"
channels="1" />
</EncoderProfile>
<EncoderProfile quality="qvga" fileFormat="3gp" duration="30">
<Video codec="h264"
bitRate="640000"
width="320"
height="240"
frameRate="30" />
<Audio codec="aac"
bitRate="128000"
sampleRate="48000"
channels="2" />
</EncoderProfile>
<EncoderProfile quality="cif" fileFormat="3gp" duration="30">
<Video codec="h264"
bitRate="640000"
width="352"
height="288"
frameRate="30" />
<Audio codec="amrnb"
bitRate="12200"
sampleRate="8000"
channels="1" />
</EncoderProfile>
<EncoderProfile quality="480p" fileFormat="mp4" duration="60">
<Video codec="h264"
bitRate="3000000"
width="720"
height="480"
frameRate="30" />
<Audio codec="aac"
bitRate="128000"
sampleRate="48000"
channels="2" />
</EncoderProfile>
<EncoderProfile quality="720p" fileFormat="mp4" duration="60">
<Video codec="h264"
bitRate="3000000"
width="1280"
height="720"
frameRate="30" />
<Audio codec="aac"
bitRate="192000"
sampleRate="48000"
channels="2" />
</EncoderProfile>
<EncoderProfile quality="1080p" fileFormat="mp4" duration="60">
<Video codec="h264"
bitRate="15000000"
width="1920"
height="1080"
frameRate="30" />
<Audio codec="aac"
bitRate="192000"
sampleRate="48000"
channels="2" />
</EncoderProfile>
<EncoderProfile quality="timelapselow" fileFormat="3gp" duration="30">
<Video codec="h263"
bitRate="128000"
width="176"
height="144"
frameRate="15" />
<Audio codec="amrnb"
bitRate="12200"
sampleRate="8000"
channels="1" />
</EncoderProfile>
<EncoderProfile quality="timelapsehigh" fileFormat="mp4" duration="30">
<Video codec="h264"
bitRate="3000000"
width="1920"
height="1080"
frameRate="30" />
<Audio codec="aac"
bitRate="192000"
sampleRate="48000"
channels="2" />
</EncoderProfile>
<EncoderProfile quality="timelapseqcif" fileFormat="3gp" duration="30">
<Video codec="h263"
bitRate="128000"
width="176"
height="144"
frameRate="15" />
<Audio codec="amrnb"
bitRate="12200"
sampleRate="8000"
channels="1" />
</EncoderProfile>
<EncoderProfile quality="timelapsecif" fileFormat="3gp" duration="30">
<Video codec="h264"
bitRate="640000"
width="352"
height="288"
frameRate="30" />
<Audio codec="amrnb"
bitRate="12200"
sampleRate="8000"
channels="1" />
</EncoderProfile>
<EncoderProfile quality="timelapse480p" fileFormat="mp4" duration="30">
<Video codec="h264"
bitRate="3000000"
width="720"
height="480"
frameRate="30" />
<Audio codec="amrnb"
bitRate="12200"
sampleRate="8000"
channels="1" />
</EncoderProfile>
<EncoderProfile quality="timelapse720p" fileFormat="mp4" duration="30">
<Video codec="h264"
bitRate="3000000"
width="1280"
height="720"
frameRate="30" />
<Audio codec="aac"
bitRate="192000"
sampleRate="48000"
channels="2" />
</EncoderProfile>
<EncoderProfile quality="timelapse1080p" fileFormat="mp4" duration="30">
<Video codec="h264"
bitRate="3000000"
width="1920"
height="1080"
frameRate="30" />
<Audio codec="aac"
bitRate="192000"
sampleRate="48000"
channels="2" />
</EncoderProfile>
<ImageEncoding quality="90" />
<ImageEncoding quality="80" />
<ImageEncoding quality="70" />
<ImageDecoding memCap="20000000" />
<Camera previewFrameRate="30" />
</CamcorderProfiles>
<EncoderOutputFileFormat name="3gp" />
<EncoderOutputFileFormat name="mp4" />
<!--
If a codec is not enabled, it is invisible to the applications
In other words, the applications won't be able to use the codec
or query the capabilities of the codec at all if it is disabled
-->
<VideoEncoderCap name="h264" enabled="true"
minBitRate="64000" maxBitRate="15000000"
minFrameWidth="176" maxFrameWidth="1920"
minFrameHeight="144" maxFrameHeight="1080"
minFrameRate="15" maxFrameRate="60" />
<VideoEncoderCap name="h263" enabled="true"
minBitRate="64000" maxBitRate="2000000"
minFrameWidth="176" maxFrameWidth="720"
minFrameHeight="144" maxFrameHeight="480"
minFrameRate="15" maxFrameRate="30" />
<VideoEncoderCap name="m4v" enabled="true"
minBitRate="64000" maxBitRate="8000000"
minFrameWidth="176" maxFrameWidth="720"
minFrameHeight="144" maxFrameHeight="480"
minFrameRate="15" maxFrameRate="30" />
<AudioEncoderCap name="aac" enabled="true"
minBitRate="32000" maxBitRate="320000"
minSampleRate="8000" maxSampleRate="48000"
minChannels="1" maxChannels="2" />
<AudioEncoderCap name="amrwb" enabled="true"
minBitRate="6600" maxBitRate="23850"
minSampleRate="16000" maxSampleRate="16000"
minChannels="1" maxChannels="1" />
<AudioEncoderCap name="amrnb" enabled="true"
minBitRate="4750" maxBitRate="12200"
minSampleRate="8000" maxSampleRate="8000"
minChannels="1" maxChannels="1" />
<AudioEncoderCap name="aac" enabled="true"
minBitRate="32000" maxBitRate="320000"
minSampleRate="8000" maxSampleRate="48000"
minChannels="1" maxChannels="1" />
<AudioEncoderCap name="heaac" enabled="true"
minBitRate="8000" maxBitRate="64000"
minSampleRate="16000" maxSampleRate="48000"
minChannels="1" maxChannels="2" />
<AudioEncoderCap name="aaceld" enabled="true"
minBitRate="16000" maxBitRate="192000"
minSampleRate="8000" maxSampleRate="48000"
minChannels="1" maxChannels="2" />
<!--
FIXME:
We do not check decoder capabilities at present
At present, we only check whether windows media is visible
for TEST applications. For other applications, we do
not perform any checks at all.
-->
<VideoDecoderCap name="wmv" enabled="true"/>
<AudioDecoderCap name="wma" enabled="true"/>
</MediaSettings>

View file

@ -0,0 +1 @@
OMX.Intel.sw_vd.h265 : libmfx_omx_components_sw.so

View file

@ -0,0 +1,140 @@
/**************************************************************************
*
* Copyright 2006-2008 Tungsten Graphics, Inc., Cedar Park, TX., USA
* All Rights Reserved.
* Copyright (c) 2009 VMware, Inc., Palo Alto, CA., USA
* All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
*
**************************************************************************/
/*
* Authors
* Thomas Hellström <thomas-at-tungstengraphics-dot-com>
*/
#ifndef TTM_FENCE_USER_H
#define TTM_FENCE_USER_H
#if !defined(__KERNEL__) && !defined(_KERNEL)
#include <stdint.h>
#endif
#define TTM_FENCE_MAJOR 0
#define TTM_FENCE_MINOR 1
#define TTM_FENCE_PL 0
#define TTM_FENCE_DATE "080819"
/**
* struct ttm_fence_signaled_req
*
* @handle: Handle to the fence object. Input.
*
* @fence_type: Fence types we want to flush. Input.
*
* @flush: Boolean. Flush the indicated fence_types. Input.
*
* Argument to the TTM_FENCE_SIGNALED ioctl.
*/
struct ttm_fence_signaled_req {
uint32_t handle;
uint32_t fence_type;
int32_t flush;
uint32_t pad64;
};
/**
* struct ttm_fence_rep
*
* @signaled_types: Fence type that has signaled.
*
* @fence_error: Command execution error.
* Hardware errors that are consequences of the execution
* of the command stream preceding the fence are reported
* here.
*
* Output argument to the TTM_FENCE_SIGNALED and
* TTM_FENCE_FINISH ioctls.
*/
struct ttm_fence_rep {
uint32_t signaled_types;
uint32_t fence_error;
};
union ttm_fence_signaled_arg {
struct ttm_fence_signaled_req req;
struct ttm_fence_rep rep;
};
/*
* Waiting mode flags for the TTM_FENCE_FINISH ioctl.
*
* TTM_FENCE_FINISH_MODE_LAZY: Allow for sleeps during polling
* wait.
*
* TTM_FENCE_FINISH_MODE_NO_BLOCK: Don't block waiting for GPU,
* but return -EBUSY if the buffer is busy.
*/
#define TTM_FENCE_FINISH_MODE_LAZY (1 << 0)
#define TTM_FENCE_FINISH_MODE_NO_BLOCK (1 << 1)
/**
* struct ttm_fence_finish_req
*
* @handle: Handle to the fence object. Input.
*
* @fence_type: Fence types we want to finish.
*
* @mode: Wait mode.
*
* Input to the TTM_FENCE_FINISH ioctl.
*/
struct ttm_fence_finish_req {
uint32_t handle;
uint32_t fence_type;
uint32_t mode;
uint32_t pad64;
};
union ttm_fence_finish_arg {
struct ttm_fence_finish_req req;
struct ttm_fence_rep rep;
};
/**
* struct ttm_fence_unref_arg
*
* @handle: Handle to the fence object.
*
* Argument to the TTM_FENCE_UNREF ioctl.
*/
struct ttm_fence_unref_arg {
uint32_t handle;
uint32_t pad64;
};
/*
* Ioctl offsets frome extenstion start.
*/
#define TTM_FENCE_SIGNALED 0x01
#define TTM_FENCE_FINISH 0x02
#define TTM_FENCE_UNREF 0x03
#endif

View file

@ -0,0 +1,252 @@
/**************************************************************************
*
* Copyright 2006-2008 Tungsten Graphics, Inc., Cedar Park, TX., USA
* All Rights Reserved.
* Copyright (c) 2009 VMware, Inc., Palo Alto, CA., USA
* All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
*
**************************************************************************/
/*
* Authors
* Thomas Hellström <thomas-at-tungstengraphics-dot-com>
*/
#ifndef _TTM_PLACEMENT_USER_H_
#define _TTM_PLACEMENT_USER_H_
#if !defined(__KERNEL__) && !defined(_KERNEL)
#include <stdint.h>
#else
#include <linux/kernel.h>
#endif
#include "ttm/ttm_placement.h"
#define TTM_PLACEMENT_MAJOR 0
#define TTM_PLACEMENT_MINOR 1
#define TTM_PLACEMENT_PL 0
#define TTM_PLACEMENT_DATE "080819"
/**
* struct ttm_pl_create_req
*
* @size: The buffer object size.
* @placement: Flags that indicate initial acceptable
* placement.
* @page_alignment: Required alignment in pages.
*
* Input to the TTM_BO_CREATE ioctl.
*/
struct ttm_pl_create_req {
uint64_t size;
uint32_t placement;
uint32_t page_alignment;
};
/**
* struct ttm_pl_create_ub_req
*
* @size: The buffer object size.
* @user_address: User-space address of the memory area that
* should be used to back the buffer object cast to 64-bit.
* @placement: Flags that indicate initial acceptable
* placement.
* @page_alignment: Required alignment in pages.
*
* Input to the TTM_BO_CREATE_UB ioctl.
*/
struct ttm_pl_create_ub_req {
uint64_t size;
uint64_t user_address;
uint32_t placement;
uint32_t page_alignment;
};
/**
* struct ttm_pl_rep
*
* @gpu_offset: The current offset into the memory region used.
* This can be used directly by the GPU if there are no
* additional GPU mapping procedures used by the driver.
*
* @bo_size: Actual buffer object size.
*
* @map_handle: Offset into the device address space.
* Used for map, seek, read, write. This will never change
* during the lifetime of an object.
*
* @placement: Flag indicating the placement status of
* the buffer object using the TTM_PL flags above.
*
* @sync_object_arg: Used for user-space synchronization and
* depends on the synchronization model used. If fences are
* used, this is the buffer_object::fence_type_mask
*
* Output from the TTM_PL_CREATE and TTM_PL_REFERENCE, and
* TTM_PL_SETSTATUS ioctls.
*/
struct ttm_pl_rep {
uint64_t gpu_offset;
uint64_t bo_size;
uint64_t map_handle;
uint32_t placement;
uint32_t handle;
uint32_t sync_object_arg;
uint32_t pad64;
};
/**
* struct ttm_pl_setstatus_req
*
* @set_placement: Placement flags to set.
*
* @clr_placement: Placement flags to clear.
*
* @handle: The object handle
*
* Input to the TTM_PL_SETSTATUS ioctl.
*/
struct ttm_pl_setstatus_req {
uint32_t set_placement;
uint32_t clr_placement;
uint32_t handle;
uint32_t pad64;
};
/**
* struct ttm_pl_reference_req
*
* @handle: The object to put a reference on.
*
* Input to the TTM_PL_REFERENCE and the TTM_PL_UNREFERENCE ioctls.
*/
struct ttm_pl_reference_req {
uint32_t handle;
uint32_t pad64;
};
/*
* ACCESS mode flags for SYNCCPU.
*
* TTM_SYNCCPU_MODE_READ will guarantee that the GPU is not
* writing to the buffer.
*
* TTM_SYNCCPU_MODE_WRITE will guarantee that the GPU is not
* accessing the buffer.
*
* TTM_SYNCCPU_MODE_NO_BLOCK makes sure the call does not wait
* for GPU accesses to finish but return -EBUSY.
*
* TTM_SYNCCPU_MODE_TRYCACHED Try to place the buffer in cacheable
* memory while synchronized for CPU.
*/
#define TTM_PL_SYNCCPU_MODE_READ TTM_ACCESS_READ
#define TTM_PL_SYNCCPU_MODE_WRITE TTM_ACCESS_WRITE
#define TTM_PL_SYNCCPU_MODE_NO_BLOCK (1 << 2)
#define TTM_PL_SYNCCPU_MODE_TRYCACHED (1 << 3)
/**
* struct ttm_pl_synccpu_arg
*
* @handle: The object to synchronize.
*
* @access_mode: access mode indicated by the
* TTM_SYNCCPU_MODE flags.
*
* @op: indicates whether to grab or release the
* buffer for cpu usage.
*
* Input to the TTM_PL_SYNCCPU ioctl.
*/
struct ttm_pl_synccpu_arg {
uint32_t handle;
uint32_t access_mode;
enum {
TTM_PL_SYNCCPU_OP_GRAB,
TTM_PL_SYNCCPU_OP_RELEASE
} op;
uint32_t pad64;
};
/*
* Waiting mode flags for the TTM_BO_WAITIDLE ioctl.
*
* TTM_WAITIDLE_MODE_LAZY: Allow for sleeps during polling
* wait.
*
* TTM_WAITIDLE_MODE_NO_BLOCK: Don't block waiting for GPU,
* but return -EBUSY if the buffer is busy.
*/
#define TTM_PL_WAITIDLE_MODE_LAZY (1 << 0)
#define TTM_PL_WAITIDLE_MODE_NO_BLOCK (1 << 1)
/**
* struct ttm_waitidle_arg
*
* @handle: The object to synchronize.
*
* @mode: wait mode indicated by the
* TTM_SYNCCPU_MODE flags.
*
* Argument to the TTM_BO_WAITIDLE ioctl.
*/
struct ttm_pl_waitidle_arg {
uint32_t handle;
uint32_t mode;
};
union ttm_pl_create_arg {
struct ttm_pl_create_req req;
struct ttm_pl_rep rep;
};
union ttm_pl_reference_arg {
struct ttm_pl_reference_req req;
struct ttm_pl_rep rep;
};
union ttm_pl_setstatus_arg {
struct ttm_pl_setstatus_req req;
struct ttm_pl_rep rep;
};
union ttm_pl_create_ub_arg {
struct ttm_pl_create_ub_req req;
struct ttm_pl_rep rep;
};
/*
* Ioctl offsets.
*/
#define TTM_PL_CREATE 0x00
#define TTM_PL_REFERENCE 0x01
#define TTM_PL_UNREF 0x02
#define TTM_PL_SYNCCPU 0x03
#define TTM_PL_WAITIDLE 0x04
#define TTM_PL_SETSTATUS 0x05
#define TTM_PL_CREATE_UB 0x06
#endif

View file

@ -0,0 +1,92 @@
/**************************************************************************
*
* Copyright (c) 2006-2009 VMware, Inc., Palo Alto, CA., USA
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
/*
* Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com>
*/
#ifndef _TTM_PLACEMENT_H_
#define _TTM_PLACEMENT_H_
/*
* Memory regions for data placement.
*/
#define TTM_PL_SYSTEM 0
#define TTM_PL_TT 1
#define TTM_PL_VRAM 2
#define TTM_PL_PRIV0 3
#define TTM_PL_PRIV1 4
#define TTM_PL_PRIV2 5
#define TTM_PL_PRIV3 6
#define TTM_PL_PRIV4 7
#define TTM_PL_PRIV5 8
#define TTM_PL_SWAPPED 15
#define TTM_PL_FLAG_SYSTEM (1 << TTM_PL_SYSTEM)
#define TTM_PL_FLAG_TT (1 << TTM_PL_TT)
#define TTM_PL_FLAG_VRAM (1 << TTM_PL_VRAM)
#define TTM_PL_FLAG_PRIV0 (1 << TTM_PL_PRIV0)
#define TTM_PL_FLAG_PRIV1 (1 << TTM_PL_PRIV1)
#define TTM_PL_FLAG_PRIV2 (1 << TTM_PL_PRIV2)
#define TTM_PL_FLAG_PRIV3 (1 << TTM_PL_PRIV3)
#define TTM_PL_FLAG_PRIV4 (1 << TTM_PL_PRIV4)
#define TTM_PL_FLAG_PRIV5 (1 << TTM_PL_PRIV5)
#define TTM_PL_FLAG_SWAPPED (1 << TTM_PL_SWAPPED)
#define TTM_PL_MASK_MEM 0x0000FFFF
/*
* Other flags that affects data placement.
* TTM_PL_FLAG_CACHED indicates cache-coherent mappings
* if available.
* TTM_PL_FLAG_SHARED means that another application may
* reference the buffer.
* TTM_PL_FLAG_NO_EVICT means that the buffer may never
* be evicted to make room for other buffers.
*/
#define TTM_PL_FLAG_CACHED (1 << 16)
#define TTM_PL_FLAG_UNCACHED (1 << 17)
#define TTM_PL_FLAG_WC (1 << 18)
#define TTM_PL_FLAG_SHARED (1 << 20)
#define TTM_PL_FLAG_NO_EVICT (1 << 21)
#define TTM_PL_MASK_CACHING (TTM_PL_FLAG_CACHED | \
TTM_PL_FLAG_UNCACHED | \
TTM_PL_FLAG_WC)
#define TTM_PL_MASK_MEMTYPE (TTM_PL_MASK_MEM | TTM_PL_MASK_CACHING)
/*
* Access flags to be used for CPU- and GPU- mappings.
* The idea is that the TTM synchronization mechanism will
* allow concurrent READ access and exclusive write access.
* Currently GPU- and CPU accesses are exclusive.
*/
#define TTM_ACCESS_READ (1 << 0)
#define TTM_ACCESS_WRITE (1 << 1)
#endif

View file

@ -0,0 +1,282 @@
#ifndef KCT_H_
# define KCT_H_
# include <linux/netlink.h>
/*
* warning: structures and constants in this header must match the
* ones in libc/kernel/common/linux/kct.h, so that information can
* be exchange between kernel and userspace throught netlink socket.
*/
/* flags to optionally filter events on android property activation */
#define EV_FLAGS_PRIORITY_LOW (1<<0)
# ifndef MAX_SB_N
# define MAX_SB_N 32
# endif
# ifndef MAX_EV_N
# define MAX_EV_N 32
# endif
# define NETLINK_CRASHTOOL 27
# define ATTCHMT_ALIGN 4U
/* Type of events supported by crashtool */
enum ct_ev_type {
CT_EV_STAT,
CT_EV_INFO,
CT_EV_ERROR,
CT_EV_CRASH,
CT_EV_LAST
};
enum ct_attchmt_type {
CT_ATTCHMT_DATA0,
CT_ATTCHMT_DATA1,
CT_ATTCHMT_DATA2,
CT_ATTCHMT_DATA3,
CT_ATTCHMT_DATA4,
CT_ATTCHMT_DATA5,
/* Always add new types after DATA5 */
CT_ATTCHMT_BINARY,
CT_ATTCHMT_FILELIST
};
struct ct_attchmt {
__u32 size; /* sizeof(data) */
enum ct_attchmt_type type;
char data[];
} __aligned(4);
struct ct_event {
__u64 timestamp;
char submitter_name[MAX_SB_N];
char ev_name[MAX_EV_N];
enum ct_ev_type type;
__u32 attchmt_size; /* sizeof(all_attachments inc. padding) */
__u32 flags;
struct ct_attchmt attachments[];
} __aligned(4);
enum kct_nlmsg_type {
/* kernel -> userland */
KCT_EVENT,
/* userland -> kernel */
KCT_SET_PID = 4200,
};
struct kct_packet {
struct nlmsghdr nlh;
struct ct_event event;
};
# define ATTCHMT_ALIGNMENT 4
# ifndef KCT_ALIGN
# define __KCT_ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask))
# define __KCT_ALIGN(x, a) __KCT_ALIGN_MASK(x, (typeof(x))(a) - 1)
# define KCT_ALIGN(x, a) __KCT_ALIGN((x), (a))
# endif /* !KCT_ALIGN */
# define foreach_attchmt(Event, Attchmt) \
if ((Event)->attchmt_size) \
for ((Attchmt) = (Event)->attachments; \
(Attchmt) < (typeof(Attchmt))(((char *) \
(Event)->attachments) + \
(Event)->attchmt_size); \
(Attchmt) = (typeof(Attchmt))KCT_ALIGN(((size_t)(Attchmt)) \
+ sizeof(*(Attchmt)) + \
(Attchmt)->size, ATTCHMT_ALIGNMENT))
/*
* User should use the macros below rather than those extern functions
* directly. Laters' declaration are only to set them __weak so
* that the macros works fine.
*/
/* Raw API (deprecated) */
extern struct ct_event *kct_alloc_event(const char *submitter_name,
const char *ev_name,
enum ct_ev_type ev_type,
gfp_t flags, uint eflags) __weak;
extern int kct_add_attchmt(struct ct_event **ev,
enum ct_attchmt_type at_type,
unsigned int size,
char *data, gfp_t flags) __weak;
extern void kct_free_event(struct ct_event *ev) __weak;
extern int kct_log_event(struct ct_event *ev, gfp_t flags) __weak;
/* API */
#define MKFN(fn, ...) MKFN_N(fn, ##__VA_ARGS__, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)(__VA_ARGS__)
#define MKFN_N(fn, n0, n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n, ...) fn##n
#define kct_log(...) MKFN(__kct_log_, ##__VA_ARGS__)
#define __kct_log_4(Type, Submitter_name, Ev_name, flags) \
do { if (kct_alloc_event) { \
struct ct_event *__ev = \
kct_alloc_event(Submitter_name, Ev_name, Type, \
GFP_ATOMIC, flags); \
if (__ev) { \
kct_log_event(__ev, GFP_ATOMIC); \
} \
} } while (0)
#define __kct_log_5(Type, Submitter_name, Ev_name, flags, Data0) \
do { if (kct_alloc_event) { \
struct ct_event *__ev = \
kct_alloc_event(Submitter_name, Ev_name, Type, \
GFP_ATOMIC, flags); \
if (__ev) { \
if (Data0) \
kct_add_attchmt(&__ev, CT_ATTCHMT_DATA0, \
strlen(Data0) + 1, Data0, GFP_ATOMIC); \
kct_log_event(__ev, GFP_ATOMIC); \
} \
} } while (0)
#define __kct_log_6(Type, Submitter_name, Ev_name, flags, Data0, Data1) \
do { if (kct_alloc_event) { \
struct ct_event *__ev = \
kct_alloc_event(Submitter_name, Ev_name, Type, \
GFP_ATOMIC, flags); \
if (__ev) { \
if (Data0) \
kct_add_attchmt(&__ev, CT_ATTCHMT_DATA0, \
strlen(Data0) + 1, Data0, GFP_ATOMIC); \
if (Data1) \
kct_add_attchmt(&__ev, CT_ATTCHMT_DATA1, \
strlen(Data1) + 1, Data1, GFP_ATOMIC); \
kct_log_event(__ev, GFP_ATOMIC); \
} \
} } while (0)
#define __kct_log_7(Type, Submitter_name, Ev_name, flags, Data0, Data1, Data2) \
do { if (kct_alloc_event) { \
struct ct_event *__ev = \
kct_alloc_event(Submitter_name, Ev_name, Type, \
GFP_ATOMIC, flags); \
if (__ev) { \
if (Data0) \
kct_add_attchmt(&__ev, CT_ATTCHMT_DATA0, \
strlen(Data0) + 1, Data0, GFP_ATOMIC); \
if (Data1) \
kct_add_attchmt(&__ev, CT_ATTCHMT_DATA1, \
strlen(Data1) + 1, Data1, GFP_ATOMIC); \
if (Data2) \
kct_add_attchmt(&__ev, CT_ATTCHMT_DATA2, \
strlen(Data2) + 1, Data2, GFP_ATOMIC); \
kct_log_event(__ev, GFP_ATOMIC); \
} \
} } while (0)
#define __kct_log_8(Type, Submitter_name, Ev_name, flags, Data0, Data1, Data2, \
Data3) \
do { if (kct_alloc_event) { \
struct ct_event *__ev = \
kct_alloc_event(Submitter_name, Ev_name, Type, \
GFP_ATOMIC, flags); \
if (__ev) { \
if (Data0) \
kct_add_attchmt(&__ev, CT_ATTCHMT_DATA0, \
strlen(Data0) + 1, Data0, GFP_ATOMIC); \
if (Data1) \
kct_add_attchmt(&__ev, CT_ATTCHMT_DATA1, \
strlen(Data1) + 1, Data1, GFP_ATOMIC); \
if (Data2) \
kct_add_attchmt(&__ev, CT_ATTCHMT_DATA2, \
strlen(Data2) + 1, Data2, GFP_ATOMIC); \
if (Data3) \
kct_add_attchmt(&__ev, CT_ATTCHMT_DATA3, \
strlen(Data3) + 1, Data3, GFP_ATOMIC); \
kct_log_event(__ev, GFP_ATOMIC); \
} \
} } while (0)
#define __kct_log_9(Type, Submitter_name, Ev_name, flags, Data0, Data1, Data2, \
Data3, Data4) \
do { if (kct_alloc_event) { \
struct ct_event *__ev = \
kct_alloc_event(Submitter_name, Ev_name, Type, \
GFP_ATOMIC, flags); \
if (__ev) { \
if (Data0) \
kct_add_attchmt(&__ev, CT_ATTCHMT_DATA0, \
strlen(Data0) + 1, Data0, GFP_ATOMIC); \
if (Data1) \
kct_add_attchmt(&__ev, CT_ATTCHMT_DATA1, \
strlen(Data1) + 1, Data1, GFP_ATOMIC); \
if (Data2) \
kct_add_attchmt(&__ev, CT_ATTCHMT_DATA2, \
strlen(Data2) + 1, Data2, GFP_ATOMIC); \
if (Data3) \
kct_add_attchmt(&__ev, CT_ATTCHMT_DATA3, \
strlen(Data3) + 1, Data3, GFP_ATOMIC); \
if (Data4) \
kct_add_attchmt(&__ev, CT_ATTCHMT_DATA4, \
strlen(Data4) + 1, Data4, GFP_ATOMIC); \
kct_log_event(__ev, GFP_ATOMIC); \
} \
} } while (0)
#define __kct_log_10(Type, Submitter_name, Ev_name, flags, Data0, Data1, Data2, \
Data3, Data4, Data5) \
do { if (kct_alloc_event) { \
struct ct_event *__ev = \
kct_alloc_event(Submitter_name, Ev_name, Type, \
GFP_ATOMIC, flags); \
if (__ev) { \
if (Data0) \
kct_add_attchmt(&__ev, CT_ATTCHMT_DATA0, \
strlen(Data0) + 1, Data0, GFP_ATOMIC); \
if (Data1) \
kct_add_attchmt(&__ev, CT_ATTCHMT_DATA1, \
strlen(Data1) + 1, Data1, GFP_ATOMIC); \
if (Data2) \
kct_add_attchmt(&__ev, CT_ATTCHMT_DATA2, \
strlen(Data2) + 1, Data2, GFP_ATOMIC); \
if (Data3) \
kct_add_attchmt(&__ev, CT_ATTCHMT_DATA3, \
strlen(Data3) + 1, Data3, GFP_ATOMIC); \
if (Data4) \
kct_add_attchmt(&__ev, CT_ATTCHMT_DATA4, \
strlen(Data4) + 1, Data4, GFP_ATOMIC); \
if (Data5) \
kct_add_attchmt(&__ev, CT_ATTCHMT_DATA5, \
strlen(Data5) + 1, Data5, GFP_ATOMIC); \
kct_log_event(__ev, GFP_ATOMIC); \
} \
} } while (0)
#define __kct_log_11(Type, Submitter_name, Ev_name, flags, Data0, Data1, Data2, \
Data3, Data4, Data5, filelist) \
do { if (kct_alloc_event) { \
struct ct_event *__ev = \
kct_alloc_event(Submitter_name, Ev_name, Type, \
GFP_ATOMIC, flags); \
if (__ev) { \
if (Data0) \
kct_add_attchmt(&__ev, CT_ATTCHMT_DATA0, \
strlen(Data0) + 1, Data0, GFP_ATOMIC); \
if (Data1) \
kct_add_attchmt(&__ev, CT_ATTCHMT_DATA1, \
strlen(Data1) + 1, Data1, GFP_ATOMIC); \
if (Data2) \
kct_add_attchmt(&__ev, CT_ATTCHMT_DATA2, \
strlen(Data2) + 1, Data2, GFP_ATOMIC); \
if (Data3) \
kct_add_attchmt(&__ev, CT_ATTCHMT_DATA3, \
strlen(Data3) + 1, Data3, GFP_ATOMIC); \
if (Data4) \
kct_add_attchmt(&__ev, CT_ATTCHMT_DATA4, \
strlen(Data4) + 1, Data4, GFP_ATOMIC); \
if (Data5) \
kct_add_attchmt(&__ev, CT_ATTCHMT_DATA5, \
strlen(Data5) + 1, Data5, GFP_ATOMIC); \
if (filelist) \
kct_add_attchmt(&__ev, CT_ATTCHMT_FILELIST, \
strlen(filelist) + 1, filelist, GFP_ATOMIC); \
kct_log_event(__ev, GFP_ATOMIC); \
} \
} } while (0)
#endif /* !KCT_H_ */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,63 @@
#ifndef __INTEL_SST_IOCTL_H__
#define __INTEL_SST_IOCTL_H__
/*
* intel_sst_ioctl.h - Intel SST Driver for audio engine
*
* Copyright (C) 2008-10 Intel Corporation
* Authors: Vinod Koul <vinod.koul@intel.com>
* Harsha Priya <priya.harsha@intel.com>
* Dharageswari R <dharageswari.r@intel.com>
* KP Jeeja <jeeja.kp@intel.com>
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* This file defines all sst ioctls
*/
/* codec and post/pre processing related info */
#include <linux/types.h>
/* Pre and post processing params structure */
struct snd_ppp_params {
__u8 algo_id;/* Post/Pre processing algorithm ID */
__u8 str_id; /*Only 5 bits used 0 - 31 are valid*/
__u8 enable; /* 0= disable, 1= enable*/
__u8 operation; /* 0 = set_algo, 1 = get_algo */
__u32 size; /*Size of parameters for all blocks*/
void *params;
} __packed;
struct snd_sst_driver_info {
__u32 max_streams;
};
struct snd_sst_tuning_params {
__u8 type;
__u8 str_id;
__u8 size;
__u8 rsvd;
__u64 addr;
} __packed;
/*IOCTL defined here */
/*SST common ioctls */
#define SNDRV_SST_DRIVER_INFO _IOR('L', 0x10, struct snd_sst_driver_info)
#define SNDRV_SST_SET_ALGO _IOW('L', 0x30, struct snd_ppp_params)
#define SNDRV_SST_GET_ALGO _IOWR('L', 0x31, struct snd_ppp_params)
#define SNDRV_SST_TUNING_PARAMS _IOW('L', 0x32, struct snd_sst_tuning_params)
#endif /* __INTEL_SST_IOCTL_H__ */

View file

@ -0,0 +1,10 @@
<resources>
<!-- Control the behavior when the user long presses the home button.
0 - Nothing
1 - Launch all apps intent
2 - Launch assist intent
This needs to match the constants in
policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
-->
<integer name="config_longPressOnHomeBehavior">1</integer>
</resources>

View file

@ -0,0 +1,65 @@
<resources>
<!-- Don't allow volume change on the device. -->
<bool name="config_useFixedVolume">true</bool>
<!-- Control the behavior when the user long presses the home button.
0 - Nothing
1 - Launch all apps intent
2 - Launch assist intent
This needs to match the constants in
policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
-->
<integer name="config_longPressOnHomeBehavior">1</integer>
<!-- Supports MS PlayReady in Chromium WebView -->
<string-array name="config_keySystemUuidMapping" translatable="false">
<item>"x-com.microsoft.playready,9A04F079-9840-4286-AB92-E65BE0885F95"</item>
</string-array>
<!-- This string array should be overridden by the device to present a list of network
attributes. This is used by the connectivity manager to decide which networks can coexist
based on the hardware -->
<!-- An Array of "[Connection name],[ConnectivityManager.TYPE_xxxx],
[associated radio-type],[priority],[restoral-timer(ms)],[dependencyMet] -->
<!-- the 5th element "restore-time" indicates the number of milliseconds to delay
before automatically restore the default connection. Set -1 if the connection
does not require auto-restore. -->
<!-- the 6th element indicates boot-time dependency-met value. -->
<string-array translatable="false" name="networkAttributes">
<item>"wifi,1,1,1,-1,true"</item>
<item>"ethernet,9,9,9,-1,true"</item>
</string-array>
<!-- This string array should be overridden by the device to present a list of radio
attributes. This is used by the connectivity manager to decide which networks can coexist
based on the hardware -->
<!-- An Array of "[ConnectivityManager connectionType],
[# simultaneous connection types]" -->
<string-array translatable="false" name="radioAttributes">
<item>"1,1"</item>
<item>"9,1"</item>
</string-array>
<bool name="config_ui_enableFadingMarquee">true</bool>
<!-- Device configuration adjusting the minfree tunable in the lowmemorykiller in the
kernel. A high value will cause the lowmemorykiller to fire earlier, keeping more
memory in the file cache and preventing I/O thrashing, but allowing fewer processes
to stay in memory. A low value will keep more processes in memory but may cause
thrashing if set too low. Directly added to the default value chosen by
ActivityManager based on screen size and total memory for the largest lowmemorykiller
bucket, and scaled proportionally to the smaller buckets. 0 keeps the default.
Below will adj 6 minfree buckets (in MB) to: 32, 40, 48, 56, 64, 80 -->
<integer name="config_lowMemoryKillerMinFreeKbytesAbsolute">81920</integer>
<!-- Number of times to try again with the shorter interval, before backing
off until the normal polling interval. A value < 0 indicates infinite. -->
<integer name="config_ntpRetry">-1</integer>
<!-- Flag indicating if device supports EAP SIM, AKA, AKA' -->
<bool name="config_eap_sim_based_auth_supported">false</bool>
<!-- Package of the unbundled tv remote service which can connect to tv remote provider -->
<string translatable="false" name="config_tvRemoteServicePackage">com.google.android.tv.remote.service</string>
</resources>

View file

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
** Copyright 2013, 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.
*/
-->
<!-- Mapping of keycodes to components which will be handled globally.
Modify this file to add global keys.
The key will NOT go to the foreground application and instead only ever be sent via targeted
broadcast to the specified component. The action of the intent will be
android.intent.action.GLOBAL_BUTTON and the KeyEvent will be included in the intent as
android.intent.extra.KEY_EVENT.
-->
<global_keys version="1">
<!-- Example format: id = keycode to handle globally. component = component which will handle this key. -->
<key keyCode="KEYCODE_GUIDE" component="com.google.android.tv/.receiver.GlobalKeyReceiver" />
<key keyCode="KEYCODE_TV" component="com.google.android.tv/.receiver.GlobalKeyReceiver" />
<key keyCode="KEYCODE_TV_INPUT" component="com.google.android.tv/.receiver.GlobalKeyReceiver" />
<key keyCode="KEYCODE_TV_POWER" component="com.google.android.athome.globalkeyinterceptor/.Receiver" />
<key keyCode="KEYCODE_VOLUME_UP" component="com.google.android.athome.globalkeyinterceptor/.Receiver" />
<key keyCode="KEYCODE_VOLUME_DOWN" component="com.google.android.athome.globalkeyinterceptor/.Receiver" />
<key keyCode="KEYCODE_PAIRING" component="com.google.android.athome.globalkeyinterceptor/.Receiver" />
</global_keys>

View file

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
**
** Copyright 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.
*/
-->
<!-- See storage config details at http://source.android.com/tech/storage/ -->
<StorageList xmlns:android="http://schemas.android.com/apk/res/android">
<!-- removable is not set in nosdcard product -->
<storage
android:storageDescription="@string/storage_internal"
android:primary="true"
android:emulated="true"
android:mtpReserve="100"/>
</StorageList>

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="def_backup_enabled">false</bool>
<string name="def_backup_transport">com.google.android.backup/.BackupTransportService</string>
<bool name="def_wifi_on">true</bool>
<bool name="def_bluetooth_on">true</bool>
</resources>

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="config_enableKeyguardService">false</bool>
</resources>

View file

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2009-2012 Broadcom Corporation
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.
-->
<resources>
<bool name="profile_supported_pbap">false</bool>
<bool name="profile_supported_map">false</bool>
<bool name="profile_supported_opp">false</bool>
<string name="pairing_ui_package">com.android.tv.settings</string>
</resources>

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string-array name="controller_names" translatable="false">
<item>ASUS Gamepad</item>
<item>Nexus Remote</item>
<item>Gamepad</item>
<item>Spike</item>
</string-array>
</resources>

View file

@ -0,0 +1,15 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := power.$(TARGET_DEVICE)
LOCAL_MODULE_RELATIVE_PATH := hw
LOCAL_SRC_FILES := power.c
LOCAL_CFLAGS := -Werror
LOCAL_SHARED_LIBRARIES := liblog
LOCAL_MODULE_TAGS := optional
# power.c uses of GNU old-style field designator extension
LOCAL_CLANG_CFLAGS += -Wno-gnu-designator
include $(BUILD_SHARED_LIBRARY)

View file

@ -0,0 +1,188 @@
/*
* Copyright (c) 2014 Intel Corporation All Rights Reserved
* Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
//#define LOG_NDEBUG 0
#define LOG_TAG "IntelPowerHAL"
#include <utils/Log.h>
#include <hardware/hardware.h>
#include <hardware/power.h>
#define BOOST_PULSE_SYSFS "/sys/devices/system/cpu/cpufreq/interactive/boostpulse"
#define BOOST_FREQ_SYSFS "/sys/devices/system/cpu/cpufreq/interactive/hispeed_freq"
#define BOOST_DURATION_SYSFS "/sys/devices/system/cpu/cpufreq/interactive/boostpulse_duration"
struct intel_power_module {
struct power_module container;
uint32_t pulse_duration;
struct timespec last_boost_time; /* latest POWER_HINT_INTERACTION boost */
};
static ssize_t sysfs_write(char *path, char *s)
{
char buf[80];
ssize_t len;
int fd = open(path, O_WRONLY);
if (fd < 0) {
strerror_r(errno, buf, sizeof(buf));
ALOGE("Error opening %s: %s\n", path, buf);
return -1;
}
if ((len = write(fd, s, strlen(s))) < 0) {
strerror_r(errno, buf, sizeof(buf));
ALOGE("Error writing to %s: %s\n", path, buf);
}
close(fd);
ALOGV("wrote '%s' to %s", s, path);
return len;
}
static ssize_t sysfs_read(char *path, char *s, int num_bytes)
{
char buf[80];
ssize_t count;
int fd = open(path, O_RDONLY);
if (fd < 0) {
strerror_r(errno, buf, sizeof(buf));
ALOGE("Error reading from %s: %s\n", path, buf);
return -1;
}
if ((count = read(fd, s, (num_bytes - 1))) < 0) {
strerror_r(errno, buf, sizeof(buf));
ALOGE("Error reading from %s: %s\n", path, buf);
} else {
if ((count >= 1) && (s[count-1] == '\n')) {
s[count-1] = '\0';
} else {
s[count] = '\0';
}
}
close(fd);
ALOGV("read '%s' from %s", s, path);
return count;
}
static void fugu_power_init(struct power_module *module)
{
struct intel_power_module *mod = (struct intel_power_module *) module;
char boost_freq[32];
char boostpulse_duration[32];
/* Keep default boost_freq for fugu => max freq */
if (sysfs_read(BOOST_FREQ_SYSFS, boost_freq, 32) < 0) {
strcpy(boost_freq, "?");
}
if (sysfs_read(BOOST_DURATION_SYSFS, boostpulse_duration, 32) < 0) {
/* above should not fail but just in case it does use an arbitrary 20ms value */
snprintf(boostpulse_duration, 32, "%d", 20000);
}
mod->pulse_duration = atoi(boostpulse_duration);
/* initialize last_boost_time */
clock_gettime(CLOCK_MONOTONIC, &mod->last_boost_time);
ALOGI("init done: will boost CPU to %skHz for %dus on input events",
boost_freq, mod->pulse_duration);
}
static void fugu_power_set_interactive(struct power_module *module, int on)
{
ALOGI("setInteractive: on=%d", on);
(void) module; /* unused */
(void) on; /* unused */
}
static inline void timespec_sub(struct timespec *res, struct timespec *a, struct timespec *b)
{
res->tv_sec = a->tv_sec - b->tv_sec;
if (a->tv_sec >= b->tv_sec) {
res->tv_nsec = a->tv_nsec - b->tv_nsec;
} else {
res->tv_nsec = 1000000000 - b->tv_nsec + a->tv_nsec;
res->tv_sec--;
}
}
static inline uint64_t timespec_to_us(struct timespec *t)
{
return t->tv_sec * 1000000 + t->tv_nsec / 1000;
}
static void fugu_power_hint(struct power_module *module, power_hint_t hint, void *data)
{
struct intel_power_module *mod = (struct intel_power_module *) module;
struct timespec curr_time;
struct timespec diff_time;
uint64_t diff;
(void) data;
switch (hint) {
case POWER_HINT_INTERACTION:
clock_gettime(CLOCK_MONOTONIC, &curr_time);
timespec_sub(&diff_time, &curr_time, &mod->last_boost_time);
diff = timespec_to_us(&diff_time);
ALOGV("POWER_HINT_INTERACTION: diff=%llu", diff);
if (diff > mod->pulse_duration) {
sysfs_write(BOOST_PULSE_SYSFS, "1");
mod->last_boost_time = curr_time;
}
break;
case POWER_HINT_VSYNC:
break;
default:
break;
}
}
static struct hw_module_methods_t power_module_methods = {
.open = NULL,
};
struct intel_power_module HAL_MODULE_INFO_SYM = {
container:{
common: {
tag: HARDWARE_MODULE_TAG,
module_api_version: POWER_MODULE_API_VERSION_0_2,
hal_api_version: HARDWARE_HAL_API_VERSION,
id: POWER_HARDWARE_MODULE_ID,
name: "Fugu Power HAL",
author: "Intel",
methods: &power_module_methods,
},
init: fugu_power_init,
setInteractive: fugu_power_set_interactive,
powerHint: fugu_power_hint,
},
};

View file

@ -0,0 +1,8 @@
[default]
RsRecompileThreads=1
[com.google.earth]
AdjustShaderPrecision=0xFFFFFFFF
[com.android.chrome]
AdjustShaderPrecision=0xFFFFFFFF

View file

@ -0,0 +1,239 @@
# 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.
# This file is generated by device/common/generate-blob-lists.sh - DO NOT EDIT
/system/bin/BtFwLoader
/system/bin/houdini
/system/bin/teeprov
/system/etc/binfmt_misc/arm_dyn
/system/etc/binfmt_misc/arm_exe
/system/etc/binfmt_misc/disable
/system/etc/firmware/IT8566_CEC.BIN
/system/etc/firmware/msvdx.bin.0008.0000.0000
/system/etc/firmware/msvdx.bin.0008.0000.0001
/system/etc/firmware/msvdx.bin.0008.0000.0002
/system/etc/firmware/msvdx.bin.0008.0002.0001
/system/etc/firmware/msvdx.bin.000c.0001.0001
/system/etc/firmware/topaz.bin.0008.0000.0000
/system/etc/firmware/topaz.bin.0008.0000.0001
/system/etc/firmware/topaz.bin.0008.0000.0002
/system/etc/firmware/topaz.bin.0008.0002.0001
/system/etc/firmware/topaz.bin.000c.0001.0001
/system/etc/firmware/vsp.bin.0008.0000.0000
/system/etc/firmware/vsp.bin.0008.0000.0001
/system/etc/firmware/vsp.bin.0008.0000.0002
/system/etc/firmware/vsp.bin.0008.0002.0001
/system/etc/firmware/vsp.bin.000c.0001.0001
/system/etc/vp9_interpredict.binary
/system/etc/wifi/bcmdhd.cal
/system/etc/wifi/bcmdhd_sr2.cal
/system/lib/arm/cpuinfo
/system/lib/arm/libandroidfw.so
/system/lib/arm/libandroid_runtime.so
/system/lib/arm/libandroid.so
/system/lib/arm/libart.so
/system/lib/arm/libaudioflinger.so
/system/lib/arm/libaudiospdif.so
/system/lib/arm/libaudioutils.so
/system/lib/arm/libbacktrace.so
/system/lib/arm/libbase.so
/system/lib/libbcc.so
/system/lib/arm/libbcinfo.so
/system/lib/arm/libbinder.so
/system/lib/arm/libblas.so
/system/lib/arm/libcamera2ndk.so
/system/lib/arm/libcamera_client.so
/system/lib/arm/libcamera_metadata.so
/system/lib/libcommon_time_client.so
/system/lib/arm/libcompiler_rt.so
/system/lib/arm/libcrypto.so
/system/lib/arm/libc.so
/system/lib/arm/libc++.so
/system/lib/arm/libcutils.so
/system/lib/arm/libdl.so
/system/lib/arm/libdng_sdk.so
/system/lib/arm/libdrmframework.so
/system/vendor/lib/libeffects.so
/system/lib/arm/libEGL.so
/system/lib/arm/libETC1.so
/system/lib/arm/libexpat.so
/system/lib/libFFTEm.so
/system/lib/libfilterfw.so
/system/lib/libfilterpack_imageproc.so
/system/lib/arm/libft2.so
/system/lib/arm/libGLESv1_CM.so
/system/lib/arm/libGLESv2.so
/system/lib/arm/libGLESv3.so
/system/lib/arm/libgui.so
/system/lib/arm/libhardware.so
/system/lib/arm/libharfbuzz_ng.so
/system/lib/arm/libhwui.so
/system/lib/arm/libicui18n.so
/system/lib/arm/libicuuc.so
/system/lib/arm/libimg_utils.so
/system/lib/libinputflinger.so
/system/lib/arm/libinput.so
/system/lib/arm/libjnigraphics.so
/system/lib/arm/libjpeg.so
/system/lib/libLLVM.so
/system/lib/arm/liblog.so
/system/lib/arm/liblz4.so
/system/lib/arm/liblzma.so
/system/lib/arm/libmediandk.so
/system/lib/arm/libmedia.so
/system/lib/arm/libmediautils.so
/system/lib/arm/libmemtrack.so
/system/lib/arm/libmemunreachable.so
/system/lib/arm/libminikin.so
/system/lib/arm/libm.so
/system/lib/arm/libnativebridge.so
/system/lib/arm/libnativehelper.so
/system/lib/arm/libnativeloader.so
/system/lib/arm/libnbaio.so
/system/lib/arm/libnetd_client.so
/system/lib/libnetutils.so
/system/lib/libnl.so
/system/lib/arm/libOpenMAXAL.so
/system/lib/arm/libOpenSLES.so
/system/lib/libopus.so
/system/lib/arm/libpackagelistparser.so
/system/lib/arm/libpdfium.so
/system/lib/arm/libpiex.so
/system/lib/arm/libpixelflinger.so
/system/lib/arm/libpng.so
/system/lib/arm/libpowermanager.so
/system/lib/arm/libprocessgroup.so
/system/lib/arm/libprotobuf-cpp-lite.so
/system/lib/arm/libradio_metadata.so
/system/lib/arm/libRScpp.so
/system/lib/arm/libRSCpuRef.so
/system/lib/arm/libRSDriver.so
/system/lib/arm/libRS.so
/system/lib/arm/libselinux.so
/system/lib/arm/libserviceutility.so
/system/lib/arm/libsigchain.so
/system/lib/arm/libskia.so
/system/lib/arm/libsonic.so
/system/lib/arm/libsonivox.so
/system/lib/arm/libsoundtrigger.so
/system/lib/arm/libspeexresampler.so
/system/lib/arm/libsqlite.so
/system/lib/arm/libssl.so
/system/lib/libstagefright_enc_common.so
/system/lib/arm/libstagefright_foundation.so
/system/lib/arm/libstagefright_http_support.so
/system/lib/arm/libstagefright_omx.so
/system/lib/arm/libstagefright.so
/system/lib/arm/libstdc++.so
/system/lib/arm/libsurfaceflinger.so
/system/lib/arm/libsync.so
/system/lib/libsysutils.so
/system/lib/arm/libui.so
/system/lib/arm/libunwind.so
/system/lib/arm/libusbhost.so
/system/lib/arm/libutils.so
/system/lib/arm/libvorbisidec.so
/system/lib/arm/libvulkan.so
/system/vendor/lib/libwebrtc_audio_preprocessing.so
/system/lib/arm/libwebviewchromium_plat_support.so
/system/lib/arm/libwilhelm.so
/system/lib/arm/libz.so
/system/lib/arm/linker
/system/lib/arm/nb/libandroid_runtime.so
/system/lib/arm/nb/libandroid.so
/system/lib/arm/nb/libart.so
/system/lib/arm/nb/libaudioflinger.so
/system/lib/arm/nb/libbinder.so
/system/lib/arm/nb/libcamera_client.so
/system/lib/arm/nb/libc.so
/system/lib/arm/nb/libcutils.so
/system/lib/arm/nb/libdl.so
/system/lib/arm/nb/libEGL.so
/system/lib/arm/nb/libft2.so
/system/lib/arm/nb/libGLESv1_CM.so
/system/lib/arm/nb/libGLESv2.so
/system/lib/arm/nb/libGLESv3.so
/system/lib/arm/nb/libgui.so
/system/lib/arm/nb/libhwui.so
/system/lib/arm/nb/libicui18n.so
/system/lib/arm/nb/libicuuc.so
/system/lib/arm/nb/libjnigraphics.so
/system/lib/arm/nb/libmediandk.so
/system/lib/arm/nb/libmedia.so
/system/lib/arm/nb/libm.so
/system/lib/arm/nb/libnativehelper.so
/system/lib/arm/nb/libOpenMAXAL.so
/system/lib/arm/nb/libOpenSLES.so
/system/lib/arm/nb/libpixelflinger.so
/system/lib/arm/nb/libskia.so
/system/lib/arm/nb/libsqlite.so
/system/lib/arm/nb/libstagefright.so
/system/lib/arm/nb/libsurfaceflinger.so
/system/lib/arm/nb/libui.so
/system/lib/arm/nb/libutils.so
/system/lib/arm/nb/libz.so
/system/lib/hw/hdmi_cec.fugu.so
/system/lib/hw/keystore.moorefield.so
/system/vendor/lib/libDecoderVP9Hybrid.so
/system/lib/libdx_cc7.so
/system/lib/libgabi++-mfx.so
/system/lib/libhoudini.so
/system/lib/libifp.so
/system/lib/libion.so
/system/lib/libkeymaster.so
/system/lib/libmfx_omx_components_sw.so
/system/lib/libmfx_omx_core.so
/system/lib/libmfxsw32.so
/system/lib/libmixvbp_h264secure.so
/system/lib/libmixvbp_h264.so
/system/lib/libmixvbp_mpeg2.so
/system/lib/libmixvbp_mpeg4.so
/system/lib/libmixvbp.so
/system/lib/libmixvbp_vc1.so
/system/lib/libmixvbp_vp8.so
/system/lib/libOMXVideoDecoderAVCSecure.so
/system/lib/libsepdrm_cc54.so
/system/lib/libstlport-mfx.so
/system/priv-app/AtvRemoteService/AtvRemoteService.apk
/system/priv-app/LeanbackLauncher/LeanbackLauncher.apk
/system/priv-app/TV/TV.apk
/system/vendor/bin/hwperfbin2jsont
/system/vendor/bin/pvrdebug
/system/vendor/bin/pvrhtb2txt
/system/vendor/bin/pvrtld
/system/vendor/bin/rscompiler
/system/vendor/firmware/BCM4350C0.hcd
/system/vendor/firmware/BCM4350C0_SR2.hcd
/system/vendor/firmware/PR-ModelCert
/system/vendor/firmware/rgx.fw.signed.1.72.4.12
/system/vendor/lib/egl/libEGL_POWERVR_ROGUE.so
/system/vendor/lib/egl/libGLESv1_CM_POWERVR_ROGUE.so
/system/vendor/lib/egl/libGLESv2_POWERVR_ROGUE.so
/system/vendor/lib/hw/gralloc.moorefield.so
/system/vendor/lib/hw/memtrack.moorefield.so
/system/vendor/lib/hw/vulkan.moorefield.so
/system/vendor/lib/libglslcompiler.so
/system/vendor/lib/libIMGegl.so
/system/vendor/lib/liboemcrypto.so
/system/vendor/lib/libpvrcpt.so
/system/vendor/lib/libPVRRS.sha1.so
/system/vendor/lib/libPVRRS.so
/system/vendor/lib/libPVRScopeServices.so
/system/vendor/lib/libseppr_hal.so
/system/vendor/lib/libsrv_um.so
/system/vendor/lib/libufwriter.so
/system/vendor/lib/libusc.so
/system/vendor/lib/mediadrm/libplayreadydrmplugin.so
/system/vendor/lib/mediadrm/libwvdrmengine.so

View file

@ -0,0 +1,9 @@
/dev/block/by-name/boot /boot emmc defaults defaults
/dev/block/by-name/recovery /recovery emmc defaults defaults
/dev/block/by-name/splashscreen /splashscreen emmc defaults defaults
/dev/block/by-name/fastboot /fastboot emmc defaults defaults
/dev/block/by-name/misc /misc emmc defaults defaults
/dev/block/by-name/system /system ext4 ro,noatime wait
/dev/block/by-name/cache /cache ext4 nosuid,nodev,noatime,barrier=1,data=ordered wait,check
/dev/block/by-name/userdata /data ext4 nosuid,nodev,noatime,discard,barrier=1,data=ordered,noauto_da_alloc wait,check
/dev/block/by-name/factory /factory ext4 nosuid,nodev,noatime,barrier=1,data=ordered wait

View file

@ -0,0 +1,28 @@
ifneq (,$(findstring $(TARGET_DEVICE),fugu))
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_CLANG := true
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := librecovery_updater_fugu
LOCAL_SRC_FILES := recovery_updater.cpp fw_version_check.cpp
LOCAL_C_INCLUDES += bootable/recovery
include $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_CLANG := true
LOCAL_MODULE_TAGS := optional
LOCAL_C_INCLUDES += bootable/recovery
LOCAL_SRC_FILES := recovery_ui.cpp
# should match TARGET_RECOVERY_UI_LIB set in BoardConfig.mk
LOCAL_MODULE := librecovery_ui_fugu
include $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS)
endif

View file

@ -0,0 +1,265 @@
/*
* Copyright (C) 2011 Intel Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdint.h>
#include "fw_version_check.h"
#define DEVICE_NAME "/sys/kernel/fw_update/fw_info/fw_version"
#define FIP_PATTERN 0x50494624
#define SCU_IPC_VERSION_LEN_LONG 32
#define READ_SZ 256
struct fip_version_block {
uint16_t minor;
uint16_t major;
uint8_t checksum;
uint8_t reserved8;
uint16_t reserved16;
};
struct fip_version_block_chxx {
uint16_t minor;
uint16_t major;
uint8_t checksum;
uint8_t reserved8;
uint16_t reserved16;
uint16_t size;
uint16_t dest;
};
struct FIP_header {
uint32_t FIP_SIG;
struct fip_version_block umip_rev;
struct fip_version_block spat_rev;
struct fip_version_block spct_rev;
struct fip_version_block rpch_rev;
struct fip_version_block ch00_rev;
struct fip_version_block mipd_rev;
struct fip_version_block mipn_rev;
struct fip_version_block scuc_rev;
struct fip_version_block hvm_rev;
struct fip_version_block mia_rev;
struct fip_version_block ia32_rev;
struct fip_version_block oem_rev;
struct fip_version_block ved_rev;
struct fip_version_block vec_rev;
struct fip_version_block mos_rev;
struct fip_version_block pos_rev;
struct fip_version_block cos_rev;
struct fip_version_block_chxx ch01_rev;
struct fip_version_block_chxx ch02_rev;
struct fip_version_block_chxx ch03_rev;
struct fip_version_block_chxx ch04_rev;
struct fip_version_block_chxx ch05_rev;
struct fip_version_block_chxx ch06_rev;
struct fip_version_block_chxx ch07_rev;
struct fip_version_block_chxx ch08_rev;
struct fip_version_block_chxx ch09_rev;
struct fip_version_block_chxx ch10_rev;
struct fip_version_block_chxx ch11_rev;
struct fip_version_block_chxx ch12_rev;
struct fip_version_block_chxx ch13_rev;
struct fip_version_block_chxx ch14_rev;
struct fip_version_block_chxx ch15_rev;
struct fip_version_block dnx_rev;
struct fip_version_block reserved0_rev;
struct fip_version_block reserved1_rev;
struct fip_version_block ifwi_rev;
};
static int read_fw_revision(unsigned int *fw_revision, int len)
{
int i, fw_info, ret;
const char *sep = " ";
char *p, *save;
char buf[READ_SZ];
fw_info = open(DEVICE_NAME, O_RDONLY);
if (fw_info < 0) {
fprintf(stderr, "failed to open %s ", DEVICE_NAME);
return fw_info;
}
ret = read(fw_info, buf, READ_SZ - 1);
if (ret < 0) {
fprintf(stderr, "failed to read fw_revision, ret = %d\n", ret);
goto err;
}
buf[ret] = 0;
p = strtok_r(buf, sep, &save);
for (i = 0; p && i < len; i++) {
ret = sscanf(p, "%x", &fw_revision[i]);
if (ret != 1) {
fprintf(stderr, "failed to parse fw_revision, ret = %d\n", ret);
goto err;
}
p = strtok_r(NULL, sep, &save);
}
ret = 0;
err:
close(fw_info);
return ret;
}
/* Bytes in scu_ipc_version after the ioctl():
* 00 SCU Boot Strap Firmware Minor Revision Low
* 01 SCU Boot Strap Firmware Minor Revision High
* 02 SCU Boot Strap Firmware Major Revision Low
* 03 SCU Boot Strap Firmware Major Revision High
* 04 SCU Firmware Minor Revision Low
* 05 SCU Firmware Minor Revision High
* 06 SCU Firmware Major Revision Low
* 07 SCU Firmware Major Revision High
* 08 IA Firmware Minor Revision Low
* 09 IA Firmware Minor Revision High
* 10 IA Firmware Major Revision Low
* 11 IA Firmware Major Revision High
* 12 Validation Hooks Firmware Minor Revision Low
* 13 Validation Hooks Firmware Minor Revision High
* 14 Validation Hooks Firmware Major Revision Low
* 15 Validation Hooks Firmware Major Revision High
* 16 IFWI Firmware Minor Revision Low
* 17 IFWI Firmware Minor Revision High
* 18 IFWI Firmware Major Revision Low
* 19 IFWI Firmware Major Revision High
* 20 Chaabi Firmware Minor Revision Low
* 21 Chaabi Firmware Minor Revision High
* 22 Chaabi Firmware Major Revision Low
* 23 Chaabi Firmware Major Revision High
* 24 mIA Firmware Minor Revision Low
* 25 mIA Firmware Minor Revision High
* 26 mIA Firmware Major Revision Low
* 27 mIA Firmware Major Revision High
*/
int get_current_fw_rev(struct firmware_versions *v)
{
int ret;
unsigned int fw_revision[SCU_IPC_VERSION_LEN_LONG] = { 0 };
ret = read_fw_revision(fw_revision, SCU_IPC_VERSION_LEN_LONG);
if (ret)
return ret;
v->scubootstrap.minor = fw_revision[1] << 8 | fw_revision[0];
v->scubootstrap.major = fw_revision[3] << 8 | fw_revision[2];
v->scu.minor = fw_revision[5] << 8 | fw_revision[4];
v->scu.major = fw_revision[7] << 8 | fw_revision[6];
v->ia32.minor = fw_revision[9] << 8 | fw_revision[8];
v->ia32.major = fw_revision[11] << 8 | fw_revision[10];
v->valhooks.minor = fw_revision[13] << 8 | fw_revision[12];
v->valhooks.major = fw_revision[15] << 8 | fw_revision[14];
v->ifwi.minor = fw_revision[17] << 8 | fw_revision[16];
v->ifwi.major = fw_revision[19] << 8 | fw_revision[18];
v->chaabi.minor = fw_revision[21] << 8 | fw_revision[20];
v->chaabi.major = fw_revision[23] << 8 | fw_revision[22];
v->mia.minor = fw_revision[25] << 8 | fw_revision[24];
v->mia.major = fw_revision[27] << 8 | fw_revision[26];
return ret;
}
int get_image_fw_rev(void *data, unsigned sz, struct firmware_versions *v)
{
struct FIP_header fip;
unsigned char *databytes = (unsigned char *)data;
int magic;
int magic_found = 0;
if (v == NULL) {
fprintf(stderr, "Null pointer !\n");
return -1;
} else
memset((void *)v, 0, sizeof(struct firmware_versions));
while (sz >= sizeof(fip)) {
/* Scan for the FIP magic */
while (sz >= sizeof(fip)) {
memcpy(&magic, databytes, sizeof(magic));
if (magic == FIP_PATTERN) {
magic_found = 1;
break;
}
databytes += sizeof(magic);
sz -= sizeof(magic);
}
if (!magic_found) {
fprintf(stderr, "Couldn't find FIP magic in image!\n");
return -1;
}
if (sz < sizeof(fip)) {
break;
}
memcpy(&fip, databytes, sizeof(fip));
/* not available in ifwi file */
v->scubootstrap.minor = 0;
v->scubootstrap.major = 0;
/* don't update if null */
if (fip.scuc_rev.minor != 0)
v->scu.minor = fip.scuc_rev.minor;
if (fip.scuc_rev.major != 0)
v->scu.major = fip.scuc_rev.major;
if (fip.ia32_rev.minor != 0)
v->ia32.minor = fip.ia32_rev.minor;
if (fip.ia32_rev.major != 0)
v->ia32.major = fip.ia32_rev.major;
if (fip.oem_rev.minor != 0)
v->valhooks.minor = fip.oem_rev.minor;
if (fip.oem_rev.major != 0)
v->valhooks.major = fip.oem_rev.major;
if (fip.ifwi_rev.minor != 0)
v->ifwi.minor = fip.ifwi_rev.minor;
if (fip.ifwi_rev.major != 0)
v->ifwi.major = fip.ifwi_rev.major;
if (fip.ch00_rev.minor != 0)
v->chaabi.minor = fip.ch00_rev.minor;
if (fip.ch00_rev.major != 0)
v->chaabi.major = fip.ch00_rev.major;
if (fip.mia_rev.minor != 0)
v->mia.minor = fip.mia_rev.minor;
if (fip.mia_rev.major != 0)
v->mia.major = fip.mia_rev.major;
databytes += sizeof(magic);
sz -= sizeof(magic);
}
return 0;
}

View file

@ -0,0 +1,56 @@
/*
* Copyright (C) 2014 Intel Corporation
*
* 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 IFWI_VERSION_CHECK_H
#define IFWI_VERSION_CHECK_H
#include <stdint.h>
struct fw_version {
uint16_t major;
uint16_t minor;
};
struct firmware_versions {
struct fw_version scubootstrap;
struct fw_version scu;
struct fw_version ia32;
struct fw_version valhooks;
struct fw_version ifwi;
struct fw_version chaabi;
struct fw_version mia;
};
/* Query the SCU for current firmware versions and populate
* the fields in v. Returns nonzero on error */
int get_current_fw_rev(struct firmware_versions *v);
/* Assuming data points to a blob of memory containing an IFWI
* firmware image, inpsect the FIP header inside it and
* populate the fields in v. Returns nonzero on error */
int get_image_fw_rev(void *data, unsigned sz, struct firmware_versions *v);
/* Compare versions v1 and v2, and return -1, 1, or 0 if v1 is less than,
* greater than, or equal to v2, respectively */
int fw_vercmp(struct firmware_versions *v1, struct firmware_versions *v2);
/* Crack ifwi firmware file */
int crack_update_fw(const char *fw_file, struct fw_version *ifwi_version);
/* Crack ifwi firmware file to get the PTI Field. */
int crack_update_fw_pti_field(const char *fw_file, uint8_t * pti_field);
#endif

View file

@ -0,0 +1,103 @@
/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <errno.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <pthread.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
#include <string>
#include "common.h"
#include "device.h"
#include "ui.h"
#include "screen_ui.h"
#define kFBDevice "/dev/graphics/fb0"
#define FBIO_PSB_SET_RGBX _IOWR('F', 0x42, struct fb_var_screeninfo)
#define FBIO_PSB_SET_RMODE _IOWR('F', 0x43, struct fb_var_screeninfo)
class FuguUI : public ScreenRecoveryUI {
public:
bool Init(const std::string& locale) override {
SetupDisplayMode();
return ScreenRecoveryUI::Init(locale);
}
void SetupDisplayMode() {
printf("opening fb %s\n", kFBDevice);
int fb_dev = open(kFBDevice, O_RDWR);
if (fb_dev == -1) {
fprintf(stderr, "FAIL: failed to open \"%s\": %s\n", kFBDevice, strerror(errno));
return;
}
struct fb_var_screeninfo current_mode;
if (ioctl(fb_dev, FBIO_PSB_SET_RMODE, &current_mode) == -1) {
fprintf(stderr, "FAIL: unable to set RGBX mode on display controller: %s\n",
strerror(errno));
return;
}
if (ioctl(fb_dev, FBIOGET_VSCREENINFO, &current_mode) == -1) {
fprintf(stderr, "FAIL: unable to get mode: %s\n", strerror(errno));
return;
}
if (ioctl(fb_dev, FBIOBLANK, FB_BLANK_POWERDOWN) == -1) {
fprintf(stderr, "FAIL: unable to blank display: %s\n", strerror(errno));
return;
}
current_mode.bits_per_pixel = 32;
current_mode.red.offset = 0;
current_mode.red.length = 8;
current_mode.green.offset = 8;
current_mode.green.length = 8;
current_mode.blue.offset = 16;
current_mode.blue.length = 8;
if (ioctl(fb_dev, FBIOPUT_VSCREENINFO, &current_mode) == -1) {
fprintf(stderr, "FAIL: unable to set mode: %s\n", strerror(errno));
return;
}
if (ioctl(fb_dev, FBIO_PSB_SET_RGBX, &current_mode) == -1) {
fprintf(stderr, "FAIL: unable to set RGBX mode on display controller: %s\n",
strerror(errno));
return;
}
if (ioctl(fb_dev, FBIOBLANK, FB_BLANK_UNBLANK) == -1) {
fprintf(stderr, "FAIL: unable to unblank display: %s\n", strerror(errno));
return;
}
}
};
Device* make_device() {
return new Device(new FuguUI);
}

View file

@ -0,0 +1,346 @@
/*
* Copyright 2014 Intel Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <cutils/properties.h>
#include <sys/mman.h>
#include <memory>
#include <string>
#include <vector>
#include "fw_version_check.h"
#include "edify/expr.h"
#define FORCE_RW_OPT "0"
#define BOOT_IFWI_SIZE 0x400000
#define BOOT_UMIP_SIZE 0x10000
#define BOOT_UMIP_SECTOR_SIZE 0x200
#define BOOT_UMIP_XOR_OFFSET 0x7
#define BOOT_UMIP_3GPP_OFFSET 0x76F
#define BOOT_IFWI_XOR_OFFSET 0x0112d8
#define BOOT_DNX_TIMEOUT_OFFSET 0x400
#define IFWI_OFFSET 0
#define TOKEN_UMIP_AREA_OFFSET 0x4000
#define TOKEN_UMIP_AREA_SIZE 0x2C00
#define FILE_PATH_SIZE 64
#define IFWI_TYPE_LSH 12
static void dump_fw_versions(struct firmware_versions *v)
{
fprintf(stderr, "Image FW versions:\n");
fprintf(stderr, " ifwi: %04X.%04X\n", v->ifwi.major, v->ifwi.minor);
fprintf(stderr, "---- components ----\n");
fprintf(stderr, " scu: %04X.%04X\n", v->scu.major, v->scu.minor);
fprintf(stderr, " hooks/oem: %04X.%04X\n", v->valhooks.major, v->valhooks.minor);
fprintf(stderr, " ia32: %04X.%04X\n", v->ia32.major, v->ia32.minor);
fprintf(stderr, " chaabi: %04X.%04X\n", v->chaabi.major, v->chaabi.minor);
fprintf(stderr, " mIA: %04X.%04X\n", v->mia.major, v->mia.minor);
}
static int force_rw(const char *name) {
int ret, fd;
fd = open(name, O_WRONLY);
if (fd < 0) {
fprintf(stderr, "force_ro(): failed to open %s\n", name);
return fd;
}
ret = write(fd, FORCE_RW_OPT, sizeof(FORCE_RW_OPT));
if (ret <= 0) {
fprintf(stderr, "force_ro(): failed to write %s\n", name);
close(fd);
return ret;
}
close(fd);
return 0;
}
int check_ifwi_file_scu_emmc(void *data, size_t size)
{
struct firmware_versions dev_fw_rev, img_fw_rev;
if (get_image_fw_rev(data, size, &img_fw_rev)) {
fprintf(stderr, "Coudn't extract FW version data from image\n");
return -1;
}
dump_fw_versions(&img_fw_rev);
if (get_current_fw_rev(&dev_fw_rev)) {
fprintf(stderr, "Couldn't query existing IFWI version\n");
return -1;
}
fprintf(stderr,
"Attempting to flash ifwi image version %04X.%04X over ifwi current version %04X.%04X\n",
img_fw_rev.ifwi.major, img_fw_rev.ifwi.minor, dev_fw_rev.ifwi.major, dev_fw_rev.ifwi.minor);
if (img_fw_rev.ifwi.major != dev_fw_rev.ifwi.major) {
fprintf(stderr,
"IFWI FW Major version numbers (file=%04X current=%04X) don't match, Update abort.\n",
img_fw_rev.ifwi.major, dev_fw_rev.ifwi.major);
return -1;
}
return 1;
}
static uint32_t xor_compute(char *ptr, uint32_t size)
{
uint32_t val = 0;
uint32_t i;
for (i = 0; i < size; i+=4)
val = val ^ *(uint32_t *)(ptr + i);
return val;
}
static uint8_t xor_factorize(uint32_t val)
{
return (uint8_t)((val & 0xff) ^ ((val >> 8) & 0xff) ^ ((val >> 16) & 0xff) ^ ((val >> 24) & 0xff));
}
static void xor_update(char *ptr)
{
uint16_t i;
uint32_t val;
/* update UMIP xor of sector 2 to 127 */
for (i = 2; i < 128; i++) {
val = xor_compute(ptr + i * BOOT_UMIP_SECTOR_SIZE, BOOT_UMIP_SECTOR_SIZE);
*(uint32_t *)(ptr + 4 * i) = val;
}
/* update UMIP xor */
*(ptr + BOOT_UMIP_XOR_OFFSET) = 0;
val= xor_compute(ptr, BOOT_UMIP_SIZE);
*(ptr + BOOT_UMIP_XOR_OFFSET) = xor_factorize(val);
/* update IFWI xor */
*(uint32_t *)(ptr + BOOT_IFWI_XOR_OFFSET) = 0x0;
val= xor_compute(ptr, BOOT_IFWI_SIZE);
*(uint32_t *)(ptr + BOOT_IFWI_XOR_OFFSET) = val;
}
static int write_umip_emmc(uint32_t addr_offset, void *data, size_t size)
{
int boot_fd = 0;
int boot_index;
char boot_partition[FILE_PATH_SIZE];
char boot_partition_force_ro[FILE_PATH_SIZE];
char *ptr;
char *token_data;
if (addr_offset == IFWI_OFFSET) {
token_data = reinterpret_cast<char *>(malloc(TOKEN_UMIP_AREA_SIZE));
if (!token_data) {
fprintf(stderr, "write_umip_emmc: Malloc error\n");
return -1;
}
if (size > BOOT_IFWI_SIZE) {
fprintf(stderr, "write_umip_emmc: Truncating last %d bytes from the IFWI\n",
(size - BOOT_IFWI_SIZE));
/* Since the last 144 bytes are the FUP header which are not required,*/
/* we truncate it to fit into the boot partition. */
size = BOOT_IFWI_SIZE;
}
}
for (boot_index = 0; boot_index < 2; boot_index++) {
snprintf(boot_partition, FILE_PATH_SIZE, "/dev/block/mmcblk0boot%d", boot_index);
snprintf(boot_partition_force_ro, FILE_PATH_SIZE, "/sys/block/mmcblk0boot%d/force_ro", boot_index);
if (force_rw(boot_partition_force_ro)) {
fprintf(stderr, "write_umip_emmc: unable to force_ro %s\n", boot_partition);
goto err_boot1;
}
boot_fd = open(boot_partition, O_RDWR);
if (boot_fd < 0) {
fprintf(stderr, "write_umip_emmc: failed to open %s\n", boot_partition);
goto err_boot1;
}
ptr = (char *)mmap(NULL, BOOT_IFWI_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, boot_fd, 0);
if (ptr == MAP_FAILED) {
fprintf(stderr, "write_umip_emmc: mmap failed on boot%d with error : %s\n", boot_index, strerror(errno));
goto err_boot1;
}
if (addr_offset == IFWI_OFFSET)
memcpy(token_data, ptr + TOKEN_UMIP_AREA_OFFSET, TOKEN_UMIP_AREA_SIZE);
/* Write the data */
if (addr_offset + size <= BOOT_IFWI_SIZE)
if (data == NULL)
memset(ptr + addr_offset, 0, size);
else
memcpy(ptr + addr_offset, data, size);
else {
fprintf(stderr, "write_umip_emmc: write failed\n");
goto err_boot2;
}
if (addr_offset == IFWI_OFFSET)
memcpy(ptr + TOKEN_UMIP_AREA_OFFSET, token_data, TOKEN_UMIP_AREA_SIZE);
/* Compute and write xor */
xor_update(ptr);
munmap(ptr, BOOT_IFWI_SIZE);
close(boot_fd);
}
if (addr_offset == IFWI_OFFSET)
free(token_data);
return 0;
err_boot2:
munmap(ptr, BOOT_IFWI_SIZE);
err_boot1:
if (addr_offset == IFWI_OFFSET)
free(token_data);
close(boot_fd);
return -1;
}
static int readbyte_umip_emmc(uint32_t addr_offset)
{
int boot_fd = 0;
char *ptr;
int value = 0;
if (force_rw("/sys/block/mmcblk0boot0/force_ro")) {
fprintf(stderr, "read_umip_emmc: unable to force_ro\n");
goto err_boot1;
}
boot_fd = open("/dev/block/mmcblk0boot0", O_RDWR);
if (boot_fd < 0) {
fprintf(stderr, "read_umip_emmc: failed to open /dev/block/mmcblk0boot0\n");
goto err_boot1;
}
ptr = (char *)mmap(NULL, BOOT_UMIP_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, boot_fd, 0);
if (ptr == MAP_FAILED) {
fprintf(stderr, "read_umip_emmc: mmap failed on boot0 with error : %s\n", strerror(errno));
goto err_boot1;
}
/* Read the data */
if (addr_offset < BOOT_UMIP_SIZE)
value = (int)*(ptr + addr_offset);
else {
fprintf(stderr, "read_umip_emmc: read failed\n");
goto err_boot2;
}
munmap(ptr, BOOT_UMIP_SIZE);
close(boot_fd);
return value;
err_boot2:
munmap(ptr, BOOT_UMIP_SIZE);
err_boot1:
close(boot_fd);
return -1;
}
int update_ifwi_file_scu_emmc(void *data, size_t size)
{
return write_umip_emmc(IFWI_OFFSET, data, size);
}
int flash_ifwi_scu_emmc(void *data, unsigned size)
{
int ret;
ret = check_ifwi_file_scu_emmc(data, size);
if (ret > 0)
return update_ifwi_file_scu_emmc(data, size);
return ret;
}
Value* FlashIfwiFuguFn(const char *name, State * state,
const std::vector<std::unique_ptr<Expr>>& argv) {
Value *ret = NULL;
unsigned char *buffer = NULL;
int ifwi_size;
FILE *f = NULL;
if (argv.size() != 1) {
ErrorAbort(state, "%s() expected 1 arg, got %zu", name, argv.size());
return NULL;
}
std::vector<std::string> args;
if (!ReadArgs(state, argv, &args)) {
ErrorAbort(state, "%s() invalid args ", name);
return NULL;
}
const std::string& filename = args[0];
if (filename.empty()) {
ErrorAbort(state, "filename argument to %s can't be empty", name);
return nullptr;
}
if ((f = fopen(filename.c_str(),"rb")) == NULL) {
ErrorAbort(state, "Unable to open file %s: %s ", filename.c_str(), strerror(errno));
return nullptr;
}
fseek(f, 0, SEEK_END);
ifwi_size = ftell(f);
if (ifwi_size < 0) {
ErrorAbort(state, "Unable to get ifwi_size ");
return nullptr;
};
fseek(f, 0, SEEK_SET);
if ((buffer = reinterpret_cast<unsigned char *>(malloc(ifwi_size))) == NULL) {
ErrorAbort(state, "Unable to alloc ifwi flash buffer of size %d", ifwi_size);
return nullptr;
}
fread(buffer, ifwi_size, 1, f);
fclose(f);
if(flash_ifwi_scu_emmc(buffer, ifwi_size) !=0) {
ErrorAbort(state, "Unable to flash ifwi in emmc");
free(buffer);
return nullptr;
};
free(buffer);
ret = StringValue("");
return ret;
}
void Register_librecovery_updater_fugu() {
RegisterFunction("fugu.flash_ifwi", FlashIfwiFuguFn);
}

View file

@ -0,0 +1,102 @@
# Copyright (C) 2012 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Emit extra commands needed for Group during OTA installation
(installing the bootloader)."""
import struct
import common
def WriteIfwi(info):
info.script.AppendExtra('package_extract_file("ifwi.bin", "/tmp/ifwi.bin");')
info.script.AppendExtra("""fugu.flash_ifwi("/tmp/ifwi.bin");""")
def WriteDroidboot(info):
info.script.WriteRawImage("/fastboot", "droidboot.img")
def WriteSplashscreen(info):
info.script.WriteRawImage("/splashscreen", "splashscreen.img")
def WriteBootloader(info, bootloader):
header_fmt = "<8sHHI"
header_size = struct.calcsize(header_fmt)
magic, revision, reserved, reserved = struct.unpack(
header_fmt, bootloader[:header_size])
assert magic == "BOOTLDR!", "bootloader.img bad magic value"
if revision == 1:
offset = header_size;
header_v1_fmt = "II"
header_v1_size = struct.calcsize(header_v1_fmt)
ifwi_size, droidboot_size = struct.unpack(header_v1_fmt, bootloader[offset:offset + header_v1_size])
offset += header_v1_size
ifwi = bootloader[offset:offset + ifwi_size]
offset += ifwi_size
droidboot = bootloader[offset:]
common.ZipWriteStr(info.output_zip, "droidboot.img", droidboot)
common.ZipWriteStr(info.output_zip, "ifwi.bin", ifwi)
WriteIfwi(info)
WriteDroidboot(info)
return
offset = header_size;
while offset < len(bootloader):
c_header_fmt = "<8sIBBBB"
c_header_size = struct.calcsize(c_header_fmt)
c_magic, size, flags, _, _ , _ = struct.unpack(c_header_fmt, bootloader[offset:offset + c_header_size])
buf = bootloader[offset + c_header_size: offset + c_header_size + size]
offset += c_header_size + size
if not flags & 1:
continue
if c_magic == "IFWI!!!!":
common.ZipWriteStr(info.output_zip, "ifwi.bin", buf)
WriteIfwi(info);
continue
if c_magic == "DROIDBT!":
common.ZipWriteStr(info.output_zip, "droidboot.img", buf)
WriteDroidboot(info);
continue
if c_magic == "SPLASHS!":
common.ZipWriteStr(info.output_zip, "splashscreen.img", buf)
WriteSplashscreen(info);
continue
def FullOTA_InstallEnd(info):
try:
bootloader_img = info.input_zip.read("RADIO/bootloader.img")
except KeyError:
print "no bootloader.img in target_files; skipping install"
else:
WriteBootloader(info, bootloader_img)
def IncrementalOTA_InstallEnd(info):
try:
target_bootloader_img = info.target_zip.read("RADIO/bootloader.img")
try:
source_bootloader_img = info.source_zip.read("RADIO/bootloader.img")
except KeyError:
source_bootloader_img = None
if source_bootloader_img == target_bootloader_img:
print "bootloader unchanged; skipping"
else:
print "bootloader changed; adding it"
WriteBootloader(info, target_bootloader_img)
except KeyError:
print "no bootloader.img in target target_files; skipping install"

View file

@ -0,0 +1,12 @@
#
# Usage is subject to the enclosed license agreement
echo
echo The license for this software will now be displayed.
echo You must agree to this license before using this software.
echo
echo -n Press Enter to view the license
read dummy
echo
more << __EOF__

View file

@ -0,0 +1,22 @@
__EOF__
if test $? != 0
then
echo ERROR: Couldn\'t display license file 1>&2
exit 1
fi
echo
echo -n Type \"I ACCEPT\" if you agree to the terms of the license:\
read typed
if test "$typed" != I\ ACCEPT
then
echo
echo You didn\'t accept the license. Extraction aborted.
exit 2
fi
echo

View file

@ -0,0 +1,12 @@
if test $? != 0
then
echo
echo ERROR: Couldn\'t extract files. 1>&2
exit 3
else
echo
echo Files extracted successfully.
fi
exit 0

View file

@ -0,0 +1,2 @@
#!/bin/bash
#

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