diff --git a/.clang-format b/.clang-format
new file mode 100644
index 00000000..34633046
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1,13 @@
+BasedOnStyle: Google
+AccessModifierOffset: -2
+AllowShortFunctionsOnASingleLine: Inline
+ColumnLimit: 99
+CommentPragmas: NOLINT:.*
+DerivePointerAlignment: false
+IndentWidth: 4
+PointerAlignment: Right
+TabWidth: 4
+UseTab: Never
+PenaltyExcessCharacter: 32
+AllowShortIfStatementsOnASingleLine: false
+SpacesBeforeTrailingComments: 2
diff --git a/Android.bp b/Android.bp
new file mode 100644
index 00000000..e69df8d8
--- /dev/null
+++ b/Android.bp
@@ -0,0 +1,6 @@
+soong_namespace {
+ imports: [
+ "hardware/google/interfaces",
+ "hardware/google/pixel",
+ ],
+}
diff --git a/Android.mk b/Android.mk
new file mode 100644
index 00000000..843b1e8e
--- /dev/null
+++ b/Android.mk
@@ -0,0 +1,22 @@
+#
+# Copyright 2019 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)
+
+ifeq ($(USES_DEVICE_GOOGLE_SUNFISH),true)
+ subdir_makefiles=$(call first-makefiles-under,$(LOCAL_PATH))
+ $(foreach mk,$(subdir_makefiles),$(info including $(mk) ...)$(eval include $(mk)))
+endif
diff --git a/AndroidProducts.mk b/AndroidProducts.mk
new file mode 100644
index 00000000..9db0a5fb
--- /dev/null
+++ b/AndroidProducts.mk
@@ -0,0 +1,21 @@
+#
+# Copyright 2019 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_sunfish.mk \
+
+COMMON_LUNCH_CHOICES := \
+ aosp_sunfish-userdebug \
diff --git a/BoardConfig-common.mk b/BoardConfig-common.mk
new file mode 100644
index 00000000..cbb790a9
--- /dev/null
+++ b/BoardConfig-common.mk
@@ -0,0 +1,254 @@
+#
+# 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.
+#
+
+include build/make/target/board/BoardConfigMainlineCommon.mk
+
+TARGET_BOARD_PLATFORM := sm6150
+TARGET_BOARD_INFO_FILE := device/google/sunfish/board-info.txt
+USES_DEVICE_GOOGLE_SUNFISH := true
+
+TARGET_ARCH := arm64
+TARGET_ARCH_VARIANT := armv8-a
+TARGET_CPU_ABI := arm64-v8a
+TARGET_CPU_ABI2 :=
+TARGET_CPU_VARIANT := generic
+
+TARGET_2ND_ARCH := arm
+TARGET_2ND_ARCH_VARIANT := armv7-a-neon
+TARGET_2ND_CPU_ABI := armeabi-v7a
+TARGET_2ND_CPU_ABI2 := armeabi
+TARGET_2ND_CPU_VARIANT := cortex-a9
+
+BUILD_BROKEN_ENG_DEBUG_TAGS := true
+BUILD_BROKEN_DUP_RULES := true
+
+TARGET_BOARD_COMMON_PATH := device/google/sunfish/sm7150
+
+BOARD_KERNEL_CMDLINE += console=ttyMSM0,115200n8 androidboot.console=ttyMSM0 printk.devkmsg=on
+BOARD_KERNEL_CMDLINE += msm_rtb.filter=0x237
+BOARD_KERNEL_CMDLINE += ehci-hcd.park=3
+BOARD_KERNEL_CMDLINE += service_locator.enable=1
+BOARD_KERNEL_CMDLINE += androidboot.memcg=1 cgroup.memory=nokmem
+BOARD_KERNEL_CMDLINE += lpm_levels.sleep_disabled=1 #STOPSHIP
+BOARD_KERNEL_CMDLINE += usbcore.autosuspend=7
+BOARD_KERNEL_CMDLINE += loop.max_part=7
+BOARD_KERNEL_CMDLINE += androidboot.usbcontroller=a600000.dwc3 swiotlb=1
+BOARD_KERNEL_CMDLINE += androidboot.selinux=permissive # STOPSHIP
+#BOARD_KERNEL_CMDLINE += androidboot.boot_devices= #TODO
+
+#BOARD_KERNEL_CMDLINE += video=vfb:640x400,bpp=32,memsize=3072000 service_locator.enable=1 earlycon=msm_geni_serial,0x880000
+
+BOARD_KERNEL_BASE := 0x00000000
+BOARD_KERNEL_PAGESIZE := 4096
+BOARD_KERNEL_TAGS_OFFSET := 0x01E00000
+BOARD_RAMDISK_OFFSET := 0x02000000
+
+BOARD_INCLUDE_DTB_IN_BOOTIMG := true
+BOARD_BOOT_HEADER_VERSION := 2
+BOARD_MKBOOTIMG_ARGS += --header_version $(BOARD_BOOT_HEADER_VERSION)
+
+# DTBO partition definitions
+BOARD_PREBUILT_DTBOIMAGE := device/google/sunfish-kernel/dtbo.img
+BOARD_DTBOIMG_PARTITION_SIZE := 8388608
+
+TARGET_NO_KERNEL := false
+BOARD_USES_RECOVERY_AS_BOOT := true
+BOARD_USES_METADATA_PARTITION := true
+
+AB_OTA_UPDATER := true
+
+AB_OTA_PARTITIONS += \
+ boot \
+ system \
+ vbmeta \
+ dtbo \
+ product \
+ vbmeta_system
+
+# Partitions (listed in the file) to be wiped under recovery.
+TARGET_RECOVERY_WIPE := device/google/sunfish/recovery.wipe
+TARGET_RECOVERY_FSTAB := device/google/sunfish/fstab.hardware
+TARGET_RECOVERY_PIXEL_FORMAT := RGBX_8888
+TARGET_RECOVERY_UI_LIB := \
+ librecovery_ui_sunfish \
+ libnos_citadel_for_recovery \
+ libnos_for_recovery
+
+# Enable chain partition for system.
+BOARD_AVB_VBMETA_SYSTEM := system
+BOARD_AVB_VBMETA_SYSTEM_KEY_PATH := external/avb/test/data/testkey_rsa2048.pem
+BOARD_AVB_VBMETA_SYSTEM_ALGORITHM := SHA256_RSA2048
+BOARD_AVB_VBMETA_SYSTEM_ROLLBACK_INDEX := $(PLATFORM_SECURITY_PATCH_TIMESTAMP)
+BOARD_AVB_VBMETA_SYSTEM_ROLLBACK_INDEX_LOCATION := 1
+
+# product.img
+BOARD_PRODUCTIMAGE_FILE_SYSTEM_TYPE := ext4
+
+# userdata.img
+TARGET_USERIMAGES_USE_F2FS := true
+BOARD_USERDATAIMAGE_PARTITION_SIZE := 10737418240
+BOARD_USERDATAIMAGE_FILE_SYSTEM_TYPE := f2fs
+
+# persist.img
+BOARD_PERSISTIMAGE_PARTITION_SIZE := 33554432
+BOARD_PERSISTIMAGE_FILE_SYSTEM_TYPE := ext4
+
+# boot.img
+BOARD_BOOTIMAGE_PARTITION_SIZE := 0x04000000
+
+# super
+BOARD_SUPER_PARTITION_SIZE := 9755951104
+BOARD_SUPER_PARTITION_GROUPS := google_dynamic_partitions
+BOARD_GOOGLE_DYNAMIC_PARTITIONS_PARTITION_LIST := \
+ system \
+ vendor \
+ product
+
+#BOARD_GOOGLE_DYNAMIC_PARTITIONS_SIZE is set to BOARD_SUPER_PARTITION_SIZE / 2 - 4MB
+BOARD_GOOGLE_DYNAMIC_PARTITIONS_SIZE := 4873781248
+
+#Set error limit to BOARD_SUPER_PARTITON_SIZE - 500MB
+BOARD_SUPER_PARTITION_ERROR_LIMIT := 9231663104
+
+BOARD_FLASH_BLOCK_SIZE := 131072
+
+BOARD_ROOT_EXTRA_SYMLINKS := /vendor/lib/dsp:/dsp
+BOARD_ROOT_EXTRA_SYMLINKS += /mnt/vendor/persist:/persist
+
+include device/google/sunfish-sepolicy/sunfish-sepolicy.mk
+
+TARGET_FS_CONFIG_GEN := device/google/sunfish/config.fs
+
+BOARD_EXT4_SHARE_DUP_BLOCKS := true
+
+QCOM_BOARD_PLATFORMS += sm6150
+QC_PROP_ROOT := vendor/qcom/sm7150/proprietary
+QC_PROP_PATH := $(QC_PROP_ROOT)
+BOARD_HAVE_BLUETOOTH_QCOM := true
+BOARD_USES_COMMON_BLUETOOTH_HAL := true
+
+# Camera
+TARGET_USES_AOSP := true
+BOARD_QTI_CAMERA_32BIT_ONLY := false
+CAMERA_DAEMON_NOT_PRESENT := true
+TARGET_USES_ION := true
+TARGET_USES_EASEL := true
+BOARD_USES_EASEL := true
+
+# GPS
+TARGET_NO_RPC := true
+TARGET_USES_HARDWARE_QCOM_GPS := false
+BOARD_VENDOR_QCOM_GPS_LOC_API_HARDWARE := default
+BOARD_VENDOR_QCOM_LOC_PDK_FEATURE_SET := true
+
+# RenderScript
+OVERRIDE_RS_DRIVER := libRSDriver_adreno.so
+
+# Sensors
+USE_SENSOR_MULTI_HAL := true
+TARGET_SUPPORT_DIRECT_REPORT := true
+
+# wlan
+BOARD_WLAN_DEVICE := qcwcn
+BOARD_WPA_SUPPLICANT_DRIVER := NL80211
+BOARD_HOSTAPD_DRIVER := NL80211
+WIFI_DRIVER_DEFAULT := qca_cld3
+WPA_SUPPLICANT_VERSION := VER_0_8_X
+BOARD_WPA_SUPPLICANT_PRIVATE_LIB := lib_driver_cmd_$(BOARD_WLAN_DEVICE)
+BOARD_HOSTAPD_PRIVATE_LIB := lib_driver_cmd_$(BOARD_WLAN_DEVICE)
+WIFI_HIDL_FEATURE_AWARE := true
+WIFI_HIDL_FEATURE_DUAL_INTERFACE:= true
+
+# Audio
+BOARD_USES_ALSA_AUDIO := true
+AUDIO_FEATURE_ENABLED_MULTI_VOICE_SESSIONS := true
+AUDIO_FEATURE_ENABLED_SND_MONITOR := true
+AUDIO_FEATURE_ENABLED_USB_TUNNEL := true
+AUDIO_FEATURE_ENABLED_CIRRUS_SPKR_PROTECTION := true
+BOARD_SUPPORTS_SOUND_TRIGGER := true
+AUDIO_FEATURE_FLICKER_SENSOR_INPUT := true
+SOUND_TRIGGER_FEATURE_LPMA_ENABLED := true
+AUDIO_FEATURE_ENABLED_MAXX_AUDIO := true
+BOARD_SUPPORTS_SOUND_TRIGGER_5514 := true
+AUDIO_FEATURE_ENABLED_24BITS_CAMCORDER := true
+
+# Graphics
+TARGET_USES_GRALLOC1 := true
+TARGET_USES_HWC2 := true
+TARGET_USES_NV21_CAMERA_PREVIEW := true
+
+VSYNC_EVENT_PHASE_OFFSET_NS := 2000000
+SF_VSYNC_EVENT_PHASE_OFFSET_NS := 6000000
+
+# Display
+TARGET_HAS_WIDE_COLOR_DISPLAY := false
+TARGET_USES_DISPLAY_RENDER_INTENTS := true
+TARGET_USES_COLOR_METADATA := true
+TARGET_USES_DRM_PP := true
+
+# Misc
+TARGET_USES_HARDWARE_QCOM_BOOTCTRL := true
+
+
+# Vendor Interface Manifest
+DEVICE_MANIFEST_FILE := device/google/sunfish/manifest.xml
+DEVICE_MATRIX_FILE := device/google/sunfish/compatibility_matrix.xml
+DEVICE_FRAMEWORK_COMPATIBILITY_MATRIX_FILE := device/google/sunfish/device_framework_matrix.xml
+DEVICE_FRAMEWORK_MANIFEST_FILE := device/google/sunfish/framework_manifest.xml
+
+# Use mke2fs to create ext4 images
+TARGET_USES_MKE2FS := true
+
+# Kernel modules
+ifeq (,$(filter-out sunfish_kasan, $(TARGET_PRODUCT)))
+BOARD_VENDOR_KERNEL_MODULES += \
+ $(wildcard device/google/sunfish-kernel/kasan/*.ko)
+else ifeq (,$(filter-out sunfish_kernel_debug_memory, $(TARGET_PRODUCT)))
+BOARD_VENDOR_KERNEL_MODULES += \
+ $(wildcard device/google/sunfish-kernel/debug_memory/*.ko)
+else ifeq (,$(filter-out sunfish_kernel_debug_locking, $(TARGET_PRODUCT)))
+BOARD_VENDOR_KERNEL_MODULES += \
+ $(wildcard device/google/sunfish-kernel/debug_locking/*.ko)
+else ifeq (,$(filter-out sunfish_kernel_debug_hang, $(TARGET_PRODUCT)))
+BOARD_VENDOR_KERNEL_MODULES += \
+ $(wildcard device/google/sunfish-kernel/debug_hang/*.ko)
+else ifeq (,$(filter-out sunfish_kernel_debug_api, $(TARGET_PRODUCT)))
+BOARD_VENDOR_KERNEL_MODULES += \
+ $(wildcard device/google/sunfish-kernel/debug_api/*.ko)
+else
+BOARD_VENDOR_KERNEL_MODULES += \
+ $(wildcard device/google/sunfish-kernel/*.ko)
+endif
+
+# DTB
+ifeq (,$(filter-out sunfish_kasan, $(TARGET_PRODUCT)))
+BOARD_PREBUILT_DTBIMAGE_DIR := device/google/sunfish-kernel/kasan
+else ifeq (,$(filter-out sunfish_kernel_debug_memory, $(TARGET_PRODUCT)))
+BOARD_PREBUILT_DTBIMAGE_DIR := device/google/sunfish-kernel/debug_memory
+else ifeq (,$(filter-out sunfish_kernel_debug_locking, $(TARGET_PRODUCT)))
+BOARD_PREBUILT_DTBIMAGE_DIR := device/google/sunfish-kernel/debug_locking
+else ifeq (,$(filter-out sunfish_kernel_debug_hang, $(TARGET_PRODUCT)))
+BOARD_PREBUILT_DTBIMAGE_DIR := device/google/sunfish-kernel/debug_hang
+else ifeq (,$(filter-out sunfish_kernel_debug_api, $(TARGET_PRODUCT)))
+BOARD_PREBUILT_DTBIMAGE_DIR := device/google/sunfish-kernel/debug_api
+else
+BOARD_PREBUILT_DTBIMAGE_DIR := device/google/sunfish-kernel
+endif
+
+# Testing related defines
+BOARD_PERFSETUP_SCRIPT := platform_testing/scripts/perf-setup/s5-setup.sh
+
+-include vendor/google_devices/sunfish/proprietary/BoardConfigVendor.mk
diff --git a/CleanSpec.mk b/CleanSpec.mk
new file mode 100644
index 00000000..0007a8ba
--- /dev/null
+++ b/CleanSpec.mk
@@ -0,0 +1,89 @@
+# Copyright 2019 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.
+#
+
+# If you don't need to do a full clean build but would like to touch
+# a file or delete some intermediate files, add a clean step to the end
+# of the list. These steps will only be run once, if they haven't been
+# run before.
+#
+# E.g.:
+# $(call add-clean-step, touch -c external/sqlite/sqlite3.h)
+# $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libz_intermediates)
+#
+# Always use "touch -c" and "rm -f" or "rm -rf" to gracefully deal with
+# files that are missing or have been moved.
+#
+# Use $(PRODUCT_OUT) to get to the "out/target/product/blah/" directory.
+# Use $(OUT_DIR) to refer to the "out" directory.
+#
+# If you need to re-do something that's already mentioned, just copy
+# the command and add it to the bottom of the list. E.g., if a change
+# that you made last week required touching a file and a change you
+# made today requires touching the same file, just copy the old
+# touch step and add it to the end of the list.
+#
+# ************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
+# ************************************************
+
+# For example:
+#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/AndroidTests_intermediates)
+#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/core_intermediates)
+#$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f)
+#$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*)
+
+# Remove default android.hardware.health@2.0-service
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/bin/hw/android.hardware.health@2.0-service)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/etc/init/android.hardware.health@2.0-service.rc)
+
+# Remove healthd
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/bin/healthd)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/etc/init/healthd.rc)
+
+# Move libnfc-nci.conf to /vendor
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/etc/libnfc-nci.conf)
+
+# Remove /firmware which used to be a symlink to /vendor/firmware_mnt
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/root/firmware)
+
+# Remove thermalHAL 1.0
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/etc/init/android.hardware.thermal@1.0-service.sunfish.rc)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/bin/hw/android.hardware.thermal@1.0-service.sunfish)
+
+# Remove default android.hardware.composer@2.2
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/bin/hw/android.hardware.graphics.composer@2.2-service)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/etc/init/android.hardware.graphics.composer@2.2-service.rc)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/lib64/hw/android.hardware.graphics.composer@2.2-impl.so)
+
+# Remove default android.hardware.graphics.composer@2.3-service
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/bin/hw/android.hardware.graphics.composer@2.3-service)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/etc/init/android.hardware.graphics.composer@2.3-service.rc)
+
+# Remove super_empty.img
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/super_empty.img)
+
+# Remove Vibrator HAL 1.2
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/etc/init/android.hardware.vibrator@1.2-service.sunfish.rc)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/bin/hw/android.hardware.vibrator@1.2-service.sunfish)
+
+# Remove Misnamed Vibrator VINTF Fragment
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/etc/vintf/manifest/manifest.xml)
+
+# Rename power HAL
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/etc/init/android.hardware.power@1.3-service.sunfish-libperfmgr.rc)
+
+# Remove VR permission
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/etc/permissions/android.hardware.vr.headtracking.xml)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/etc/permissions/android.hardware.vr.high_performance.xml)
diff --git a/WCNSS_qcom_cfg.ini b/WCNSS_qcom_cfg.ini
new file mode 100644
index 00000000..24563f73
--- /dev/null
+++ b/WCNSS_qcom_cfg.ini
@@ -0,0 +1,429 @@
+# This file allows user to override the factory
+# defaults for the WLAN Driver
+
+#############################################
+# Power related configurations
+#############################################
+# Phy Mode (auto, b, g, n, etc)
+# Valid values are 0-9, with 0 = Auto, 4 = 11n, 9 = 11ac
+# 1 = 11abg, 2 = 11b, 3 = 11g, 5 = 11g only, 6 = 11n only
+# 7 = 11b only 8 = 11ac only.
+gDot11Mode=0
+
+#############################################
+# STA related general configurations
+#############################################
+# UAPSD service interval for VO,VI, BE, BK traffic
+InfraUapsdVoSrvIntv=0
+InfraUapsdViSrvIntv=0
+InfraUapsdBeSrvIntv=0
+InfraUapsdBkSrvIntv=0
+
+# Flag to allow STA send AddTspec even when ACM is Off
+gAddTSWhenACMIsOff=1
+
+#############################################
+# SAP related configurations
+#############################################
+#Enable OBSS protection
+gEnableApOBSSProt=1
+
+# Maximum Tx power
+# gTxPowerCap=30
+
+# Fragmentation Threshold
+# gFragmentationThreshold=2346
+
+# RTS threshold
+RTSThreshold=1048576
+
+# 802.11d support
+g11dSupportEnabled=0
+
+# DFS Master Capability
+gEnableDFSMasterCap=1
+
+gNeighborLookupThreshold=76
+
+# Legacy (non-ESE, non-802.11r) Fast Roaming Support
+# To enable, set FastRoamEnabled=1
+# To disable, set FastRoamEnabled=0
+FastRoamEnabled=1
+
+# Check if the AP to which we are roaming is better than current AP in
+# terms of RSSI. Checking is disabled if set to Zero.Otherwise it will
+# use this value as to how better the RSSI of the new/roamable AP should
+# be for roaming
+RoamRssiDiff=3
+
+#Channel Bonding
+gChannelBondingMode5GHz=1
+
+#Say gGoKeepAlivePeriod(5 seconds) and gGoLinkMonitorPeriod(10 seconds).
+#For every 10 seconds DUT send Qos Null frame(i.e., Keep Alive frame if link
+#is idle for last 10 seconds.) For both active and power save clients.
+
+#Power save clients: DUT set TIM bit from 10th second onwards and till client
+#honors TIM bit. If doesn't honor for 5 seconds then DUT remove client.
+
+#Active clients: DUT send Qos Null frame for 10th seconds onwards if it is not
+#success still we try on 11th second if not tries on 12th and so on till 15th
+#second. Hence before disconnection DUT will send 5 NULL frames. Hence in any
+#case DUT will detect client got removed in (10+5) seconds.
+#i.e., (gGoKeepAlivePeriod + gGoLinkMonitorPeriod)..
+
+#gGoLinkMonitorPeriod/ gApLinkMonitorPeriod is period where link is idle and
+#it is period where we send NULL frame.
+#gApLinkMonitorPeriod = 10
+#gGoLinkMonitorPeriod = 10
+
+# Enable DFS channel roam
+# 0: DISABLE, 1: ENABLED_NORMAL, 2: ENABLED_ACTIVE
+gAllowDFSChannelRoam=1
+
+# chain mask related params
+#
+# Set txchainmask and rxchainmask
+# These parameters are used only if gEnable2x2 is 0
+# Valid values are 1,2
+# Set gSetTxChainmask1x1=1 or gSetRxChainmask1x1=1 to select chain0.
+# Set gSetTxChainmask1x1=2 or gSetRxChainmask1x1=2 to select chain1.
+gSetTxChainmask1x1=1
+gSetRxChainmask1x1=1
+
+# MCC to SCC Switch mode:
+# 0-Disable
+# 1-Enable
+# 2-Force SCC if same band, with SAP restart
+# 3-Force SCC if same band, without SAP restart by sending (E)CSA
+# 4-Force SCC if same band (or) use SAP mandatory channel for DBS,
+# without SAP restart by sending (E)CSA
+gWlanMccToSccSwitchMode = 3
+
+# 1=enable tx STBC; 0=disable
+gEnableTXSTBC=1
+
+# 1=enable rx LDPC; 0=disable
+gEnableRXLDPC=1
+
+#Enable/Disable Tx beamformee in SAP mode
+gEnableTxBFeeSAP=1
+
+# Enable Tx beamforming in VHT20MHz
+# Valid values are 0,1. If commented out, the default value is 0.
+# 0=disable, 1=enable
+gEnableTxBFin20MHz=1
+
+# 802.11K support
+gRrmEnable=1
+
+#Enable Power Save offload
+gEnablePowerSaveOffload=2
+
+# Maximum Receive AMPDU size (VHT only. Valid values:
+# 0->8k 1->16k 2->32k 3->64k 4->128k)
+gVhtAmpduLenExponent=7
+
+# Maximum MPDU length (VHT only. Valid values:
+# 0->3895 octets, 1->7991 octets, 2->11454 octets)
+gVhtMpduLen=2
+
+# Maximum number of wow filters required
+#gMaxWoWFilters=22
+
+# WOW Enable/Disable.
+# 0 - Disable both magic pattern match and pattern byte match.
+# 1 - Enable magic pattern match on all interfaces.
+# 2 - Enable pattern byte match on all interfaces.
+# 3 - Enable both magic pattern and pattern byte match on all interfaces.
+# Default value of gEnableWoW is 3.
+# gEnableWoW=0
+
+#############################################
+# P2P related configurations
+#############################################
+#Enable or Disable p2p device address administered
+isP2pDeviceAddrAdministrated=0
+
+# Set Thermal Power limit
+TxPower2g=10
+TxPower5g=10
+
+#Enable VHT on 2.4Ghz
+gEnableVhtFor24GHzBand=1
+
+#############################################
+# Offload related configurations
+#############################################
+#Maximum number of offload peers supported
+# gMaxOffloadPeers=2
+
+# controlling the following offload patterns
+# through ini parameter. Default value is 1
+# to disable set it to zero. ssdp = 0
+# Setup multicast pattern for mDNS 224.0.0.251,
+# SSDP 239.255.255.250 and LLMNR 224.0.0.252
+ssdp=0
+
+# Regulatory Setting; 0=STRICT; 1=CUSTOM
+gRegulatoryChangeCountry=1
+
+# RA filtering rate limit param, the current value would not
+# help if the lifetime in RA is less than 3*60=3min. Then
+# we need to change it, though it is uncommon.
+# gRAFilterEnable=0
+gRArateLimitInterval=600
+
+# Disable/Enable GreenAP
+# 0 to disable, 1 to enable, default: 1
+gEnableGreenAp=0
+
+#Enable/Disable LPASS support
+# 0 to disable, 1 to enable
+gEnableLpassSupport=1
+
+# Whether userspace country code setting shld have priority
+gCountryCodePriority=1
+
+# Enable or Disable Multi-user MIMO
+# 1=Enable (default), 0=Disable
+gEnableMuBformee=1
+
+# Inactivity time (in ms) to end TX Service Period while in IBSS power save mode
+gIbssTxSpEndInactivityTime=10
+
+#############################################
+# TDLS related configurations
+#############################################
+# Enable support for TDLS
+# 0 - disable
+# 1 - enable
+gEnableTDLSSupport=1
+
+# Enable support for Implicit Trigger of TDLS. That is, wlan driver shall
+# initiate TDLS Discovery towards a peer whenever setup criteria (throughput
+# and RSSI) is met and then will initiate teardown when teardown criteria
+# (idle packet count and RSSI) is met.
+# 0 - disable
+# 1 - enable
+gEnableTDLSImplicitTrigger=1
+
+# Enable support for TDLS off-channel operation
+# 0 - disable
+# 1 - enable
+# TDLS off-channel operation will be invoked when there is only one
+# TDLS connection.
+gEnableTDLSOffChannel=1
+
+# Tx/Rx Packet threshold for initiating TDLS.
+# This ini is used to configure the number of Tx/Rx packets during the period of
+# gTDLSTxStatsPeriod when exceeded, a TDLS Discovery request is triggered.
+gTDLSTxPacketThreshold=10
+
+# Number of idle packet.
+# This ini is used to configure the number of Tx/Rx packet, below which
+# within last gTDLSTxStatsPeriod period is considered as idle condition.
+gTDLSIdlePacketThreshold=1
+
+# VHT Tx/Rx MCS values
+# Valid values are 0,1,2. If commented out, the default value is 0.
+# 0=MCS0-7, 1=MCS0-8, 2=MCS0-9
+gVhtRxMCS=2
+gVhtTxMCS=2
+
+# VHT Tx/Rx MCS values for 2x2
+# Valid values are 0,1,2. If commented out, the default value is 0.
+# 0=MCS0-7, 1=MCS0-8, 2=MCS0-9
+gEnable2x2=1
+gVhtRxMCS2x2=2
+gVhtTxMCS2x2=2
+
+#IPA config is a bit mask and following are the configurations.
+#bit0 IPA Enable
+#bit1 IPA PRE Filter enable
+#bit2 IPv6 enable
+#bit3 IPA Resource Manager (RM) enable
+#bit4 IPA Clock scaling enable
+#bit5 IPA uC ENABLE
+#bit6 IPA uC STA ENABLE
+#bit8 IPA Real Time Debugging
+gIPAConfig=0x7d
+
+# Enable Rx handling options
+# Rx_thread=1 RPS=2(default for ROME) NAPI=4(default for ihelium)
+# Rx_thread + NAPI = 5
+rx_mode=5
+
+# Enable(Tx) fastpath for data traffic.
+# 1 - enable(default) 0 - disable
+gEnableFastPath=1
+
+# Enable TCP Segmentation Offload
+# 1 - enable 0 - disable
+TSOEnable=1
+
+# Enable Generic Receive Offload
+# LRO and GRO are exclusive to each other
+# LRO support is deprecated on latest 4.9(SDM845) kernel
+# 1 - enable(default) 0 - disable
+GROEnable=1
+
+# Enable HT MPDU Density
+# 4 for 2 micro sec
+ght_mpdu_density=4
+
+# Enable flow steering to enable multiple CEs for Rx flows.
+# Multiple Rx CEs<==>Multiple Rx IRQs<==>probably different CPUs.
+# Parallel Rx paths.
+# 1 - enable 0 - disable(default)
+gEnableFlowSteering=1
+
+# Time in microseconds after which a NAPI poll must yield
+ce_service_max_yield_time=500
+
+#Maximum number of HTT messages to be processed per NAPI poll
+ce_service_max_rx_ind_flush=1
+
+# Maximum number of MSDUs the firmware will pack in one HTT_T2H_MSG_TYPE_RX_IN_ORD_PADDR_IND
+maxMSDUsPerRxInd=8
+################ Datapath feature set End ################
+
+################ NAN feature set start ###################
+
+# Enable NAN discovery (NAN 1.0)
+# 1 - enable 0 - disable(default)
+gEnableNanSupport=1
+################ NAN feature set end #####################
+
+hostscan_adaptive_dwell_mode=1
+
+# Create another interface during driver load
+gEnableConcurrentSTA=wlan1
+
+#Enable/Disable dual MAC feature
+# 0 - enable DBS
+# 1 - disable DBS
+# 2 - disable DBS for connection but keep DBS for scan
+# 3 - disable DBS for connection but keep DBS scan with async
+# scan policy disabled
+# 4 - enable DBS for connection as well as for scan with async
+# scan policy disabled
+# 5 - enable DBS for connection but disable dbs for scan.
+# 6 - enable DBS for connection but disable simultaneous scan from
+# upper layer (DBS scan remains enabled in FW).
+gDualMacFeatureDisable=6
+
+#Enable/Disable latency mode
+# 0 disable
+# 1 enable
+wlm_latency_enable=1
+
+# Enable/Disable NUD Tracking within driver
+gEnableNUDTracking=0
+
+# Configure hardware filter for DTIM mode
+# The hardware filter is only effective in DTIM mode.
+# Use this configuration to blanket drop broadcast/multicast packets at the hardware level
+# without waking up the firmware
+#
+# Takes a bitmap of frame types to drop
+#
+# 0 = disable feature
+# 1 = drop all broadcast frames, except ARP (default)
+# 2 = drop all multicast frames, except ICMPv6
+# 3 = drop all broadcast and multicast frames, except ARP and ICMPv6
+gHwFilterMode=0
+
+# Enables SNR Monitoring
+# This ini is used to set default snr monitor
+gEnableSNRMonitoring=1
+
+# Control to enable TCP limit output byte
+# This ini is used to enable dynamic configuration of TCP limit output bytes
+# tcp_limit_output_bytes param.
+# Enabling this will let driver post message to cnss-daemon,
+# accordingly cnss-daemon will modify the tcp_limit_output_bytes.
+gTcpLimitOutputEnable=0
+
+# Enable Target Wake Time support.
+# This ini is used to enable or disable TWT support.
+enable_twt=0
+
+# For NLO/PNO, enable MAWC based scan
+# Enable/Disable the Motion Aided Wireless Connectivity based NLO using this parameter
+mawc_nlo_enabled=0
+
+# Force 1x1 when connecting to certain peer
+# This INI when enabled will force 1x1 connection with certain peer.
+gForce1x1Exception=0
+
+# Enable/disable oce feature for STA
+# This ini is used to enable/disable oce feature for STA
+oce_sta_enable=0
+
+# Enable/disable oce feature for SAP
+# This ini is used to enable/disable oce feature for SAP
+oce_sap_enable=0
+
+# Set probe request rate
+# This ini is used to set probe request rate to 5.5Mbps as per OCE requirement in 2.4G band
+oce_enable_probe_req_rate=0
+
+# HE caps Weightage to calculate best candidate
+# This ini is used to increase/decrease HE caps weightage in best candidate selection.
+# If AP supports HE caps, AP will get additional weightage with this param.
+# Weightage will be given only if dot11mode is HE capable.
+he_caps_weightage=0
+
+# PCL Weightage to calculate best candidate
+# This ini is used to increase/decrease PCL weightage in best candidate selection.
+# If some APs are in PCL list, those AP will get addition weightage.
+pcl_weightage=0
+
+# Enable/disable esp feature
+# This ini is used to enable/disable ESP(Estimated service parameters) IE parsing and decides
+# whether firmware will include this in its scoring algo.
+enable_esp_for_roam=0
+
+# Bitmask to enable 11k offload to FW.
+# This ini is used to set which of the 11k features is offloaded to FW
+# Currently Neighbor Report Request is supported for offload and is enabled by default.
+# B0: Offload 11k neighbor report requests
+# B1-B31: Reserved
+11k_offload_enable_bitmask=0
+
+# Set channel selection logic for different concurrency combinations to DBS or inter band MCC.
+# Default is DBS for STA+STA and STA+P2P.
+# 0 - inter-band MCC
+# 1 - DBS
+#
+# BIT 0: STA+STA
+# BIT 1: STA+P2P
+# BIT 2-31: Reserved
+channel_select_logic_conc=0
+
+# Configure BTM
+# Bit 0: Enable/Disable the BTM offload. Set this to 1 will enable and 0 will disable BTM offload.
+# BIT 2, 1: Action on non matching candidate with cache. If a BTM request is received from AP
+# then the candidate AP's may/may-not be present in the firmware scan cache.
+# Based on below config firmware will decide whether to forward BTM frame to host or
+# consume with firmware and proceed with Roaming to candidate AP.
+#
+# 00 scan and consume
+# 01 no scan and forward to host
+# 10, 11 reserved
+# BIT 5, 4, 3: Roaming handoff decisions on multiple candidates match
+# 000 match if exact BSSIDs are found
+# 001 match if at least one top priority BSSID only
+# 010, 011, 100, 101, 110, 111 reserved
+# BIT 6: Set this to 1 will send BTM query frame and 0 not sent.
+# BIT 7-31: Reserved
+btm_offload_config=0
+
+#Timer waiting for interface up from the upper layer
+gInterfaceChangeWait=1000
+
+END
+
+# Note: Configuration parser would not read anything past the END marker
+
diff --git a/aosp_sunfish.mk b/aosp_sunfish.mk
new file mode 100644
index 00000000..6b55fa22
--- /dev/null
+++ b/aosp_sunfish.mk
@@ -0,0 +1,47 @@
+#
+# Copyright 2019 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.
+#
+
+# Inherit from the common Open Source product configuration
+$(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit.mk)
+$(call inherit-product, $(SRC_TARGET_DIR)/product/mainline.mk)
+
+$(call inherit-product, device/google/sunfish/device-sunfish.mk)
+$(call inherit-product-if-exists, vendor/google_devices/sunfish/proprietary/device-vendor.mk)
+$(call inherit-product-if-exists, vendor/google_devices/sunfish/prebuilts/device-vendor-sunfish.mk)
+
+PRODUCT_PROPERTY_OVERRIDES += \
+ ro.config.ringtone=Ring_Synth_04.ogg \
+ ro.com.android.dataroaming=true \
+
+PRODUCT_PACKAGES += \
+ PhotoTable \
+ WallpaperPicker \
+ WAPPushManager \
+
+# Don't build super.img.
+PRODUCT_BUILD_SUPER_PARTITION := false
+
+# STOPSHIP deal with Qualcomm stuff later
+# PRODUCT_RESTRICT_VENDOR_FILES := all
+
+PRODUCT_MANUFACTURER := Google
+PRODUCT_BRAND := Android
+PRODUCT_NAME := aosp_sunfish
+PRODUCT_DEVICE := sunfish
+PRODUCT_MODEL := AOSP on sunfish
+
+PRODUCT_COPY_FILES += \
+ device/sample/etc/apns-full-conf.xml:$(TARGET_COPY_OUT_PRODUCT)/etc/apns-conf.xml
diff --git a/board-info.txt b/board-info.txt
new file mode 100644
index 00000000..6df05a1a
--- /dev/null
+++ b/board-info.txt
@@ -0,0 +1 @@
+require board=sunfish
diff --git a/compatibility_matrix.xml b/compatibility_matrix.xml
new file mode 100644
index 00000000..8b06eef7
--- /dev/null
+++ b/compatibility_matrix.xml
@@ -0,0 +1,58 @@
+
+
+ android.frameworks.schedulerservice
+ 1.0
+
+ ISchedulingPolicyService
+ default
+
+
+
+ android.frameworks.sensorservice
+ 1.0
+
+ ISensorManager
+ default
+
+
+
+ android.hidl.allocator
+ 1.0
+
+ IAllocator
+ ashmem
+
+
+
+ android.hidl.manager
+ 1.0
+
+ IServiceManager
+ default
+
+
+
+ android.hidl.memory
+ 1.0
+
+ IMapper
+ ashmem
+
+
+
+ android.hidl.token
+ 1.0
+
+ ITokenManager
+ default
+
+
+
+ android.system.wifi.keystore
+ 1.0
+
+ IKeystore
+ default
+
+
+
diff --git a/config.fs b/config.fs
new file mode 100644
index 00000000..5dcbfc1b
--- /dev/null
+++ b/config.fs
@@ -0,0 +1,88 @@
+# Copyright (C) 2018 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 used to define the properties of the filesystem
+# images generated by build tools (mkbootfs and mkyaffs2image) and
+# by the device side of adb.
+
+[AID_VENDOR_QDSS]
+value:2902
+
+[AID_VENDOR_RFS]
+value:2903
+
+[AID_VENDOR_RFS_SHARED]
+value:2904
+
+[AID_VENDOR_ADPL_ODL]
+value:2905
+
+[AID_VENDOR_QRTR]
+value:2906
+
+[vendor/bin/cnss-daemon]
+mode: 0755
+user: AID_BLUETOOTH
+group: AID_BLUETOOTH
+caps: NET_BIND_SERVICE
+
+[vendor/bin/pm-service]
+mode: 0755
+user: AID_SYSTEM
+group: AID_SYSTEM
+caps: NET_BIND_SERVICE
+
+[vendor/bin/imsdatadaemon]
+mode: 0755
+user: AID_RADIO
+group: AID_RADIO
+caps: NET_BIND_SERVICE
+
+[vendor/bin/ims_rtp_daemon]
+mode: 0755
+user: AID_RADIO
+group: AID_RADIO
+caps: NET_BIND_SERVICE
+
+[vendor/bin/imsrcsd]
+mode: 0755
+user: AID_RADIO
+group: AID_RADIO
+caps: NET_BIND_SERVICE BLOCK_SUSPEND WAKE_ALARM
+
+[vendor/bin/cnd]
+mode: 0755
+user: AID_SYSTEM
+group: AID_SYSTEM
+caps: NET_BIND_SERVICE BLOCK_SUSPEND NET_ADMIN
+
+[vendor/bin/hw/android.hardware.health@2.0-service.sunfish]
+mode: 0755
+user: AID_SYSTEM
+group: AID_SYSTEM
+caps: WAKE_ALARM
+
+[vendor/bin/loc_launcher]
+mode: 0755
+user: AID_GPS
+group: AID_GPS
+caps: SETUID SETGID
+
+[system/vendor/bin/loc_launcher]
+mode: 0755
+user: AID_GPS
+group: AID_GPS
+caps: SETUID SETGID
+
diff --git a/default-permissions.xml b/default-permissions.xml
new file mode 100644
index 00000000..ce59726b
--- /dev/null
+++ b/default-permissions.xml
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/device-common.mk b/device-common.mk
new file mode 100644
index 00000000..34e1bcde
--- /dev/null
+++ b/device-common.mk
@@ -0,0 +1,67 @@
+#
+# Copyright (C) 2019 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 hardware platform
+PRODUCT_PLATFORM := sm7150
+
+include device/google/sunfish/device.mk
+
+# Set Vendor SPL to match platform
+VENDOR_SECURITY_PATCH = $(PLATFORM_SECURITY_PATCH)
+
+# A2DP offload enabled for compilation
+AUDIO_FEATURE_ENABLED_A2DP_OFFLOAD := true
+
+# A2DP offload supported
+PRODUCT_PROPERTY_OVERRIDES += \
+ro.bluetooth.a2dp_offload.supported=true
+
+# A2DP offload disabled (UI toggle property)
+PRODUCT_PROPERTY_OVERRIDES += \
+persist.bluetooth.a2dp_offload.disabled=false
+
+# A2DP offload DSP supported encoder list
+PRODUCT_PROPERTY_OVERRIDES += \
+persist.bluetooth.a2dp_offload.cap=sbc-aac-aptx-aptxhd-ldac
+
+# Enable AAC frame ctl for A2DP sinks
+PRODUCT_PROPERTY_OVERRIDES += \
+persist.vendor.bt.aac_frm_ctl.enabled=true
+
+# Set lmkd options
+PRODUCT_PRODUCT_PROPERTIES += \
+ ro.config.low_ram = false \
+ ro.lmk.kill_heaviest_task = true \
+ ro.lmk.kill_timeout_ms = 100 \
+ ro.lmk.use_minfree_levels = true \
+ ro.lmk.log_stats = true \
+
+# Modem loging file
+PRODUCT_COPY_FILES += \
+ device/google/sunfish/init.logging.rc:$(TARGET_COPY_OUT_VENDOR)/etc/init/hw/init.$(PRODUCT_PLATFORM).logging.rc
+
+# Pixelstats broken mic detection
+PRODUCT_PROPERTY_OVERRIDES += vendor.audio.mic_break=true
+
+PRODUCT_DEFAULT_PROPERTY_OVERRIDES += ro.surface_flinger.use_color_management=true
+PRODUCT_DEFAULT_PROPERTY_OVERRIDES += ro.surface_flinger.has_wide_color_display=true
+PRODUCT_DEFAULT_PROPERTY_OVERRIDES += ro.surface_flinger.has_HDR_display=true
+PRODUCT_DEFAULT_PROPERTY_OVERRIDES += ro.surface_flinger.set_idle_timer_ms=50
+
+# MIDI feature
+PRODUCT_COPY_FILES += \
+ frameworks/native/data/etc/android.software.midi.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.software.midi.xml
+
diff --git a/device-sunfish.mk b/device-sunfish.mk
new file mode 100644
index 00000000..6dcf75f7
--- /dev/null
+++ b/device-sunfish.mk
@@ -0,0 +1,22 @@
+#
+# Copyright 2019 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_HARDWARE := sunfish
+
+include device/google/sunfish/device-common.mk
+
+DEVICE_PACKAGE_OVERLAYS += device/google/sunfish/sunfish/overlay
+
diff --git a/device.mk b/device.mk
new file mode 100644
index 00000000..31def0fb
--- /dev/null
+++ b/device.mk
@@ -0,0 +1,767 @@
+#
+# Copyright (C) 2019 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 := device/google/sunfish
+
+PRODUCT_VENDOR_MOVE_ENABLED := true
+
+PRODUCT_SOONG_NAMESPACES += \
+ device/google/sunfish \
+ hardware/google/av \
+ hardware/google/interfaces \
+ hardware/google/pixel \
+ hardware/qcom/sm7150 \
+ hardware/qcom/sm7150/display \
+ vendor/google/camera \
+ vendor/qcom/sm7150 \
+ vendor/google/interfaces
+
+PRODUCT_PROPERTY_OVERRIDES += \
+ keyguard.no_require_sim=true
+
+# enable cal by default on accel sensor
+PRODUCT_PRODUCT_PROPERTIES += \
+ persist.debug.sensors.accel_cal=1
+
+# The default value of this variable is false and should only be set to true when
+# the device allows users to retain eSIM profiles after factory reset of user data.
+PRODUCT_PRODUCT_PROPERTIES += \
+ masterclear.allow_retain_esim_profiles_after_fdr=true
+
+PRODUCT_COPY_FILES += \
+ device/google/sunfish/default-permissions.xml:$(TARGET_COPY_OUT_PRODUCT)/etc/default-permissions/default-permissions.xml \
+ frameworks/native/data/etc/handheld_core_hardware.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/handheld_core_hardware.xml \
+ frameworks/native/data/etc/android.software.verified_boot.xml:$(TARGET_COPY_OUT_PRODUCT)/etc/permissions/android.software.verified_boot.xml
+
+PRODUCT_PACKAGES += \
+ messaging
+
+TARGET_PRODUCT_PROP := $(LOCAL_PATH)/product.prop
+
+$(call inherit-product, $(LOCAL_PATH)/utils.mk)
+
+# Installs gsi keys into ramdisk, to boot a GSI with verified boot.
+$(call inherit-product, $(SRC_TARGET_DIR)/product/gsi_keys.mk)
+
+ifeq ($(wildcard vendor/google_devices/sunfish/proprietary/device-vendor-sunfish.mk),)
+ BUILD_WITHOUT_VENDOR := true
+endif
+
+ifeq ($(TARGET_PREBUILT_KERNEL),)
+ LOCAL_KERNEL := device/google/sunfish-kernel/Image.lz4
+else
+ LOCAL_KERNEL := $(TARGET_PREBUILT_KERNEL)
+endif
+PRODUCT_VENDOR_KERNEL_HEADERS := device/google/sunfish-kernel/sm7150/kernel-headers
+
+
+PRODUCT_CHARACTERISTICS := nosdcard
+PRODUCT_SHIPPING_API_LEVEL := 28
+
+DEVICE_PACKAGE_OVERLAYS += $(LOCAL_PATH)/overlay
+
+PRODUCT_COPY_FILES += \
+ $(LOCAL_KERNEL):kernel \
+ $(LOCAL_PATH)/fstab.hardware:$(TARGET_COPY_OUT_RECOVERY)/root/first_stage_ramdisk/fstab.$(PRODUCT_PLATFORM) \
+ $(LOCAL_PATH)/fstab.hardware:$(TARGET_COPY_OUT_VENDOR)/etc/fstab.$(PRODUCT_PLATFORM) \
+ $(LOCAL_PATH)/fstab.persist:$(TARGET_COPY_OUT_VENDOR)/etc/fstab.persist \
+ $(LOCAL_PATH)/init.hardware.rc:$(TARGET_COPY_OUT_VENDOR)/etc/init/hw/init.$(PRODUCT_PLATFORM).rc \
+ $(LOCAL_PATH)/init.power.rc:$(TARGET_COPY_OUT_VENDOR)/etc/init/hw/init.$(PRODUCT_PLATFORM).power.rc \
+ $(LOCAL_PATH)/init.radio.sh:$(TARGET_COPY_OUT_VENDOR)/bin/init.radio.sh \
+ $(LOCAL_PATH)/uinput-fpc.kl:$(TARGET_COPY_OUT_VENDOR)/usr/keylayout/uinput-fpc.kl \
+ $(LOCAL_PATH)/uinput-fpc.idc:$(TARGET_COPY_OUT_VENDOR)/usr/idc/uinput-fpc.idc \
+ $(LOCAL_PATH)/init.hardware.usb.rc:$(TARGET_COPY_OUT_VENDOR)/etc/init/hw/init.$(PRODUCT_PLATFORM).usb.rc \
+ $(LOCAL_PATH)/init.insmod.sh:$(TARGET_COPY_OUT_VENDOR)/bin/init.insmod.sh \
+ $(LOCAL_PATH)/init.qcom.wlan.sh:$(TARGET_COPY_OUT_VENDOR)/bin/init.qcom.wlan.sh \
+ $(LOCAL_PATH)/init.sensors.sh:$(TARGET_COPY_OUT_VENDOR)/bin/init.sensors.sh \
+ $(LOCAL_PATH)/sensors.hals.conf:$(TARGET_COPY_OUT_VENDOR)/etc/sensors/hals.conf \
+ $(LOCAL_PATH)/thermal-engine-$(PRODUCT_HARDWARE).conf:$(TARGET_COPY_OUT_VENDOR)/etc/thermal-engine-$(PRODUCT_HARDWARE).conf \
+ $(LOCAL_PATH)/ueventd.rc:$(TARGET_COPY_OUT_VENDOR)/ueventd.rc \
+
+MSM_VIDC_TARGET_LIST := sm6150 # Get the color format from kernel headers
+MASTER_SIDE_CP_TARGET_LIST := sm6150 # ION specific settings
+
+ifneq (,$(filter userdebug eng, $(TARGET_BUILD_VARIANT)))
+ PRODUCT_COPY_FILES += \
+ $(LOCAL_PATH)/init.hardware.diag.rc.userdebug:$(TARGET_COPY_OUT_VENDOR)/etc/init/hw/init.$(PRODUCT_PLATFORM).diag.rc
+ PRODUCT_COPY_FILES += \
+ $(LOCAL_PATH)/init.hardware.mpssrfs.rc.userdebug:$(TARGET_COPY_OUT_VENDOR)/etc/init/hw/init.$(PRODUCT_PLATFORM).mpssrfs.rc
+ PRODUCT_COPY_FILES += \
+ $(LOCAL_PATH)/init.hardware.chamber.rc.userdebug:$(TARGET_COPY_OUT_VENDOR)/etc/init/init.$(PRODUCT_PLATFORM).chamber.rc
+ PRODUCT_COPY_FILES += \
+ $(LOCAL_PATH)/init.hardware.ipa.rc.userdebug:$(TARGET_COPY_OUT_VENDOR)/etc/init/init.$(PRODUCT_PLATFORM).ipa.rc
+else
+ PRODUCT_COPY_FILES += \
+ $(LOCAL_PATH)/init.hardware.diag.rc.user:$(TARGET_COPY_OUT_VENDOR)/etc/init/hw/init.$(PRODUCT_PLATFORM).diag.rc
+ PRODUCT_COPY_FILES += \
+ $(LOCAL_PATH)/init.hardware.mpssrfs.rc.user:$(TARGET_COPY_OUT_VENDOR)/etc/init/hw/init.$(PRODUCT_PLATFORM).mpssrfs.rc
+endif
+
+# A/B support
+PRODUCT_PACKAGES += \
+ otapreopt_script \
+ cppreopts.sh \
+ update_engine \
+ update_verifier
+
+# Use Sdcardfs
+PRODUCT_PRODUCT_PROPERTIES += \
+ ro.sys.sdcardfs=1
+
+PRODUCT_PACKAGES += \
+ bootctrl.sm6150
+
+PRODUCT_PROPERTY_OVERRIDES += \
+ ro.cp_system_other_odex=1
+
+AB_OTA_POSTINSTALL_CONFIG += \
+ RUN_POSTINSTALL_system=true \
+ POSTINSTALL_PATH_system=system/bin/otapreopt_script \
+ FILESYSTEM_TYPE_system=ext4 \
+ POSTINSTALL_OPTIONAL_system=true
+
+# Enable update engine sideloading by including the static version of the
+# boot_control HAL and its dependencies.
+PRODUCT_STATIC_BOOT_CONTROL_HAL := \
+ bootctrl.sm6150 \
+ libgptutils \
+ libz \
+ libcutils
+
+PRODUCT_PACKAGES += \
+ update_engine_sideload \
+ sg_write_buffer \
+ f2fs_io \
+ check_f2fs
+
+AB_OTA_POSTINSTALL_CONFIG += \
+ RUN_POSTINSTALL_vendor=true \
+ POSTINSTALL_PATH_vendor=bin/checkpoint_gc \
+ FILESYSTEM_TYPE_vendor=ext4 \
+ POSTINSTALL_OPTIONAL_vendor=true
+
+# Userdata Checkpointing OTA GC
+PRODUCT_PACKAGES += \
+ checkpoint_gc
+
+# The following modules are included in debuggable builds only.
+PRODUCT_PACKAGES_DEBUG += \
+ bootctl \
+ r.vendor \
+ update_engine_client
+
+PRODUCT_COPY_FILES += \
+ frameworks/native/data/etc/android.hardware.camera.flash-autofocus.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.camera.flash-autofocus.xml \
+ frameworks/native/data/etc/android.hardware.camera.front.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.camera.front.xml \
+ frameworks/native/data/etc/android.hardware.camera.full.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.camera.full.xml\
+ frameworks/native/data/etc/android.hardware.camera.raw.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.camera.raw.xml\
+ frameworks/native/data/etc/android.hardware.bluetooth.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.bluetooth.xml \
+ frameworks/native/data/etc/android.hardware.bluetooth_le.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.bluetooth_le.xml \
+ frameworks/native/data/etc/android.hardware.biometrics.face.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.biometrics.face.xml\
+ frameworks/native/data/etc/android.hardware.sensor.accelerometer.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.sensor.accelerometer.xml \
+ frameworks/native/data/etc/android.hardware.sensor.assist.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.sensor.assist.xml \
+ frameworks/native/data/etc/android.hardware.sensor.compass.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.sensor.compass.xml \
+ frameworks/native/data/etc/android.hardware.sensor.gyroscope.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.sensor.gyroscope.xml \
+ frameworks/native/data/etc/android.hardware.sensor.light.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.sensor.light.xml \
+ frameworks/native/data/etc/android.hardware.sensor.proximity.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.sensor.proximity.xml \
+ frameworks/native/data/etc/android.hardware.sensor.barometer.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.sensor.barometer.xml \
+ frameworks/native/data/etc/android.hardware.sensor.stepcounter.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.sensor.stepcounter.xml \
+ frameworks/native/data/etc/android.hardware.sensor.stepdetector.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.sensor.stepdetector.xml \
+ frameworks/native/data/etc/android.hardware.sensor.hifi_sensors.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.sensor.hifi_sensors.xml \
+ frameworks/native/data/etc/android.hardware.location.gps.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.location.gps.xml \
+ frameworks/native/data/etc/android.hardware.telephony.gsm.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.telephony.gsm.xml \
+ frameworks/native/data/etc/android.hardware.telephony.cdma.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.telephony.cdma.xml \
+ frameworks/native/data/etc/android.hardware.telephony.ims.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.telephony.ims.xml \
+ frameworks/native/data/etc/android.hardware.touchscreen.multitouch.jazzhand.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.touchscreen.multitouch.jazzhand.xml \
+ frameworks/native/data/etc/android.hardware.wifi.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.wifi.xml \
+ frameworks/native/data/etc/android.hardware.wifi.direct.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.wifi.direct.xml \
+ frameworks/native/data/etc/android.hardware.wifi.aware.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.wifi.aware.xml \
+ frameworks/native/data/etc/android.hardware.wifi.passpoint.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.wifi.passpoint.xml \
+ frameworks/native/data/etc/android.hardware.wifi.rtt.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.wifi.rtt.xml \
+ frameworks/native/data/etc/android.software.sip.voip.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.software.sip.voip.xml \
+ frameworks/native/data/etc/android.hardware.usb.accessory.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.usb.accessory.xml \
+ frameworks/native/data/etc/android.hardware.usb.host.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.usb.host.xml \
+ frameworks/native/data/etc/android.hardware.opengles.aep.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.opengles.aep.xml \
+ frameworks/native/data/etc/android.hardware.nfc.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.nfc.xml \
+ frameworks/native/data/etc/android.hardware.nfc.hce.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.nfc.hce.xml \
+ frameworks/native/data/etc/android.hardware.nfc.hcef.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.nfc.hcef.xml \
+ frameworks/native/data/etc/android.hardware.vulkan.level-1.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.vulkan.level.xml \
+ frameworks/native/data/etc/android.hardware.vulkan.compute-0.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.vulkan.compute.xml \
+ frameworks/native/data/etc/android.hardware.vulkan.version-1_1.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.vulkan.version.xml \
+ frameworks/native/data/etc/android.hardware.telephony.carrierlock.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.telephony.carrierlock.xml \
+ frameworks/native/data/etc/android.hardware.strongbox_keystore.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.strongbox_keystore.xml \
+ frameworks/native/data/etc/android.hardware.nfc.uicc.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.nfc.uicc.xml \
+ frameworks/native/data/etc/android.hardware.nfc.ese.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.nfc.ese.xml
+
+# Audio fluence, ns, aec property, voice and media volume steps
+PRODUCT_PROPERTY_OVERRIDES += \
+ ro.vendor.audio.sdk.fluencetype=fluencepro \
+ persist.audio.fluence.voicecall=true \
+ persist.audio.fluence.speaker=true \
+ persist.audio.fluence.voicecomm=true \
+ persist.audio.fluence.voicerec=false \
+ ro.config.vc_call_vol_steps=7 \
+ ro.config.media_vol_steps=25 \
+
+# Audio Features
+PRODUCT_PROPERTY_OVERRIDES += \
+ vendor.audio.feature.external_dsp.enable=true \
+ vendor.audio.feature.external_speaker.enable=true \
+ vendor.audio.feature.concurrent_capture.enable=false \
+ vendor.audio.feature.a2dp_offload.enable=true \
+ vendor.audio.feature.hfp.enable=true \
+ vendor.audio.feature.hwdep_cal.enable=true \
+ vendor.audio.feature.incall_music.enable=true \
+ vendor.audio.feature.maxx_audio.enable=true \
+ vendor.audio.feature.spkr_prot.enable=true \
+ vendor.audio.feature.usb_offload.enable=true \
+ vendor.audio.feature.audiozoom.enable=true \
+ vendor.audio.feature.snd_mon.enable=true \
+
+# MaxxAudio effect and add rotation monitor
+PRODUCT_PROPERTY_OVERRIDES += \
+ ro.audio.monitorRotation=true
+
+# Iaxxx streming and factory binary
+PRODUCT_PACKAGES += \
+ libtunnel \
+ libodsp \
+ adnc_strm.primary.default
+
+# graphics
+PRODUCT_PROPERTY_OVERRIDES += \
+ ro.opengles.version=196610
+
+PRODUCT_PROPERTY_OVERRIDES += \
+ ro.vendor.display.foss=1 \
+ ro.vendor.display.paneltype=2 \
+ ro.vendor.display.sensortype=2 \
+ vendor.display.foss.config=1 \
+ vendor.display.foss.config_path=/vendor/etc/FOSSConfig.xml
+
+# camera hal buffer management
+PRODUCT_PROPERTY_OVERRIDES += \
+ persist.camera.managebuffer.enable=1
+
+# Lets the vendor library that Google Camera HWL is enabled
+PRODUCT_PROPERTY_OVERRIDES += \
+ persist.camera.google_hwl.enabled=true \
+ persist.camera.google_hwl.name=libgooglecamerahwl_impl.so
+
+# OEM Unlock reporting
+PRODUCT_DEFAULT_PROPERTY_OVERRIDES += \
+ ro.oem_unlock_supported=1
+
+PRODUCT_PROPERTY_OVERRIDES += \
+ persist.vendor.cne.feature=1 \
+ persist.vendor.data.iwlan.enable=true \
+ persist.radio.RATE_ADAPT_ENABLE=1 \
+ persist.radio.ROTATION_ENABLE=1 \
+ persist.radio.VT_ENABLE=1 \
+ persist.radio.VT_HYBRID_ENABLE=1 \
+ persist.vendor.radio.apm_sim_not_pwdn=1 \
+ persist.vendor.radio.custom_ecc=1 \
+ persist.vendor.radio.data_ltd_sys_ind=1 \
+ persist.radio.videopause.mode=1 \
+ persist.vendor.radio.multisim_switch_support=true \
+ persist.vendor.radio.sib16_support=1 \
+ persist.vendor.radio.data_con_rprt=true \
+ persist.vendor.radio.relay_oprt_change=1 \
+ persist.vendor.radio.no_wait_for_card=1 \
+ persist.vendor.radio.sap_silent_pin=1 \
+ persist.rcs.supported=1 \
+ vendor.rild.libpath=/vendor/lib64/libril-qc-hal-qmi.so \
+ ro.hardware.keystore_desede=true \
+
+# Disable snapshot timer
+PRODUCT_PROPERTY_OVERRIDES += \
+ persist.vendor.radio.snapshot_enabled=0 \
+ persist.vendor.radio.snapshot_timer=0
+
+PRODUCT_PACKAGES += \
+ hwcomposer.sm6150 \
+ android.hardware.graphics.composer@2.3-service-sm7150 \
+ gralloc.sm6150 \
+ android.hardware.graphics.mapper@3.0-impl-qti-display \
+ vendor.qti.hardware.display.allocator-service
+
+# RenderScript HAL
+PRODUCT_PACKAGES += \
+ android.hardware.renderscript@1.0-impl
+
+# Light HAL
+PRODUCT_PACKAGES += \
+ lights.sm6150 \
+ hardware.google.light@1.0-service
+
+# Memtrack HAL
+PRODUCT_PACKAGES += \
+ memtrack.sm6150 \
+ android.hardware.memtrack@1.0-impl \
+ android.hardware.memtrack@1.0-service
+
+# Bluetooth HAL
+PRODUCT_PACKAGES += \
+ android.hardware.bluetooth@1.0-impl-qti \
+ android.hardware.bluetooth@1.0-service-qti
+
+#Bluetooth SAR HAL
+PRODUCT_PACKAGES += \
+ vendor.qti.hardware.bluetooth_sar@1.0-impl
+
+# Bluetooth SoC
+PRODUCT_PROPERTY_OVERRIDES += \
+ vendor.qcom.bluetooth.soc=cherokee
+
+# Property for loading BDA from device tree
+PRODUCT_PROPERTY_OVERRIDES += \
+ ro.vendor.bt.bdaddr_path=/proc/device-tree/chosen/cdt/cdb2/bt_addr
+
+# Bluetooth WiPower
+PRODUCT_PROPERTY_OVERRIDES += \
+ ro.vendor.bluetooth.emb_wp_mode=false \
+ ro.vendor.bluetooth.wipower=false
+
+# DRM HAL
+PRODUCT_PACKAGES += \
+ android.hardware.drm@1.0-impl \
+ android.hardware.drm@1.0-service \
+ android.hardware.drm@1.2-service.clearkey \
+ android.hardware.drm@1.2-service.widevine
+
+# NFC and Secure Element packages
+PRODUCT_PACKAGES += \
+ NfcNci \
+ Tag \
+ SecureElement \
+ android.hardware.nfc@1.2-service.st \
+ android.hardware.secure_element@1.0-service.st
+
+PRODUCT_COPY_FILES += \
+ device/google/sunfish/nfc/libnfc-hal-st.conf:$(TARGET_COPY_OUT_VENDOR)/etc/libnfc-hal-st.conf \
+ device/google/sunfish/nfc/libese-hal-st.conf:$(TARGET_COPY_OUT_VENDOR)/etc/libese-hal-st.conf \
+ device/google/sunfish/nfc/libnfc-nci.conf:$(TARGET_COPY_OUT_PRODUCT)/etc/libnfc-nci.conf
+
+PRODUCT_PACKAGES += \
+ android.hardware.usb@1.2-service.sunfish
+
+PRODUCT_PACKAGES += \
+ android.hardware.health@2.0-service.sunfish
+
+# Storage health HAL
+PRODUCT_PACKAGES += \
+ android.hardware.health.storage@1.0-service
+
+PRODUCT_PACKAGES += \
+ libmm-omxcore \
+ libOmxCore \
+ libstagefrighthw \
+ libOmxVdec \
+ libOmxVdecHevc \
+ libOmxVenc \
+ libc2dcolorconvert
+
+# Enable Codec 2.0
+PRODUCT_PACKAGES += \
+ libqcodec2 \
+ vendor.qti.media.c2@1.0-service \
+
+PRODUCT_PACKAGES += \
+ android.hardware.camera.provider@2.4-impl-google \
+ android.hardware.camera.provider@2.4-service-google \
+ camera.sm6150 \
+ libgooglecamerahal \
+ libgooglecamerahwl_impl \
+ libgoogle_camera_hal_tests \
+ libqomx_core \
+ libmmjpeg_interface \
+ libmmcamera_interface \
+ libcameradepthcalibrator
+
+PRODUCT_PACKAGES += \
+ sensors.$(PRODUCT_HARDWARE) \
+ android.hardware.sensors@2.0-impl \
+ android.hardware.sensors@2.0-service \
+ android.hardware.sensors@2.0-service.rc
+
+PRODUCT_PACKAGES += \
+ fs_config_dirs \
+ fs_config_files
+
+# Context hub HAL
+PRODUCT_PACKAGES += \
+ android.hardware.contexthub@1.0-impl.generic \
+ android.hardware.contexthub@1.0-service
+
+# Boot control HAL
+PRODUCT_PACKAGES += \
+ android.hardware.boot@1.0-impl \
+ android.hardware.boot@1.0-service \
+
+# Vibrator HAL
+PRODUCT_PACKAGES += \
+ android.hardware.vibrator@1.3-service.sunfish \
+
+# Thermal HAL
+PRODUCT_PACKAGES += \
+ android.hardware.thermal@2.0-service.pixel \
+
+# Thermal HAL config
+PRODUCT_COPY_FILES += \
+ $(LOCAL_PATH)/thermal_info_config_$(PRODUCT_HARDWARE).json:$(TARGET_COPY_OUT_VENDOR)/etc/thermal_info_config.json \
+
+#GNSS HAL
+PRODUCT_PACKAGES += \
+ libgps.utils \
+ libgnss \
+ liblocation_api \
+ android.hardware.gnss@2.0-impl-qti \
+ android.hardware.gnss@2.0-service-qti
+
+# Wireless Charger HAL
+PRODUCT_PACKAGES += \
+ vendor.google.wireless_charger@1.0
+
+ENABLE_VENDOR_RIL_SERVICE := true
+
+HOSTAPD := hostapd
+HOSTAPD += hostapd_cli
+PRODUCT_PACKAGES += $(HOSTAPD)
+
+WPA := wpa_supplicant.conf
+WPA += wpa_supplicant_wcn.conf
+WPA += wpa_supplicant
+PRODUCT_PACKAGES += $(WPA)
+
+ifneq (,$(filter userdebug eng, $(TARGET_BUILD_VARIANT)))
+PRODUCT_PACKAGES += wpa_cli
+endif
+
+# Wifi
+PRODUCT_PACKAGES += \
+ android.hardware.wifi@1.0-service \
+ wificond \
+ libwpa_client
+
+# WLAN driver configuration files
+PRODUCT_COPY_FILES += \
+ $(LOCAL_PATH)/wpa_supplicant_overlay.conf:$(TARGET_COPY_OUT_VENDOR)/etc/wifi/wpa_supplicant_overlay.conf \
+ $(LOCAL_PATH)/p2p_supplicant_overlay.conf:$(TARGET_COPY_OUT_VENDOR)/etc/wifi/p2p_supplicant_overlay.conf \
+ $(LOCAL_PATH)/wifi_concurrency_cfg.txt:$(TARGET_COPY_OUT_VENDOR)/etc/wifi/wifi_concurrency_cfg.txt \
+ $(LOCAL_PATH)/WCNSS_qcom_cfg.ini:$(TARGET_COPY_OUT_VENDOR)/firmware/wlan/qca_cld/WCNSS_qcom_cfg.ini \
+
+LIB_NL := libnl_2
+PRODUCT_PACKAGES += $(LIB_NL)
+
+# Factory OTA
+PRODUCT_PACKAGES += \
+ FactoryOta
+
+# Audio effects
+PRODUCT_PACKAGES += \
+ libvolumelistener \
+ libqcomvisualizer \
+ libqcomvoiceprocessing \
+ libqcomvoiceprocessingdescriptors \
+ libqcompostprocbundle
+
+PRODUCT_PACKAGES += \
+ audio.primary.sm6150 \
+ audio.a2dp.default \
+ audio.usb.default \
+ audio.r_submix.default \
+ libaudio-resampler \
+ audio.hearing_aid.default \
+ audio.bluetooth.default
+
+PRODUCT_PACKAGES += \
+ android.hardware.audio@5.0-impl:32 \
+ android.hardware.audio.effect@5.0-impl:32 \
+ android.hardware.broadcastradio@1.0-impl \
+ android.hardware.soundtrigger@2.2-impl \
+ android.hardware.bluetooth.audio@2.0-impl \
+ android.hardware.audio@2.0-service
+
+# Modules for Audio HAL
+PRODUCT_PACKAGES += \
+ libcirrusspkrprot \
+ libsndmonitor \
+ libmalistener \
+ liba2dpoffload \
+ btaudio_offload_if \
+ libmaxxaudio \
+ libaudiozoom
+
+ifneq (,$(filter userdebug eng, $(TARGET_BUILD_VARIANT)))
+PRODUCT_PACKAGES += \
+ tinyplay \
+ tinycap \
+ tinymix \
+ tinypcminfo \
+ cplay
+endif
+
+# Audio hal xmls
+
+# Audio Policy tables
+
+# Audio ACDB data
+
+# Audio ACDB workspace files for QACT
+
+# Audio speaker tunning config data
+
+# Audio audiozoom config data
+
+# and ensure that the xaac decoder is built
+PRODUCT_PACKAGES += \
+ libstagefright_soft_xaacdec.vendor
+
+PRODUCT_COPY_FILES += \
+ $(LOCAL_PATH)/media_codecs.xml:$(TARGET_COPY_OUT_VENDOR)/etc/media_codecs.xml \
+ frameworks/av/media/libstagefright/data/media_codecs_google_audio.xml:$(TARGET_COPY_OUT_VENDOR)/etc/media_codecs_google_audio.xml \
+ frameworks/av/media/libstagefright/data/media_codecs_google_telephony.xml:$(TARGET_COPY_OUT_VENDOR)/etc/media_codecs_google_telephony.xml \
+ frameworks/av/media/libstagefright/data/media_codecs_google_video.xml:$(TARGET_COPY_OUT_VENDOR)/etc/media_codecs_google_video.xml \
+ $(LOCAL_PATH)/media_profiles_V1_0.xml:$(TARGET_COPY_OUT_VENDOR)/etc/media_profiles_V1_0.xml
+
+# Vendor seccomp policy files for media components:
+PRODUCT_COPY_FILES += \
+ $(LOCAL_PATH)/seccomp_policy/mediacodec.policy:$(TARGET_COPY_OUT_VENDOR)/etc/seccomp_policy/mediacodec.policy
+
+PRODUCT_PROPERTY_OVERRIDES += \
+ audio.snd_card.open.retries=50
+
+
+ifneq (,$(filter userdebug eng, $(TARGET_BUILD_VARIANT)))
+# Subsystem ramdump
+PRODUCT_PROPERTY_OVERRIDES += \
+ persist.vendor.sys.ssr.enable_ramdumps=1
+endif
+
+# Subsystem silent restart
+PRODUCT_PROPERTY_OVERRIDES += \
+ persist.vendor.sys.ssr.restart_level=modem,SDXPRAIRIE,adsp,slpi
+
+# setup dalvik vm configs
+$(call inherit-product, frameworks/native/build/phone-xhdpi-2048-dalvik-heap.mk)
+
+# Use the default charger mode images
+PRODUCT_PACKAGES += \
+ charger_res_images
+
+ifneq (,$(filter userdebug eng, $(TARGET_BUILD_VARIANT)))
+# b/36703476: Set default log size to 1M
+PRODUCT_PROPERTY_OVERRIDES += \
+ ro.logd.size=1M
+# b/114766334: persist all logs by default rotating on 30 files of 1MiB
+PRODUCT_PROPERTY_OVERRIDES += \
+ logd.logpersistd=logcatd \
+ logd.logpersistd.size=30
+endif
+
+# Dumpstate HAL
+PRODUCT_PACKAGES += \
+ android.hardware.dumpstate@1.0-service.sunfish
+
+# Citadel
+PRODUCT_PACKAGES += \
+ citadeld \
+ citadel_updater \
+ android.hardware.authsecret@1.0-service.citadel \
+ android.hardware.oemlock@1.0-service.citadel \
+ android.hardware.weaver@1.0-service.citadel \
+ android.hardware.keymaster@4.0-service.citadel \
+ wait_for_strongbox
+
+# Citadel debug stuff
+PRODUCT_PACKAGES_DEBUG += \
+ test_citadel
+
+# Storage: for factory reset protection feature
+PRODUCT_PROPERTY_OVERRIDES += \
+ ro.frp.pst=/dev/block/bootdevice/by-name/frp
+
+PRODUCT_PACKAGES += \
+ vndk-sp
+
+PRODUCT_ENFORCE_RRO_TARGETS := *
+
+# Override heap growth limit due to high display density on device
+PRODUCT_PROPERTY_OVERRIDES += \
+ dalvik.vm.heapgrowthlimit=256m
+
+PRODUCT_COPY_FILES += \
+ $(LOCAL_PATH)/hidl/android.hidl.base@1.0.so-32:system/lib/android.hidl.base@1.0.so \
+ $(LOCAL_PATH)/hidl/android.hidl.base@1.0.so-64:system/lib64/android.hidl.base@1.0.so \
+ $(LOCAL_PATH)/hidl/android.hidl.base@1.0.so-32:vendor/lib/android.hidl.base@1.0.so \
+ $(LOCAL_PATH)/hidl/android.hidl.base@1.0.so-64:vendor/lib64/android.hidl.base@1.0.so \
+
+PRODUCT_PACKAGES += \
+ ipacm \
+ IPACM_cfg.xml
+
+#Set default CDMA subscription to RUIM
+PRODUCT_PROPERTY_OVERRIDES += \
+ ro.telephony.default_cdma_sub=0
+
+# Set display color mode to Adaptive by default
+PRODUCT_PROPERTY_OVERRIDES += \
+ persist.sys.sf.color_saturation=1.0 \
+ persist.sys.sf.native_mode=2 \
+ persist.sys.sf.color_mode=9
+
+# Keymaster configuration
+PRODUCT_COPY_FILES += \
+ frameworks/native/data/etc/android.software.device_id_attestation.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.software.device_id_attestation.xml
+
+# Enable modem logging
+PRODUCT_PROPERTY_OVERRIDES += \
+ ro.radio.log_loc="/data/vendor/modem_dump" \
+ ro.radio.log_prefix="modem_log_"
+
+# Enable modem logging for debug
+ifneq (,$(filter userdebug eng, $(TARGET_BUILD_VARIANT)))
+PRODUCT_PROPERTY_OVERRIDES += \
+ persist.vendor.sys.modem.diag.mdlog=true \
+ persist.vendor.sys.modem.diag.mdlog_br_num=5
+else
+endif
+
+# Preopt SystemUI
+PRODUCT_DEXPREOPT_SPEED_APPS += \
+ SystemUIGoogle
+
+# Enable stats logging in LMKD
+TARGET_LMKD_STATS_LOG := true
+PRODUCT_PRODUCT_PROPERTIES += \
+ ro.lmk.log_stats=true
+
+# default usb oem functions
+ifneq (,$(filter userdebug eng, $(TARGET_BUILD_VARIANT)))
+ PRODUCT_PROPERTY_OVERRIDES += \
+ persist.vendor.usb.usbradio.config=diag,diag_mdm,qdss,qdss_mdm,serial_cdev,dpl_gsi,rmnet_gsi
+endif
+
+# Early phase offset configuration for SurfaceFlinger (b/75985430)
+PRODUCT_PROPERTY_OVERRIDES += \
+ debug.sf.early_phase_offset_ns=500000
+PRODUCT_PROPERTY_OVERRIDES += \
+ debug.sf.early_app_phase_offset_ns=500000
+PRODUCT_PROPERTY_OVERRIDES += \
+ debug.sf.early_gl_phase_offset_ns=3000000
+PRODUCT_PROPERTY_OVERRIDES += \
+ debug.sf.early_gl_app_phase_offset_ns=15000000
+
+# Do not skip init trigger by default
+PRODUCT_DEFAULT_PROPERTY_OVERRIDES += \
+ vendor.skip.init=0
+
+BOARD_USES_QCNE := true
+
+#per device
+PRODUCT_COPY_FILES += \
+ $(LOCAL_PATH)/sunfish/init.sunfish.rc:$(TARGET_COPY_OUT_VENDOR)/etc/init/hw/init.sunfish.rc
+
+PRODUCT_COPY_FILES += \
+ $(LOCAL_PATH)/sec_config:$(TARGET_COPY_OUT_VENDOR)/etc/sec_config
+
+# power HAL
+PRODUCT_PACKAGES += \
+ android.hardware.power@1.3-service.pixel-libperfmgr
+
+# Disable ro.adb.secure for the factory build to work around dead touchscreens
+# Bug: 116250643
+PRODUCT_PRODUCT_PROPERTIES += \
+ ro.adb.secure=0
+
+# GPS configuration file
+PRODUCT_COPY_FILES += \
+ $(LOCAL_PATH)/gps.conf:$(TARGET_COPY_OUT_VENDOR)/etc/gps.conf
+
+# default atrace HAL
+PRODUCT_PACKAGES += \
+ android.hardware.atrace@1.0-service
+
+# Fingerprint
+PRODUCT_PACKAGES += \
+ android.hardware.biometrics.fingerprint@2.1-service.fpc
+PRODUCT_COPY_FILES += \
+ $(LOCAL_PATH)/init.fingerprint.sh:$(TARGET_COPY_OUT_VENDOR)/bin/init.fingerprint.sh
+PRODUCT_COPY_FILES += \
+ frameworks/native/data/etc/android.hardware.fingerprint.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.fingerprint.xml
+
+# Reliability reporting
+PRODUCT_PACKAGES += \
+ pixelstats-vendor
+
+PRODUCT_USE_DYNAMIC_PARTITIONS := true
+
+# fastbootd
+PRODUCT_PACKAGES += \
+ android.hardware.fastboot@1.0-impl.pixel \
+ fastbootd
+
+# insmod files
+PRODUCT_COPY_FILES += \
+ $(LOCAL_PATH)/init.insmod.sunfish.cfg:$(TARGET_COPY_OUT_VENDOR)/etc/init.insmod.sunfish.cfg
+
+# Use /product/etc/fstab.postinstall to mount system_other
+PRODUCT_PRODUCT_PROPERTIES += \
+ ro.postinstall.fstab.prefix=/product
+
+PRODUCT_COPY_FILES += \
+ $(LOCAL_PATH)/fstab.postinstall:$(TARGET_COPY_OUT_PRODUCT)/etc/fstab.postinstall
+
+# powerstats HAL
+PRODUCT_PACKAGES += \
+ android.hardware.power.stats@1.0-service.pixel
+
+# Recovery
+PRODUCT_COPY_FILES += \
+ $(LOCAL_PATH)/init.recovery.device.rc:recovery/root/init.recovery.sunfish.rc
+
+# Do not skip init trigger by default
+PRODUCT_DEFAULT_PROPERTY_OVERRIDES += \
+ vendor.skip.init=0
+
+# Oslo feature flag
+PRODUCT_PRODUCT_PROPERTIES += \
+ ro.vendor.aware_available=true
+
+QTI_TELEPHONY_UTILS := qti-telephony-utils
+QTI_TELEPHONY_UTILS += qti_telephony_utils.xml
+PRODUCT_PACKAGES += $(QTI_TELEPHONY_UTILS)
+
+HIDL_WRAPPER := qti-telephony-hidl-wrapper
+HIDL_WRAPPER += qti_telephony_hidl_wrapper.xml
+PRODUCT_PACKAGES += $(HIDL_WRAPPER)
+
+# Increment the SVN for any official public releases
+PRODUCT_PROPERTY_OVERRIDES += \
+ ro.vendor.build.svn=1
+
+# ZRAM writeback
+PRODUCT_PROPERTY_OVERRIDES += \
+ ro.zram.mark_idle_delay_mins=60 \
+ ro.zram.first_wb_delay_mins=180 \
+ ro.zram.periodic_wb_delay_hours=24
+
+# Disable SPU usage
+PRODUCT_PROPERTY_OVERRIDES += \
+ vendor.gatekeeper.disable_spu = true
+
+PRODUCT_COPY_FILES += \
+ $(LOCAL_PATH)/powerhint.json:$(TARGET_COPY_OUT_VENDOR)/etc/powerhint.json
diff --git a/device_framework_matrix.xml b/device_framework_matrix.xml
new file mode 100644
index 00000000..25b0e443
--- /dev/null
+++ b/device_framework_matrix.xml
@@ -0,0 +1,233 @@
+
+
+ com.qualcomm.qti.imscmservice
+ 2.2
+
+ IImsCmService
+ qti.ims.connectionmanagerservice
+
+
+
+ com.qualcomm.qti.uceservice
+ 2.1
+
+ IUceService
+ com.qualcomm.qti.uceservice
+
+
+
+ vendor.qti.data.factory
+ hwbinder
+ 2.0
+
+ IFactory
+ default
+
+
+
+ com.quicinc.cne.api
+ 1.1
+
+ IApiService
+ cnd
+
+
+
+ com.quicinc.cne.server
+ 2.2
+
+ IServer
+ cnd
+
+
+
+ hardware.google.media.c2
+ 1.0
+
+ IComponentStore
+ default
+ software
+
+
+ IConfigurable
+ default
+ software
+
+
+
+ android.hardware.radio.config
+ 1.1
+
+ IRadioConfig
+ default
+
+
+
+ vendor.display.config
+ 1.9
+
+ IDisplayConfig
+ default
+
+
+
+ vendor.google.radioext
+ 1.1
+
+ IRadioExt
+ default
+
+
+
+ vendor.google.wireless_charger
+ 1.0
+
+ IWirelessCharger
+ default
+
+
+
+ vendor.qti.hardware.radio.am
+ 1.0
+
+ IQcRilAudio
+ slot1
+ slot2
+
+
+
+ vendor.qti.hardware.radio.atcmdfwd
+ 1.0
+
+ IAtCmdFwd
+ AtCmdFwdService
+
+
+
+ vendor.qti.hardware.radio.ims
+ 1.5
+
+ IImsRadio
+ imsradio0
+ imsradio1
+
+
+
+ vendor.qti.hardware.radio.lpa
+ 1.0
+
+ IUimLpa
+ UimLpa0
+
+
+
+ vendor.qti.hardware.radio.qcrilhook
+ 1.0
+
+ IQtiOemHook
+ oemhook0
+ oemhook1
+
+
+
+ vendor.qti.hardware.radio.uim
+ 1.2
+
+ IUim
+ Uim0
+ Uim1
+
+
+
+ vendor.qti.hardware.radio.uim_remote_client
+ 1.0
+
+ IUimRemoteServiceClient
+ uimRemoteClient0
+ uimRemoteClient1
+
+
+
+ vendor.qti.hardware.radio.uim_remote_server
+ 1.0
+
+ IUimRemoteServiceServer
+ uimRemoteServer0
+ uimRemoteServer1
+
+
+
+ vendor.qti.hardware.tui_comm
+ 1.0
+
+ ITuiComm
+ default
+
+
+
+ vendor.qti.hardware.display.allocator
+ 1.0
+
+ IQtiAllocator
+ default
+
+
+
+ vendor.qti.hardware.display.mapper
+ 2.0
+
+ IQtiMapper
+ default
+
+
+
+ vendor.qti.hardware.display.mapperextensions
+ 1.0
+
+ IQtiMapperExtensions
+ default
+
+
+
+ vendor.qti.imsrtpservice
+ 2.1
+
+ IRTPService
+ imsrtpservice
+
+
+
+ vendor.qti.ims.callinfo
+ hwbinder
+ 1.0
+
+ IService
+ default
+
+
+
+ hardware.google.light
+ 1.0
+
+ ILight
+ default
+
+
+
+ vendor.qti.hardware.bluetooth_sar
+ 1.0
+
+ IBluetoothSar
+ default
+
+
+
+ vendor.google.wifi_ext
+ hwbinder
+ 1.0
+
+ IWifiExt
+ default
+
+
+
diff --git a/dumpstate/Android.mk b/dumpstate/Android.mk
new file mode 100644
index 00000000..77bf6928
--- /dev/null
+++ b/dumpstate/Android.mk
@@ -0,0 +1,43 @@
+#
+# Copyright 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.sunfish
+LOCAL_INIT_RC := android.hardware.dumpstate@1.0-service.sunfish.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_CFLAGS := -Werror -Wall
+
+LOCAL_MODULE_TAGS := optional
+LOCAL_PROPRIETARY_MODULE := true
+
+include $(BUILD_EXECUTABLE)
diff --git a/dumpstate/DumpstateDevice.cpp b/dumpstate/DumpstateDevice.cpp
new file mode 100755
index 00000000..3f0143b8
--- /dev/null
+++ b/dumpstate/DumpstateDevice.cpp
@@ -0,0 +1,488 @@
+/*
+ * Copyright 2018 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
+#include
+#include
+#include
+
+#include
+#include
+
+#define _SVID_SOURCE
+#include
+
+#include "DumpstateUtil.h"
+
+#define MODEM_LOG_PREFIX_PROPERTY "ro.radio.log_prefix"
+#define MODEM_LOG_LOC_PROPERTY "ro.radio.log_loc"
+#define MODEM_LOGGING_SWITCH "persist.radio.smlog_switch"
+
+#define DIAG_MDLOG_PERSIST_PROPERTY "persist.vendor.sys.modem.diag.mdlog"
+#define DIAG_MDLOG_PROPERTY "vendor.sys.modem.diag.mdlog"
+#define DIAG_MDLOG_STATUS_PROPERTY "vendor.sys.modem.diag.mdlog_on"
+
+#define DIAG_MDLOG_NUMBER_BUGREPORT "persist.vendor.sys.modem.diag.mdlog_br_num"
+
+#define UFS_BOOTDEVICE "ro.boot.bootdevice"
+
+#define TCPDUMP_NUMBER_BUGREPORT "persist.vendor.tcpdump.log.br_num"
+#define TCPDUMP_PERSIST_PROPERTY "persist.vendor.tcpdump.log.alwayson"
+
+#define MODEM_EFS_DUMP_PROPERTY "vendor.sys.modem.diag.efsdump"
+
+using android::os::dumpstate::CommandOptions;
+using android::os::dumpstate::DumpFileToFd;
+using android::os::dumpstate::PropertiesHelper;
+using android::os::dumpstate::RunCommandToFd;
+
+namespace android {
+namespace hardware {
+namespace dumpstate {
+namespace V1_0 {
+namespace implementation {
+
+#define DIAG_LOG_PREFIX "diag_log_"
+#define TCPDUMP_LOG_PREFIX "tcpdump"
+#define EXTENDED_LOG_PREFIX "extended_log_"
+
+void DumpstateDevice::dumpLogs(int fd, std::string srcDir, std::string destDir,
+ int maxFileNum, const char *logPrefix) {
+ struct dirent **dirent_list = NULL;
+ int num_entries = scandir(srcDir.c_str(),
+ &dirent_list,
+ 0,
+ (int (*)(const struct dirent **, const struct dirent **)) alphasort);
+ if (!dirent_list) {
+ return;
+ } else if (num_entries <= 0) {
+ return;
+ }
+
+ int copiedFiles = 0;
+
+ for (int i = num_entries - 1; i >= 0; i--) {
+ ALOGD("Found %s\n", dirent_list[i]->d_name);
+
+ if (0 != strncmp(dirent_list[i]->d_name, logPrefix, strlen(logPrefix))) {
+ continue;
+ }
+
+ if ((copiedFiles >= maxFileNum) && (maxFileNum != -1)) {
+ ALOGD("Skipped %s\n", dirent_list[i]->d_name);
+ continue;
+ }
+
+ copiedFiles++;
+
+ CommandOptions options = CommandOptions::WithTimeout(120).Build();
+ std::string srcLogFile = srcDir + "/" + dirent_list[i]->d_name;
+ std::string destLogFile = destDir + "/" + dirent_list[i]->d_name;
+
+ std::string copyCmd = "/vendor/bin/cp " + srcLogFile + " " + destLogFile;
+
+ ALOGD("Copying %s to %s\n", srcLogFile.c_str(), destLogFile.c_str());
+ RunCommandToFd(fd, "CP DIAG LOGS", { "/vendor/bin/sh", "-c", copyCmd.c_str() }, options);
+ }
+
+ while (num_entries--) {
+ free(dirent_list[num_entries]);
+ }
+
+ free(dirent_list);
+}
+
+void DumpstateDevice::dumpModem(int fd, int fdModem)
+{
+ std::string modemLogDir = android::base::GetProperty(MODEM_LOG_LOC_PROPERTY, "");
+ if (modemLogDir.empty()) {
+ ALOGD("No modem log place is set");
+ return;
+ }
+
+ std::string filePrefix = android::base::GetProperty(MODEM_LOG_PREFIX_PROPERTY, "");
+
+ if (filePrefix.empty()) {
+ ALOGD("Modem log prefix is not set");
+ return;
+ }
+
+ const std::string modemLogCombined = modemLogDir + "/" + filePrefix + "all.tar";
+ const std::string modemLogAllDir = modemLogDir + "/modem_log";
+
+ RunCommandToFd(fd, "MKDIR MODEM LOG", {"/vendor/bin/mkdir", "-p", modemLogAllDir.c_str()}, CommandOptions::WithTimeout(2).Build());
+
+ if (!PropertiesHelper::IsUserBuild()) {
+ char cmd[256] = { 0 };
+
+ RunCommandToFd(fd, "MODEM RFS INFO", {"/vendor/bin/find /data/vendor/rfs/mpss/OEMFI/"}, CommandOptions::WithTimeout(2).Build());
+ RunCommandToFd(fd, "MODEM DIAG SYSTEM PROPERTIES", {"/vendor/bin/getprop | grep vendor.sys.modem.diag"}, CommandOptions::WithTimeout(2).Build());
+
+ android::base::SetProperty(MODEM_EFS_DUMP_PROPERTY, "true");
+
+ const std::string diagLogDir = "/data/vendor/radio/diag_logs/logs";
+ const std::string tcpdumpLogDir = "/data/vendor/tcpdump_logger/logs";
+ const std::string extendedLogDir = "/data/vendor/radio/extended_logs";
+ const std::vector rilAndNetmgrLogs
+ {
+ "/data/vendor/radio/ril_log0",
+ "/data/vendor/radio/ril_log0_old",
+ "/data/vendor/radio/ril_log1",
+ "/data/vendor/radio/ril_log1_old",
+ "/data/vendor/radio/qmi_fw_log",
+ "/data/vendor/radio/qmi_fw_log_old",
+ "/data/vendor/radio/imsdatadaemon_log",
+ "/data/vendor/radio/imsdatadaemon_log_old",
+ "/data/vendor/netmgr/netmgr_log",
+ "/data/vendor/netmgr/netmgr_log_old",
+ "/data/vendor/radio/power_anomaly_data.txt",
+ "/data/vendor/radio/diag_logs/diag_trace.txt",
+ "/data/vendor/radio/diag_logs/diag_trace_old.txt",
+ "/data/vendor/radio/diag_logs/logs/diag_poweron_log.qmdl",
+ "/data/vendor/radio/metrics_data",
+ "/data/vendor/ssrlog/ssr_log.txt",
+ "/data/vendor/ssrlog/ssr_log_old.txt",
+ "/data/vendor/rfs/mpss/modem_efs"
+ };
+
+ bool smlogEnabled = android::base::GetBoolProperty(MODEM_LOGGING_SWITCH, false) && !access("/vendor/bin/smlog_dump", X_OK);
+ bool diagLogEnabled = android::base::GetBoolProperty(DIAG_MDLOG_PERSIST_PROPERTY, false);
+ bool tcpdumpEnabled = android::base::GetBoolProperty(TCPDUMP_PERSIST_PROPERTY, false);
+
+ if (smlogEnabled) {
+ RunCommandToFd(fd, "SMLOG DUMP", {"smlog_dump", "-d", "-o", modemLogAllDir.c_str()}, CommandOptions::WithTimeout(10).Build());
+ } else if (diagLogEnabled) {
+ bool diagLogStarted = android::base::GetBoolProperty( DIAG_MDLOG_STATUS_PROPERTY, false);
+
+ if (diagLogStarted) {
+ android::base::SetProperty(DIAG_MDLOG_PROPERTY, "false");
+ ALOGD("Stopping diag_mdlog...\n");
+ if (android::base::WaitForProperty(DIAG_MDLOG_STATUS_PROPERTY, "false", std::chrono::seconds(20))) {
+ ALOGD("diag_mdlog exited");
+ } else {
+ ALOGE("Waited mdlog timeout after 20 second");
+ }
+ } else {
+ ALOGD("diag_mdlog is not running");
+ }
+
+ dumpLogs(fd, diagLogDir, modemLogAllDir, android::base::GetIntProperty(DIAG_MDLOG_NUMBER_BUGREPORT, 100), DIAG_LOG_PREFIX);
+
+ if (diagLogStarted) {
+ ALOGD("Restarting diag_mdlog...");
+ android::base::SetProperty(DIAG_MDLOG_PROPERTY, "true");
+ }
+ }
+
+ if (tcpdumpEnabled) {
+ dumpLogs(fd, tcpdumpLogDir, modemLogAllDir, android::base::GetIntProperty(TCPDUMP_NUMBER_BUGREPORT, 5), TCPDUMP_LOG_PREFIX);
+ }
+
+ for (const auto& logFile : rilAndNetmgrLogs) {
+ RunCommandToFd(fd, "CP MODEM LOG", {"/vendor/bin/cp", logFile.c_str(), modemLogAllDir.c_str()}, CommandOptions::WithTimeout(2).Build());
+ }
+
+ //Dump IPA log
+ snprintf(cmd, sizeof(cmd),
+ "cat /d/ipc_logging/ipa/log > %s/ipa_log",
+ modemLogAllDir.c_str());
+ RunCommandToFd(fd, "Dump IPA log", {"/vendor/bin/sh", "-c", cmd});
+
+ // Dump esoc-mdm log
+ snprintf(cmd, sizeof(cmd),
+ "cat /sys/kernel/debug/ipc_logging/esoc-mdm/log > %s/esoc-mdm_log.txt",
+ modemLogAllDir.c_str());
+ RunCommandToFd(fd, "ESOC-MDM LOG", {"/vendor/bin/sh", "-c", cmd});
+
+ // Dump pcie0 log
+ snprintf(cmd, sizeof(cmd),
+ "cat /sys/kernel/debug/ipc_logging/pcie0-long/log > %s/pcie0-long_log.txt",
+ modemLogAllDir.c_str());
+ RunCommandToFd(fd, "PCIE0-LONG LOG", {"/vendor/bin/sh", "-c", cmd});
+
+ snprintf(cmd, sizeof(cmd),
+ "cat /sys/kernel/debug/ipc_logging/pcie0-short/log > %s/pcie0-short_log.txt",
+ modemLogAllDir.c_str());
+ RunCommandToFd(fd, "PCIE0-SHORT LOG", {"/vendor/bin/sh", "-c", cmd});
+
+ dumpLogs(fd, extendedLogDir, modemLogAllDir, 100, EXTENDED_LOG_PREFIX);
+ android::base::SetProperty(MODEM_EFS_DUMP_PROPERTY, "false");
+ }
+
+ RunCommandToFd(fd, "TAR LOG", {"/vendor/bin/tar", "cvf", modemLogCombined.c_str(), "-C", modemLogAllDir.c_str(), "."}, CommandOptions::WithTimeout(120).Build());
+ RunCommandToFd(fd, "CHG PERM", {"/vendor/bin/chmod", "a+w", modemLogCombined.c_str()}, CommandOptions::WithTimeout(2).Build());
+
+ std::vector buffer(65536);
+ android::base::unique_fd fdLog(TEMP_FAILURE_RETRY(open(modemLogCombined.c_str(), O_RDONLY | O_CLOEXEC | O_NONBLOCK)));
+
+ if (fdLog >= 0) {
+ while (1) {
+ ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fdLog, buffer.data(), buffer.size()));
+
+ if (bytes_read == 0) {
+ break;
+ } else if (bytes_read < 0) {
+ ALOGD("read(%s): %s\n", modemLogCombined.c_str(), strerror(errno));
+ break;
+ }
+
+ ssize_t result = TEMP_FAILURE_RETRY(write(fdModem, buffer.data(), bytes_read));
+
+ if (result != bytes_read) {
+ ALOGD("Failed to write %ld bytes, actually written: %ld", bytes_read, result);
+ break;
+ }
+ }
+ }
+
+ RunCommandToFd(fd, "RM MODEM DIR", { "/vendor/bin/rm", "-r", modemLogAllDir.c_str()}, CommandOptions::WithTimeout(2).Build());
+ RunCommandToFd(fd, "RM LOG", { "/vendor/bin/rm", modemLogCombined.c_str()}, CommandOptions::WithTimeout(2).Build());
+}
+
+static void DumpTouch(int fd) {
+ const char touch_spi_path[] = "/sys/class/spi_master/spi1/spi1.0";
+ char cmd[256];
+
+ snprintf(cmd, sizeof(cmd), "%s/appid", touch_spi_path);
+ if (!access(cmd, R_OK)) {
+ // Touch firmware version
+ DumpFileToFd(fd, "STM touch firmware version", cmd);
+
+ // Touch controller status
+ snprintf(cmd, sizeof(cmd), "%s/status", touch_spi_path);
+ DumpFileToFd(fd, "STM touch status", cmd);
+
+ // Mutual raw data
+ snprintf(cmd, sizeof(cmd),
+ "echo 13 00 > %s/stm_fts_cmd && cat %s/stm_fts_cmd",
+ touch_spi_path, touch_spi_path);
+ RunCommandToFd(fd, "Mutual Raw", {"/vendor/bin/sh", "-c", cmd});
+
+ // Mutual strength data
+ snprintf(cmd, sizeof(cmd),
+ "echo 17 > %s/stm_fts_cmd && cat %s/stm_fts_cmd",
+ touch_spi_path, touch_spi_path);
+ RunCommandToFd(fd, "Mutual Strength", {"/vendor/bin/sh", "-c", cmd});
+
+ // Self raw data
+ snprintf(cmd, sizeof(cmd),
+ "echo 15 00 > %s/stm_fts_cmd && cat %s/stm_fts_cmd",
+ touch_spi_path, touch_spi_path);
+ RunCommandToFd(fd, "Self Raw", {"/vendor/bin/sh", "-c", cmd});
+ }
+
+ if (!access("/proc/fts/driver_test", R_OK)) {
+ RunCommandToFd(fd, "Mutual Raw Data",
+ {"/vendor/bin/sh", "-c",
+ "echo 23 00 > /proc/fts/driver_test && "
+ "cat /proc/fts/driver_test"});
+ RunCommandToFd(fd, "Mutual Baseline Data",
+ {"/vendor/bin/sh", "-c",
+ "echo 23 03 > /proc/fts/driver_test && "
+ "cat /proc/fts/driver_test"});
+ RunCommandToFd(fd, "Mutual Strength Data",
+ {"/vendor/bin/sh", "-c",
+ "echo 23 02 > /proc/fts/driver_test && "
+ "cat /proc/fts/driver_test"});
+ RunCommandToFd(fd, "Self Raw Data",
+ {"/vendor/bin/sh", "-c",
+ "echo 24 00 > /proc/fts/driver_test && "
+ "cat /proc/fts/driver_test"});
+ RunCommandToFd(fd, "Self Baseline Data",
+ {"/vendor/bin/sh", "-c",
+ "echo 24 03 > /proc/fts/driver_test && "
+ "cat /proc/fts/driver_test"});
+ RunCommandToFd(fd, "Self Strength Data",
+ {"/vendor/bin/sh", "-c",
+ "echo 24 02 > /proc/fts/driver_test && "
+ "cat /proc/fts/driver_test"});
+ RunCommandToFd(fd, "Mutual Compensation",
+ {"/vendor/bin/sh", "-c",
+ "echo 32 10 > /proc/fts/driver_test && "
+ "cat /proc/fts/driver_test"});
+ RunCommandToFd(fd, "Self Compensation",
+ {"/vendor/bin/sh", "-c",
+ "echo 33 12 > /proc/fts/driver_test && "
+ "cat /proc/fts/driver_test"});
+ }
+}
+
+static void DumpF2FS(int fd) {
+ DumpFileToFd(fd, "F2FS", "/sys/kernel/debug/f2fs/status");
+ DumpFileToFd(fd, "F2FS - fragmentation", "/proc/fs/f2fs/dm-3/segment_info");
+}
+
+static void DumpUFS(int fd) {
+ DumpFileToFd(fd, "UFS model", "/sys/block/sda/device/model");
+ DumpFileToFd(fd, "UFS rev", "/sys/block/sda/device/rev");
+ DumpFileToFd(fd, "UFS size", "/sys/block/sda/size");
+ DumpFileToFd(fd, "UFS show_hba", "/sys/kernel/debug/ufshcd0/show_hba");
+ DumpFileToFd(fd, "UFS err_stats", "/sys/kernel/debug/ufshcd0/stats/err_stats");
+ DumpFileToFd(fd, "UFS io_stats", "/sys/kernel/debug/ufshcd0/stats/io_stats");
+ DumpFileToFd(fd, "UFS req_stats", "/sys/kernel/debug/ufshcd0/stats/req_stats");
+
+ std::string bootdev = android::base::GetProperty(UFS_BOOTDEVICE, "");
+ if (!bootdev.empty()) {
+ DumpFileToFd(fd, "UFS Slow IO Read", "/sys/devices/platform/soc/" + bootdev + "/slowio_read_cnt");
+ DumpFileToFd(fd, "UFS Slow IO Write", "/sys/devices/platform/soc/" + bootdev + "/slowio_write_cnt");
+ DumpFileToFd(fd, "UFS Slow IO Unmap", "/sys/devices/platform/soc/" + bootdev + "/slowio_unmap_cnt");
+ DumpFileToFd(fd, "UFS Slow IO Sync", "/sys/devices/platform/soc/" + bootdev + "/slowio_sync_cnt");
+
+ std::string ufs_health = "for f in $(find /sys/devices/platform/soc/" + bootdev + "/health -type f); do if [[ -r $f && -f $f ]]; then echo --- $f; cat $f; echo ''; fi; done";
+ RunCommandToFd(fd, "UFS health", {"/vendor/bin/sh", "-c", ufs_health.c_str()});
+ }
+}
+
+static void DumpVibrator(int fd) {
+ const std::string dir = "/sys/class/leds/vibrator/device/";
+ const std::vector files {
+ "asp_enable",
+ "comp_enable",
+ "cp_dig_scale",
+ "cp_trigger_duration",
+ "cp_trigger_index",
+ "cp_trigger_q_sub",
+ "cp_trigger_queue",
+ "dig_scale",
+ "exc_enable",
+ "f0_stored",
+ "fw_rev",
+ "heartbeat",
+ "hw_reset",
+ "leds/vibrator/activate",
+ "leds/vibrator/duration",
+ "leds/vibrator/state",
+ "num_waves",
+ "q_stored",
+ "redc_comp_enable",
+ "redc_stored",
+ "standby_timeout",
+ "vbatt_max",
+ "vbatt_min",
+ };
+
+ for (const auto &file : files) {
+ DumpFileToFd(fd, "Vibrator", dir+file);
+ }
+}
+
+// Methods from ::android::hardware::dumpstate::V1_0::IDumpstateDevice follow.
+Return DumpstateDevice::dumpstateBoard(const hidl_handle& handle) {
+ // Exit when dump is completed since this is a lazy HAL.
+ addPostCommandTask([]() {
+ exit(0);
+ });
+
+ 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();
+ }
+
+ RunCommandToFd(fd, "VENDOR PROPERTIES", {"/vendor/bin/getprop"});
+ DumpFileToFd(fd, "SoC serial number", "/sys/devices/soc0/serial_number");
+ DumpFileToFd(fd, "CPU present", "/sys/devices/system/cpu/present");
+ DumpFileToFd(fd, "CPU online", "/sys/devices/system/cpu/online");
+ DumpTouch(fd);
+
+ DumpF2FS(fd);
+ DumpUFS(fd);
+
+ DumpFileToFd(fd, "INTERRUPTS", "/proc/interrupts");
+ DumpFileToFd(fd, "Sleep Stats", "/sys/power/system_sleep/stats");
+ DumpFileToFd(fd, "Power Management Stats", "/sys/power/rpmh_stats/master_stats");
+ DumpFileToFd(fd, "WLAN Power Stats", "/sys/kernel/wlan/power_stats");
+ DumpFileToFd(fd, "LL-Stats", "/d/wlan0/ll_stats");
+ DumpFileToFd(fd, "WLAN Connect Info", "/d/wlan0/connect_info");
+ DumpFileToFd(fd, "WLAN Offload Info", "/d/wlan0/offload_info");
+ DumpFileToFd(fd, "WLAN Roaming Stats", "/d/wlan0/roam_stats");
+ DumpFileToFd(fd, "ICNSS Stats", "/d/icnss/stats");
+ DumpFileToFd(fd, "SMD Log", "/d/ipc_logging/smd/log");
+ RunCommandToFd(fd, "ION HEAPS", {"/vendor/bin/sh", "-c", "for d in $(ls -d /d/ion/*); do for f in $(ls $d); do echo --- $d/$f; cat $d/$f; done; done"});
+ DumpFileToFd(fd, "dmabuf info", "/d/dma_buf/bufinfo");
+ DumpFileToFd(fd, "dmabuf process info", "/d/dma_buf/dmaprocs");
+ RunCommandToFd(fd, "Temperatures", {"/vendor/bin/sh", "-c", "for f in /sys/class/thermal/thermal* ; do type=`cat $f/type` ; temp=`cat $f/temp` ; echo \"$type: $temp\" ; done"});
+ RunCommandToFd(fd, "Cooling Device Current State", {"/vendor/bin/sh", "-c", "for f in /sys/class/thermal/cooling* ; do type=`cat $f/type` ; temp=`cat $f/cur_state` ; echo \"$type: $temp\" ; done"});
+ RunCommandToFd(
+ fd, "LMH info",
+ {"/vendor/bin/sh", "-c",
+ "for f in /sys/bus/platform/drivers/msm_lmh_dcvs/*qcom,limits-dcvs@*/lmh_freq_limit; do "
+ "state=`cat $f` ; echo \"$f: $state\" ; done"});
+ RunCommandToFd(fd, "CPU time-in-state", {"/vendor/bin/sh", "-c", "for cpu in /sys/devices/system/cpu/cpu*; do f=$cpu/cpufreq/stats/time_in_state; if [ ! -f $f ]; then continue; fi; echo $f:; cat $f; done"});
+ RunCommandToFd(fd, "CPU cpuidle", {"/vendor/bin/sh", "-c", "for cpu in /sys/devices/system/cpu/cpu*; do for d in $cpu/cpuidle/state*; do if [ ! -d $d ]; then continue; fi; echo \"$d: `cat $d/name` `cat $d/desc` `cat $d/time` `cat $d/usage`\"; done; done"});
+ RunCommandToFd(fd, "Airbrush debug info", {"/vendor/bin/sh", "-c", "for f in `ls /sys/devices/platform/soc/c84000.i2c/i2c-4/4-0066/@(*curr|temperature|vbat|total_power)`; do echo \"$f: `cat $f`\" ; done; file=/d/airbrush/airbrush_sm/chip_state; echo \"$file: `cat $file`\""});
+ DumpFileToFd(fd, "MDP xlogs", "/data/vendor/display/mdp_xlog");
+ DumpFileToFd(fd, "TCPM logs", "/d/tcpm/usbpd0");
+ DumpFileToFd(fd, "PD Engine", "/d/pd_engine/usbpd0");
+ DumpFileToFd(fd, "ipc-local-ports", "/d/msm_ipc_router/dump_local_ports");
+ RunCommandToFd(fd, "USB Device Descriptors", {"/vendor/bin/sh", "-c", "cd /sys/bus/usb/devices/1-1 && cat product && cat bcdDevice; cat descriptors | od -t x1 -w16 -N96"});
+ RunCommandToFd(fd, "Power supply properties", {"/vendor/bin/sh", "-c", "for f in `ls /sys/class/power_supply/*/uevent` ; do echo \"------ $f\\n`cat $f`\\n\" ; done"});
+ RunCommandToFd(fd, "PMIC Votables", {"/vendor/bin/sh", "-c", "cat /sys/kernel/debug/pmic-votable/*/status"});
+ DumpFileToFd(fd, "Battery cycle count", "/d/google_battery/cycle_count_bins");
+ DumpFileToFd(fd, "Maxim FG History", "/dev/maxfg_history");
+ DumpFileToFd(fd, "Maxim FG registers", "/d/regmap/1-0036/registers");
+ DumpFileToFd(fd, "Maxim FG NV RAM", "/d/regmap/1-000b/registers");
+ RunCommandToFd(fd, "Google Charger", {"/vendor/bin/sh", "-c", "cd /d/google_charger/; for f in `ls pps_*` ; do echo \"$f: `cat $f`\" ; done"});
+ RunCommandToFd(fd, "Google Battery", {"/vendor/bin/sh", "-c", "cd /d/google_battery/; for f in `ls ssoc_*` ; do echo \"$f: `cat $f`\" ; done"});
+ DumpFileToFd(fd, "WLC VER", "/sys/devices/platform/soc/a88000.i2c/i2c-0/0-0061/version");
+ DumpFileToFd(fd, "WLC STATUS", "/sys/devices/platform/soc/a88000.i2c/i2c-0/0-0061/status");
+
+ RunCommandToFd(fd, "eSIM Status", {"/vendor/bin/sh", "-c", "od -t x1 /sys/firmware/devicetree/base/chosen/cdt/cdb2/esim"});
+ DumpFileToFd(fd, "Modem Stat", "/data/vendor/modem_stat/debug.txt");
+ DumpFileToFd(fd, "Pixel trace", "/d/tracing/instances/pixel-trace/trace");
+
+ // Slower dump put later in case stuck the rest of dump
+ // Timeout after 3s as TZ log missing EOF
+ RunCommandToFd(fd, "QSEE logs", {"/vendor/bin/sh", "-c", "/vendor/bin/timeout 3 cat /d/tzdbg/qsee_log"});
+ if (handle->numFds < 2) {
+ ALOGE("no FD for modem\n");
+ } else {
+ int fdModem = handle->data[1];
+ dumpModem(fd, fdModem);
+ }
+
+ // Citadel info (only enabled on -eng and -userdebug builds)
+ if (!PropertiesHelper::IsUserBuild()) {
+ RunCommandToFd(fd, "Citadel ID", {"/vendor/bin/hw/citadel_updater", "--id"});
+ RunCommandToFd(fd, "Citadel VER", {"/vendor/bin/hw/citadel_updater", "-lv"});
+ RunCommandToFd(fd, "Citadel SELFTEST", {"/vendor/bin/hw/citadel_updater", "--selftest"});
+ }
+
+ DumpVibrator(fd);
+
+ // Dump various events in WiFi data path
+ DumpFileToFd(fd, "WLAN DP Trace", "/d/wlan/dpt_stats/dump_set_dpt_logs");
+
+ // Keep this at the end as very long on not for humans
+ DumpFileToFd(fd, "WLAN FW Log Symbol Table", "/vendor/firmware/Data.msc");
+
+ return Void();
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace dumpstate
+} // namespace hardware
+} // namespace android
diff --git a/dumpstate/DumpstateDevice.h b/dumpstate/DumpstateDevice.h
new file mode 100644
index 00000000..83a5f5af
--- /dev/null
+++ b/dumpstate/DumpstateDevice.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2019 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
+#include
+#include
+#include
+
+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 dumpstateBoard(const hidl_handle& h) override;
+
+ void dumpLogs(int fd, std::string srcDir, std::string destDir, int maxFileNum,
+ const char *logPrefix);
+ void dumpModem(int fd, int fdModem);
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace dumpstate
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_DUMPSTATE_V1_0_DUMPSTATEDEVICE_H
diff --git a/dumpstate/android.hardware.dumpstate@1.0-service.sunfish.rc b/dumpstate/android.hardware.dumpstate@1.0-service.sunfish.rc
new file mode 100644
index 00000000..543d4b94
--- /dev/null
+++ b/dumpstate/android.hardware.dumpstate@1.0-service.sunfish.rc
@@ -0,0 +1,10 @@
+service vendor.dumpstate-1-0 /vendor/bin/hw/android.hardware.dumpstate@1.0-service.sunfish
+ class hal
+ user system
+ group system vendor_rfs
+ interface android.hardware.dumpstate@1.0::IDumpstateDevice default
+ oneshot
+ disabled
+
+on boot
+ chmod 0444 /sys/kernel/debug/tzdbg/qsee_log
diff --git a/dumpstate/service.cpp b/dumpstate/service.cpp
new file mode 100644
index 00000000..97b4e2e5
--- /dev/null
+++ b/dumpstate/service.cpp
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2019 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.sunfish"
+
+#include
+#include
+
+#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::sp;
+
+
+int main(int /* argc */, char* /* argv */ []) {
+ sp dumpstate = new DumpstateDevice;
+ configureRpcThreadpool(1, true);
+
+ android::status_t status = dumpstate->registerAsService();
+
+ if (status != android::OK)
+ {
+ ALOGE("Could not register DumpstateDevice service (%d).", status);
+ return -1;
+ }
+
+ joinRpcThreadpool();
+}
diff --git a/framework_manifest.xml b/framework_manifest.xml
new file mode 100644
index 00000000..b2276a55
--- /dev/null
+++ b/framework_manifest.xml
@@ -0,0 +1,39 @@
+
+
+
+
+ vendor.qti.hardware.radio.atcmdfwd
+ hwbinder
+ 1.0
+
+ IAtCmdFwd
+ AtCmdFwdService
+
+
+
diff --git a/fstab.hardware b/fstab.hardware
new file mode 100644
index 00000000..b601aadb
--- /dev/null
+++ b/fstab.hardware
@@ -0,0 +1,12 @@
+# Android fstab file.
+
+#
+system /system ext4 ro,barrier=1 wait,slotselect,avb=vbmeta_system,logical,first_stage_mount
+vendor /vendor ext4 ro,barrier=1 wait,slotselect,avb=vbmeta,logical,first_stage_mount
+product /product ext4 ro,barrier=1 wait,slotselect,avb,logical,first_stage_mount
+/dev/block/by-name/metadata /metadata ext4 noatime,nosuid,nodev,discard,sync wait,formattable,first_stage_mount
+/dev/block/bootdevice/by-name/modem /vendor/firmware_mnt vfat ro,shortname=lower,uid=0,gid=1000,dmask=227,fmask=337,context=u:object_r:firmware_file:s0 wait,slotselect
+/dev/block/bootdevice/by-name/misc /misc emmc defaults defaults
+/dev/block/bootdevice/by-name/userdata /data f2fs noatime,nosuid,nodev,discard,reserve_root=32768,resgid=1065,fsync_mode=nobarrier latemount,wait,check,quota,formattable,fileencryption=ice,reservedsize=128M,sysfs_path=/sys/devices/platform/soc/1d84000.ufshc,keydirectory=/metadata/vold/metadata_encryption,checkpoint=fs
+/devices/platform/soc/a600000.ssusb/a600000.dwc3* auto vfat defaults voldmanaged=usb:auto
+/dev/block/zram0 none swap defaults zramsize=2147483648,max_comp_streams=8,zram_loopback_path=/data/unencrypted/zram_swap,zram_loopback_size=512M
diff --git a/fstab.persist b/fstab.persist
new file mode 100644
index 00000000..f3840b15
--- /dev/null
+++ b/fstab.persist
@@ -0,0 +1,4 @@
+# Keep persist in an fstab file, since we need to run fsck on it after abnormal shutdown.
+
+#
+/dev/block/platform/soc/1d84000.ufshc/by-name/persist /mnt/vendor/persist ext4 nosuid,nodev,noatime,barrier=1 wait
diff --git a/fstab.postinstall b/fstab.postinstall
new file mode 100644
index 00000000..83bb3c6f
--- /dev/null
+++ b/fstab.postinstall
@@ -0,0 +1,17 @@
+#
+# Copyright (C) 2018 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.
+
+#
+system /postinstall ext4 ro,nosuid,nodev,noexec slotselect_other,logical,avb_keys=/product/etc/security/avb/system_other.avbpubkey
diff --git a/gps.conf b/gps.conf
new file mode 100644
index 00000000..9f5a7023
--- /dev/null
+++ b/gps.conf
@@ -0,0 +1,297 @@
+#Version check for XTRA
+#DISABLE = 0
+#AUTO = 1
+#XTRA2 = 2
+#XTRA3 = 3
+XTRA_VERSION_CHECK=0
+
+# Error Estimate
+# _SET = 1
+# _CLEAR = 0
+ERR_ESTIMATE=0
+
+#NTP server
+#NTP_SERVER setting is in modem NV
+
+#XTRA CA path
+XTRA_CA_PATH=/system/etc/security/cacerts
+
+# DEBUG LEVELS: 0 - none, 1 - Error, 2 - Warning, 3 - Info
+# 4 - Debug, 5 - Verbose
+# If DEBUG_LEVEL is commented, Android's logging levels will be used
+DEBUG_LEVEL = 2
+
+# Intermediate position report, 1=enable, 0=disable
+INTERMEDIATE_POS=0
+
+# Below bit mask configures how GPS functionalities
+# should be locked when user turns off GPS on Settings
+# Set bit 0x1 if MO GPS functionalities are to be locked
+# Set bit 0x2 if NI GPS functionalities are to be locked
+# default – both MO and NI locked for maximal privacy
+#GPS_LOCK = 3
+
+# supl version 1.0
+#SUPL_VER=0x10000
+
+# Emergency SUPL, 1=enable, 0=disable
+SUPL_ES=1
+
+#Choose PDN for Emergency SUPL
+#1 - Use emergency PDN
+#0 - Use regular SUPL PDN for Emergency SUPL
+#USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL=0
+
+#SUPL_MODE is a bit mask set in config.xml per carrier by default.
+#If it is uncommented here, this value will overwrite the value from
+#config.xml.
+#MSA=0X2
+#MSB=0X1
+#SUPL_MODE=
+
+# GPS Capabilities bit mask
+# SCHEDULING = 0x01
+# MSB = 0x02
+# MSA = 0x04
+# ON_DEMAND_TIME = 0x10
+# GEOFENCE = 0x20
+# default = ON_DEMAND_TIME | MSA | MSB | SCHEDULING | GEOFENCE
+CAPABILITIES=0x37
+
+# Accuracy threshold for intermediate positions
+# less accurate positions are ignored, 0 for passing all positions
+# ACCURACY_THRES=5000
+
+################################
+##### AGPS server settings #####
+################################
+
+# FOR SUPL SUPPORT, set the following
+# SUPL_HOST=supl.host.com or IP
+# SUPL_PORT=1234
+
+# FOR MO SUPL SUPPORT, set the following
+# MO_SUPL_HOST=supl.host.com or IP
+# MO_SUPL_PORT=1234
+
+# FOR C2K PDE SUPPORT, set the following
+# C2K_HOST=c2k.pde.com or IP
+# C2K_PORT=1234
+
+# Bitmask of slots that are available
+# for write/install to, where 1s indicate writable,
+# and the default value is 0 where no slots
+# are writable. For example, AGPS_CERT_WRITABLE_MASK
+# of b1000001010 makes 3 slots available
+# and the remaining 7 slots unwritable.
+#AGPS_CERT_WRITABLE_MASK=0
+
+####################################
+# LTE Positioning Profile Settings
+####################################
+# 0: Enable RRLP on LTE(Default)
+# 1: Enable LPP_User_Plane on LTE
+# 2: Enable LPP_Control_Plane
+# 3: Enable both LPP_User_Plane and LPP_Control_Plane
+#LPP_PROFILE = 2
+
+####################################
+#Datum Type
+####################################
+# 0: WGS-84
+# 1: PZ-90
+DATUM_TYPE = 0
+
+################################
+# EXTRA SETTINGS
+################################
+# NMEA provider (1=Modem Processor, 0=Application Processor)
+NMEA_PROVIDER=0
+# Mark if it is a SGLTE target (1=SGLTE, 0=nonSGLTE)
+SGLTE_TARGET=0
+
+##################################################
+# Select Positioning Protocol on A-GLONASS system
+##################################################
+# 0x1: RRC CPlane
+# 0x2: RRLP UPlane
+# 0x4: LLP Uplane
+#A_GLONASS_POS_PROTOCOL_SELECT = 0
+
+##################################################
+# Select technology for LPPe Control Plane
+##################################################
+# 0x1: DBH for LPPe CP
+# 0x2: WLAN AP Measurements for LPPe CP
+# 0x4: SRN AP measurement for CP
+# 0x8: Sensor Barometer Measurement LPPe CP
+#LPPE_CP_TECHNOLOGY = 0
+
+##################################################
+# Select technology for LPPe User Plane
+##################################################
+# 0x1: DBH for LPPe UP
+# 0x2: WLAN AP Measurements for LPPe UP
+# 0x4: SRN AP measurement for UP
+# 0x8: Sensor Barometer Measurement LPPe UP
+#LPPE_UP_TECHNOLOGY = 0
+
+##################################################
+# AGPS_CONFIG_INJECT
+##################################################
+# enable/disable injection of AGPS configurations:
+# SUPL_VER
+# SUPL_HOST
+# SUPL_PORT
+# MO_SUPL_HOST
+# MO_SUPL_PORT
+# C2K_HOST
+# C2K_PORT
+# LPP_PROFILE
+# A_GLONASS_POS_PROTOCOL_SELECT
+# 0: disable
+# 1: enable
+AGPS_CONFIG_INJECT = 1
+
+##################################################
+# GNSS settings for automotive use cases
+# Configurations in following section are
+# specific to automotive use cases, others
+# please do not change, keep the default values
+##################################################
+
+# AP Coarse Timestamp Uncertainty
+##################################################
+# default : 10
+# AP time stamp uncertainty, until GNSS receiver
+# is able to acquire better timing information
+AP_TIMESTAMP_UNCERTAINTY = 10
+
+##################################################
+# QDR engine availability status
+##################################################
+# 0 : NO QDR (default)
+# 1 : QDR enabled
+# This settings enables QDR Configuration for
+# automotive use case, if enabled then
+# DR_AP_Service needs to be enabled in izat.conf
+#EXTERNAL_DR_ENABLED = 0
+
+#####################################
+# DR_SYNC Pulse Availability
+#####################################
+# 0 : DR_SYNC pulse not available (default)
+# 1 : DR_SYNC pulse available
+# This configuration enables the driver to make use
+# of PPS events generated by DR_SYNC pulse
+# Standard Linux PPS driver needs to be enabled
+DR_SYNC_ENABLED = 0
+
+#####################################
+# PPS Device name
+#####################################
+PPS_DEVICENAME = /dev/pps0
+
+#####################################
+# Ignore PPS at Startup and after long outage
+#####################################
+IGNORE_PPS_PULSE_COUNT = 1
+
+#####################################
+# Long GNSS RF outage in seconds
+#####################################
+GNSS_OUTAGE_DURATION = 10
+
+#####################################
+# AP Clock Accuracy
+#####################################
+# Quality of APPS processor clock (in PPM).
+# Value specified is used for calculation of
+# APPS time stamp uncertainty
+AP_CLOCK_PPM = 100
+
+#####################################
+# MAX ms difference to detect missing pulse
+#####################################
+# Specifies time threshold in ms to validate any missing PPS pulses
+MISSING_PULSE_TIME_DELTA = 900
+
+#####################################
+# Propagation time uncertainty
+#####################################
+# This settings enables time uncertainty propagation
+# logic incase of missing PPS pulse
+PROPAGATION_TIME_UNCERTAINTY = 1
+
+#######################################
+# APN / IP Type Configuration
+# APN and IP Type to use for setting
+# up WWAN call.
+# Use below values for IP Type:
+# v4 = 4
+# v6 = 6
+# v4v6 = 10
+#######################################
+# INTERNET_APN = abc.xyz
+# INTERNET_IP_TYPE = 4
+# SUPL_APN = abc.xyz
+# SUPL_IP_TYPE = 4
+
+#####################################
+# Modem type
+#####################################
+# This setting configures modem type
+# (external=0 or internal=1)
+# comment out the next line to vote
+# for the first modem in the list
+MODEM_TYPE = 0
+
+##################################################
+# CONSTRAINED TIME UNCERTAINTY MODE
+##################################################
+# 0 : disabled (default)
+# 1 : enabled
+# This setting enables GPS engine to keep its time
+# uncertainty below the specified constraint
+#CONSTRAINED_TIME_UNCERTAINTY_ENABLED = 0
+
+# If constrained time uncertainty mode is enabled,
+# this setting specifies the time uncertainty
+# threshold that gps engine need to maintain.
+# In unit of milli-seconds.
+# Default is 0.0 meaning that modem default value
+# of time uncertainty threshold will be used.
+#CONSTRAINED_TIME_UNCERTAINTY_THRESHOLD = 0.0
+
+# If constrained time uncertainty mode is enabled,
+# this setting specifies the power budget that
+# gps engine is allowed to spend to maintain the time
+# uncertainty.
+# Default is 0 meaning that GPS engine is not constained
+# by power budget and can spend as much power as needed.
+# In unit of 0.1 milli watt second.
+#CONSTRAINED_TIME_UNCERTAINTY_ENERGY_BUDGET = 0
+
+##################################################
+# POSITION ASSISTED CLOCK ESTIMATOR
+##################################################
+# 0 : disabled (default)
+# 1 : enabled
+# This setting enables GPS engine to estimate clock
+# bias and drift when the signal from at least 1
+# SV is available and the UE’s position is known by
+# other position engines.
+#POSITION_ASSISTED_CLOCK_ESTIMATOR_ENABLED = 0
+
+#####################################
+# proxyAppPackageName
+#####################################
+# This is a string that is sent to the framework
+# in nfwNotifyCb callback
+PROXY_APP_PACKAGE_NAME = com.google.android.carrierlocation
+
+#####################################
+# CP_MTLR_ES
+#####################################
+# CP MTLR ES, 1=enable, 0=disable
+CP_MTLR_ES=1
diff --git a/gpt-utils/Android.mk b/gpt-utils/Android.mk
new file mode 100644
index 00000000..6dd1a448
--- /dev/null
+++ b/gpt-utils/Android.mk
@@ -0,0 +1,46 @@
+#
+# Copyright 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_SRC_FILES := gpt-utils.cpp
+ifeq ($(TARGET_COMPILE_WITH_MSM_KERNEL),true)
+LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
+LOCAL_ADDITIONAL_DEPENDENCIES := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
+endif
+LOCAL_SHARED_LIBRARIES := liblog libz
+LOCAL_MODULE := libgptutils
+LOCAL_MODULE_OWNER := qti
+include $(BUILD_STATIC_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := gpt-utils.cpp
+ifeq ($(TARGET_COMPILE_WITH_MSM_KERNEL),true)
+LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
+LOCAL_ADDITIONAL_DEPENDENCIES := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
+endif
+LOCAL_SHARED_LIBRARIES += liblog libcutils libz
+LOCAL_EXPORT_HEADER_LIBRARY_HEADERS := libgptutils_headers
+LOCAL_MODULE := libgptutils
+LOCAL_MODULE_OWNER := qti
+LOCAL_PROPRIETARY_MODULE := true
+include $(BUILD_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libgptutils_headers
+LOCAL_EXPORT_C_INCLUDE_DIRS:=$(LOCAL_PATH)
+include $(BUILD_HEADER_LIBRARY)
diff --git a/gpt-utils/gpt-utils.cpp b/gpt-utils/gpt-utils.cpp
new file mode 100644
index 00000000..1eb94412
--- /dev/null
+++ b/gpt-utils/gpt-utils.cpp
@@ -0,0 +1,1542 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define _LARGEFILE64_SOURCE /* enable lseek64() */
+
+/******************************************************************************
+ * INCLUDE SECTION
+ ******************************************************************************/
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+
+ This program is free software; you can redistribute it and/or modify it under the terms of the MIT License..
+
+
+
diff --git a/json-c/README.md b/json-c/README.md
new file mode 100644
index 00000000..bf4d2e4f
--- /dev/null
+++ b/json-c/README.md
@@ -0,0 +1,63 @@
+`json-c`
+========
+
+Building on Unix with `git`, `gcc` and `autotools`
+--------------------------------------------------
+
+Home page for json-c: https://github.com/json-c/json-c/wiki
+
+Caution: do **NOT** use sources from svn.metaparadigm.com,
+they are old.
+
+Prerequisites:
+
+ - `gcc`, `clang`, or another C compiler
+ - `libtool`
+
+If you're not using a release tarball, you'll also need:
+
+ - `autoconf` (`autoreconf`)
+ - `automake`
+
+Make sure you have a complete `libtool` install, including `libtoolize`.
+
+`json-c` GitHub repo: https://github.com/json-c/json-c
+
+```bash
+$ git clone https://github.com/json-c/json-c.git
+$ cd json-c
+$ sh autogen.sh
+```
+
+followed by
+
+```bash
+$ ./configure
+$ make
+$ make install
+```
+
+To build and run the test programs:
+
+```bash
+$ make check
+```
+
+Linking to `libjson-c`
+----------------------
+
+If your system has `pkgconfig`,
+then you can just add this to your `makefile`:
+
+```make
+CFLAGS += $(shell pkg-config --cflags json-c)
+LDFLAGS += $(shell pkg-config --libs json-c)
+```
+
+Without `pkgconfig`, you would do something like this:
+
+```make
+JSON_C_DIR=/path/to/json_c/install
+CFLAGS += -I$(JSON_C_DIR)/include/json-c
+LDFLAGS+= -L$(JSON_C_DIR)/lib -ljson-c
+```
diff --git a/json-c/RELEASE_CHECKLIST.txt b/json-c/RELEASE_CHECKLIST.txt
new file mode 100644
index 00000000..47132582
--- /dev/null
+++ b/json-c/RELEASE_CHECKLIST.txt
@@ -0,0 +1,132 @@
+
+Release checklist:
+
+release=0.12
+git clone https://github.com/json-c/json-c json-c-${release}
+cd json-c-${release}
+
+Check that the compile works on Linux
+Check that the compile works on NetBSD
+Check that the compile works on Windows
+Check ChangeLog to see if anything should be added.
+Make any fixes/changes *before* branching.
+
+ git branch json-c-${release}
+ git checkout json-c-${release}
+
+------------
+
+Update the version in json_c_version.h
+Update the version in Doxyfile
+Update the version in configure.ac
+ Use ${release}.
+
+Update the libjson_la_LDFLAGS line in Makefile.am to the new version.
+ Generally, unless we're doing a major release, change:
+ -version-info x:y:z
+ to
+ -version-info x:y+1:z
+
+------------
+
+Generate the configure script and other files:
+ sh autogen.sh
+ git add -f Makefile.in aclocal.m4 config.guess \
+ config.sub configure depcomp install-sh \
+ ltmain.sh missing tests/Makefile.in \
+ INSTALL
+
+ # check for anything else to be added:
+ git status --ignored
+ git commit
+
+------------
+
+Generate the doxygen documentation:
+ doxygen
+ git add -f doc
+ git commit doc
+
+------------
+
+cd ..
+echo .git > excludes
+echo autom4te.cache >> excludes
+tar -czf json-c-${release}.tar.gz -X excludes json-c-${release}
+
+echo doc >> excludes
+tar -czf json-c-${release}-nodoc.tar.gz -X excludes json-c-${release}
+
+------------
+
+Tag the branch:
+cd json-c-${release}
+git tag -a json-c-${release}-$(date +%Y%m%d) -m "Release json-c-${release}"
+
+git push origin json-c-${release}
+git push --tags
+
+------------
+
+Go to Amazon S3 service at:
+ https://console.aws.amazon.com/s3/
+
+Upload the two tarballs in the json-c_releases folder.
+ When uploading, use "Reduced Redundancy", and make the uploaded files publicly accessible.
+
+Logout of Amazon S3, and verify that the files are visible.
+ https://s3.amazonaws.com/json-c_releases/releases/index.html
+
+===================================
+
+Post-release checklist:
+
+git checkout master
+Add new section to ChangeLog
+Update the version in json_c_version.h
+Update the version in Doxyfile
+Update the version in configure.ac
+ Use ${release}.99 to indicate a version "newer" than anything on the branch.
+
+Leave the libjson_la_LDFLAGS line in Makefile.am alone.
+ For more details see:
+ http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
+
+------------
+
+Update the gh-pages branch with new docs:
+
+cd json-c-${release}
+git checkout json-c-${release}
+cd ..
+
+git clone -b gh-pages https://github.com/json-c/json-c json-c-pages
+cd json-c-pages
+mkdir json-c-${release}
+cp -R ../json-c-${release}/doc json-c-${release}/.
+cp ../json-c-${release}/README-WIN32.html json-c-${release}/.
+git add json-c-${release}
+git commit
+
+vi index.html
+ Add/change links to current release.
+
+git commit index.html
+
+git push
+
+------------
+
+Update checksums on wiki page.
+
+cd ..
+openssl sha -sha256 json-c*gz
+openssl md5 json-c*gz
+
+Copy and paste this output into the wiki page at:
+ https://github.com/json-c/json-c/wiki
+
+------------
+
+Send an email to the mailing list.
+
diff --git a/json-c/arraylist.c b/json-c/arraylist.c
new file mode 100644
index 00000000..1d899fa9
--- /dev/null
+++ b/json-c/arraylist.c
@@ -0,0 +1,102 @@
+/*
+ * $Id: arraylist.c,v 1.4 2006/01/26 02:16:28 mclark Exp $
+ *
+ * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
+ * Michael Clark
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See COPYING for details.
+ *
+ */
+
+#include "config.h"
+
+#ifdef STDC_HEADERS
+# include
+# include
+#endif /* STDC_HEADERS */
+
+#if defined(HAVE_STRINGS_H) && !defined(_STRING_H) && !defined(__USE_BSD)
+# include
+#endif /* HAVE_STRINGS_H */
+
+#include "arraylist.h"
+
+struct array_list*
+array_list_new(array_list_free_fn *free_fn)
+{
+ struct array_list *arr;
+
+ arr = (struct array_list*)calloc(1, sizeof(struct array_list));
+ if(!arr) return NULL;
+ arr->size = ARRAY_LIST_DEFAULT_SIZE;
+ arr->length = 0;
+ arr->free_fn = free_fn;
+ if(!(arr->array = (void**)calloc(sizeof(void*), arr->size))) {
+ free(arr);
+ return NULL;
+ }
+ return arr;
+}
+
+extern void
+array_list_free(struct array_list *arr)
+{
+ int i;
+ for(i = 0; i < arr->length; i++)
+ if(arr->array[i]) arr->free_fn(arr->array[i]);
+ free(arr->array);
+ free(arr);
+}
+
+void*
+array_list_get_idx(struct array_list *arr, int i)
+{
+ if(i >= arr->length) return NULL;
+ return arr->array[i];
+}
+
+static int array_list_expand_internal(struct array_list *arr, int max)
+{
+ void *t;
+ int new_size;
+
+ if(max < arr->size) return 0;
+ new_size = arr->size << 1;
+ if (new_size < max)
+ new_size = max;
+ if(!(t = realloc(arr->array, new_size*sizeof(void*)))) return -1;
+ arr->array = (void**)t;
+ (void)memset(arr->array + arr->size, 0, (new_size-arr->size)*sizeof(void*));
+ arr->size = new_size;
+ return 0;
+}
+
+int
+array_list_put_idx(struct array_list *arr, int idx, void *data)
+{
+ if(array_list_expand_internal(arr, idx+1)) return -1;
+ if(arr->array[idx]) arr->free_fn(arr->array[idx]);
+ arr->array[idx] = data;
+ if(arr->length <= idx) arr->length = idx + 1;
+ return 0;
+}
+
+int
+array_list_add(struct array_list *arr, void *data)
+{
+ return array_list_put_idx(arr, arr->length, data);
+}
+
+void
+array_list_sort(struct array_list *arr, int(*sort_fn)(const void *, const void *))
+{
+ qsort(arr->array, arr->length, sizeof(arr->array[0]),
+ (int (*)(const void *, const void *))sort_fn);
+}
+
+int
+array_list_length(struct array_list *arr)
+{
+ return arr->length;
+}
diff --git a/json-c/arraylist.h b/json-c/arraylist.h
new file mode 100644
index 00000000..4f3113c0
--- /dev/null
+++ b/json-c/arraylist.h
@@ -0,0 +1,56 @@
+/*
+ * $Id: arraylist.h,v 1.4 2006/01/26 02:16:28 mclark Exp $
+ *
+ * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
+ * Michael Clark
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See COPYING for details.
+ *
+ */
+
+#ifndef _arraylist_h_
+#define _arraylist_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ARRAY_LIST_DEFAULT_SIZE 32
+
+typedef void (array_list_free_fn) (void *data);
+
+struct array_list
+{
+ void **array;
+ int length;
+ int size;
+ array_list_free_fn *free_fn;
+};
+
+extern struct array_list*
+array_list_new(array_list_free_fn *free_fn);
+
+extern void
+array_list_free(struct array_list *al);
+
+extern void*
+array_list_get_idx(struct array_list *al, int i);
+
+extern int
+array_list_put_idx(struct array_list *al, int i, void *data);
+
+extern int
+array_list_add(struct array_list *al, void *data);
+
+extern int
+array_list_length(struct array_list *al);
+
+extern void
+array_list_sort(struct array_list *arr, int(*compar)(const void *, const void *));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/json-c/autogen.sh b/json-c/autogen.sh
new file mode 100755
index 00000000..69e765a6
--- /dev/null
+++ b/json-c/autogen.sh
@@ -0,0 +1,13 @@
+#!/bin/sh
+autoreconf -v --install || exit 1
+
+# If there are any options, assume the user wants to run configure.
+# To run configure w/o any options, use ./autogen.sh --configure
+if [ $# -gt 0 ] ; then
+ case "$1" in
+ --conf*)
+ shift 1
+ ;;
+ esac
+ exec ./configure "$@"
+fi
diff --git a/json-c/bits.h b/json-c/bits.h
new file mode 100644
index 00000000..d14a1db0
--- /dev/null
+++ b/json-c/bits.h
@@ -0,0 +1,35 @@
+/**
+ * @file
+ * @deprecated Use json_util.h instead.
+ *
+ * $Id: bits.h,v 1.10 2006/01/30 23:07:57 mclark Exp $
+ *
+ * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
+ * Michael Clark
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See COPYING for details.
+ *
+ */
+
+#ifndef _bits_h_
+#define _bits_h_
+
+/**
+ * @deprecated
+ */
+#define hexdigit(x) (((x) <= '9') ? (x) - '0' : ((x) & 7) + 9)
+/**
+ * @deprecated
+ */
+#define error_ptr(error) ((void*)error)
+/**
+ * @deprecated
+ */
+#define error_description(error) (json_tokener_get_error(error))
+/**
+ * @deprecated
+ */
+#define is_error(ptr) (ptr == NULL)
+
+#endif
diff --git a/json-c/check.log b/json-c/check.log
new file mode 100644
index 00000000..3c73d2ae
--- /dev/null
+++ b/json-c/check.log
@@ -0,0 +1,2 @@
+HEAD is now at 6442a2f... json-c: Add libjson to the vendor image
+HEAD is now at 6442a2f... json-c: Add libjson to the vendor image
diff --git a/json-c/config.h b/json-c/config.h
new file mode 100644
index 00000000..f958d440
--- /dev/null
+++ b/json-c/config.h
@@ -0,0 +1,178 @@
+/* config.h. Generated from config.h.in by configure. */
+/* config.h.in. Generated from configure.ac by autoheader. */
+
+/* Enable RDRANR Hardware RNG Hash Seed */
+/* #undef ENABLE_RDRAND */
+
+/* Define if .gnu.warning accepts long strings. */
+/* #undef HAS_GNU_WARNING_LONG */
+
+/* Define to 1 if you have the declaration of `INFINITY', and to 0 if you
+ don't. */
+#define HAVE_DECL_INFINITY 1
+
+/* Define to 1 if you have the declaration of `isinf', and to 0 if you don't.
+ */
+#define HAVE_DECL_ISINF 1
+
+/* Define to 1 if you have the declaration of `isnan', and to 0 if you don't.
+ */
+#define HAVE_DECL_ISNAN 1
+
+/* Define to 1 if you have the declaration of `nan', and to 0 if you don't. */
+#define HAVE_DECL_NAN 1
+
+/* Define to 1 if you have the declaration of `_finite', and to 0 if you
+ don't. */
+#define HAVE_DECL__FINITE 0
+
+/* Define to 1 if you have the declaration of `_isnan', and to 0 if you don't.
+ */
+#define HAVE_DECL__ISNAN 0
+
+/* Define to 1 if you have the header file. */
+#define HAVE_DLFCN_H 1
+
+/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
+/* #undef HAVE_DOPRNT */
+
+/* Define to 1 if you have the header file. */
+#define HAVE_ENDIAN_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_LOCALE_H 1
+
+/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
+ to 0 otherwise. */
+#define HAVE_MALLOC 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the `open' function. */
+#define HAVE_OPEN 1
+
+/* Define to 1 if your system has a GNU libc compatible `realloc' function,
+ and to 0 otherwise. */
+#define HAVE_REALLOC 1
+
+/* Define to 1 if you have the `setlocale' function. */
+#define HAVE_SETLOCALE 1
+
+/* Define to 1 if you have the `snprintf' function. */
+#define HAVE_SNPRINTF 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_STDARG_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the `strcasecmp' function. */
+#define HAVE_STRCASECMP 1
+
+/* Define to 1 if you have the `strdup' function. */
+#define HAVE_STRDUP 1
+
+/* Define to 1 if you have the `strerror' function. */
+#define HAVE_STRERROR 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the `strncasecmp' function. */
+#define HAVE_STRNCASECMP 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_SYSLOG_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_SYS_CDEFS_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the `vasprintf' function. */
+#define HAVE_VASPRINTF 1
+
+/* Define to 1 if you have the `vprintf' function. */
+#define HAVE_VPRINTF 1
+
+/* Define to 1 if you have the `vsnprintf' function. */
+#define HAVE_VSNPRINTF 1
+
+/* Define to 1 if you have the `vsyslog' function. */
+#define HAVE_VSYSLOG 1
+
+/* Public define for json_inttypes.h */
+#define JSON_C_HAVE_INTTYPES_H 1
+
+/* Define to the sub-directory in which libtool stores uninstalled libraries.
+ */
+#define LT_OBJDIR ".libs/"
+
+/* Define to 1 if your C compiler doesn't accept -c and -o together. */
+/* #undef NO_MINUS_C_MINUS_O */
+
+/* Name of package */
+#define PACKAGE "json-c"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "json-c@googlegroups.com"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "json-c"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "json-c 0.12.99"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "json-c"
+
+/* Define to the home page for this package. */
+#define PACKAGE_URL ""
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "0.12.99"
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Version number of package */
+#define VERSION "0.12.99"
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
+
+/* Define to rpl_malloc if the replacement function should be used. */
+/* #undef malloc */
+
+/* Define to rpl_realloc if the replacement function should be used. */
+/* #undef realloc */
+
+/* Define to `unsigned int' if does not define. */
+/* #undef size_t */
diff --git a/json-c/config.h.in b/json-c/config.h.in
new file mode 100644
index 00000000..af2e5fc2
--- /dev/null
+++ b/json-c/config.h.in
@@ -0,0 +1,177 @@
+/* config.h.in. Generated from configure.ac by autoheader. */
+
+/* Enable RDRANR Hardware RNG Hash Seed */
+#undef ENABLE_RDRAND
+
+/* Define if .gnu.warning accepts long strings. */
+#undef HAS_GNU_WARNING_LONG
+
+/* Define to 1 if you have the declaration of `INFINITY', and to 0 if you
+ don't. */
+#undef HAVE_DECL_INFINITY
+
+/* Define to 1 if you have the declaration of `isinf', and to 0 if you don't.
+ */
+#undef HAVE_DECL_ISINF
+
+/* Define to 1 if you have the declaration of `isnan', and to 0 if you don't.
+ */
+#undef HAVE_DECL_ISNAN
+
+/* Define to 1 if you have the declaration of `nan', and to 0 if you don't. */
+#undef HAVE_DECL_NAN
+
+/* Define to 1 if you have the declaration of `_finite', and to 0 if you
+ don't. */
+#undef HAVE_DECL__FINITE
+
+/* Define to 1 if you have the declaration of `_isnan', and to 0 if you don't.
+ */
+#undef HAVE_DECL__ISNAN
+
+/* Define to 1 if you have the header file. */
+#undef HAVE_DLFCN_H
+
+/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
+#undef HAVE_DOPRNT
+
+/* Define to 1 if you have the header file. */
+#undef HAVE_ENDIAN_H
+
+/* Define to 1 if you have the header file. */
+#undef HAVE_FCNTL_H
+
+/* Define to 1 if you have the header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the header file. */
+#undef HAVE_LIMITS_H
+
+/* Define to 1 if you have the header file. */
+#undef HAVE_LOCALE_H
+
+/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
+ to 0 otherwise. */
+#undef HAVE_MALLOC
+
+/* Define to 1 if you have the header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the `open' function. */
+#undef HAVE_OPEN
+
+/* Define to 1 if your system has a GNU libc compatible `realloc' function,
+ and to 0 otherwise. */
+#undef HAVE_REALLOC
+
+/* Define to 1 if you have the `setlocale' function. */
+#undef HAVE_SETLOCALE
+
+/* Define to 1 if you have the `snprintf' function. */
+#undef HAVE_SNPRINTF
+
+/* Define to 1 if you have the header file. */
+#undef HAVE_STDARG_H
+
+/* Define to 1 if you have the header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the `strcasecmp' function. */
+#undef HAVE_STRCASECMP
+
+/* Define to 1 if you have the `strdup' function. */
+#undef HAVE_STRDUP
+
+/* Define to 1 if you have the `strerror' function. */
+#undef HAVE_STRERROR
+
+/* Define to 1 if you have the header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the `strncasecmp' function. */
+#undef HAVE_STRNCASECMP
+
+/* Define to 1 if you have the header file. */
+#undef HAVE_SYSLOG_H
+
+/* Define to 1 if you have the header file. */
+#undef HAVE_SYS_CDEFS_H
+
+/* Define to 1 if you have the header file. */
+#undef HAVE_SYS_PARAM_H
+
+/* Define to 1 if you have the header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to 1 if you have the `vasprintf' function. */
+#undef HAVE_VASPRINTF
+
+/* Define to 1 if you have the `vprintf' function. */
+#undef HAVE_VPRINTF
+
+/* Define to 1 if you have the `vsnprintf' function. */
+#undef HAVE_VSNPRINTF
+
+/* Define to 1 if you have the `vsyslog' function. */
+#undef HAVE_VSYSLOG
+
+/* Public define for json_inttypes.h */
+#undef JSON_C_HAVE_INTTYPES_H
+
+/* Define to the sub-directory in which libtool stores uninstalled libraries.
+ */
+#undef LT_OBJDIR
+
+/* Define to 1 if your C compiler doesn't accept -c and -o together. */
+#undef NO_MINUS_C_MINUS_O
+
+/* Name of package */
+#undef PACKAGE
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the home page for this package. */
+#undef PACKAGE_URL
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Version number of package */
+#undef VERSION
+
+/* Define to empty if `const' does not conform to ANSI C. */
+#undef const
+
+/* Define to rpl_malloc if the replacement function should be used. */
+#undef malloc
+
+/* Define to rpl_realloc if the replacement function should be used. */
+#undef realloc
+
+/* Define to `unsigned int' if does not define. */
+#undef size_t
diff --git a/json-c/configure.ac b/json-c/configure.ac
new file mode 100644
index 00000000..c50f81bd
--- /dev/null
+++ b/json-c/configure.ac
@@ -0,0 +1,107 @@
+AC_PREREQ(2.52)
+
+# Process this file with autoconf to produce a configure script.
+AC_INIT([json-c], 0.12.99, [json-c@googlegroups.com])
+
+AM_INIT_AUTOMAKE
+
+AC_PROG_MAKE_SET
+
+AC_ARG_ENABLE(rdrand,
+ AS_HELP_STRING([--enable-rdrand],
+ [Enable RDRAND Hardware RNG Hash Seed generation on supported x86/x64 platforms.]),
+[if test x$enableval = xyes; then
+ enable_rdrand=yes
+ AC_DEFINE(ENABLE_RDRAND, 1, [Enable RDRANR Hardware RNG Hash Seed])
+fi])
+
+if test "x$enable_rdrand" = "xyes"; then
+ AC_MSG_RESULT([RDRAND Hardware RNG Hash Seed enabled on supported x86/x64 platforms])
+else
+ AC_MSG_RESULT([RDRAND Hardware RNG Hash Seed disabled. Use --enable-rdrand to enable])
+fi
+
+# Checks for programs.
+
+# Checks for libraries.
+
+# Checks for header files.
+AM_PROG_CC_C_O
+AC_CONFIG_HEADER(config.h)
+AC_CONFIG_HEADER(json_config.h)
+AC_HEADER_STDC
+AC_CHECK_HEADERS(fcntl.h limits.h strings.h syslog.h unistd.h [sys/cdefs.h] [sys/param.h] stdarg.h locale.h endian.h)
+AC_CHECK_HEADER(inttypes.h,[AC_DEFINE([JSON_C_HAVE_INTTYPES_H],[1],[Public define for json_inttypes.h])])
+
+# Checks for typedefs, structures, and compiler characteristics.
+AC_C_CONST
+AC_TYPE_SIZE_T
+
+# Checks for library functions.
+AC_FUNC_VPRINTF
+AC_FUNC_MEMCMP
+AC_FUNC_MALLOC
+AC_FUNC_REALLOC
+AC_CHECK_FUNCS(strcasecmp strdup strerror snprintf vsnprintf vasprintf open vsyslog strncasecmp setlocale)
+AC_CHECK_DECLS([INFINITY], [], [], [[#include ]])
+AC_CHECK_DECLS([nan], [], [], [[#include ]])
+AC_CHECK_DECLS([isnan], [], [], [[#include ]])
+AC_CHECK_DECLS([isinf], [], [], [[#include ]])
+AC_CHECK_DECLS([_isnan], [], [], [[#include ]])
+AC_CHECK_DECLS([_finite], [], [], [[#include ]])
+
+#check if .section.gnu.warning accepts long strings (for __warn_references)
+AC_LANG_PUSH([C])
+
+AC_MSG_CHECKING([if .gnu.warning accepts long strings])
+AC_LINK_IFELSE([AC_LANG_SOURCE([[
+extern void json_object_get();
+__asm__(".section .gnu.json_object_get,\n\t.ascii \"Please link against libjson-c instead of libjson\"\n\t.text");
+
+int main(int c,char* v) {return 0;}
+]])], [
+ AC_DEFINE(HAS_GNU_WARNING_LONG, 1, [Define if .gnu.warning accepts long strings.])
+ AC_MSG_RESULT(yes)
+], [
+ AC_MSG_RESULT(no)
+])
+
+AC_LANG_POP([C])
+
+AM_PROG_LIBTOOL
+
+# Check for the -Bsymbolic-functions linker flag
+AC_ARG_ENABLE([Bsymbolic],
+ [AS_HELP_STRING([--disable-Bsymbolic], [Avoid linking with -Bsymbolic-function])],
+ [],
+ [enable_Bsymbolic=check])
+
+AS_IF([test "x$enable_Bsymbolic" = "xcheck"],
+ [
+ saved_LDFLAGS="${LDFLAGS}"
+ AC_MSG_CHECKING([for -Bsymbolic-functions linker flag])
+ LDFLAGS=-Wl,-Bsymbolic-functions
+ AC_TRY_LINK([], [int main (void) { return 0; }],
+ [
+ AC_MSG_RESULT([yes])
+ enable_Bsymbolic=yes
+ ],
+ [
+ AC_MSG_RESULT([no])
+ enable_Bsymbolic=no
+ ])
+ LDFLAGS="${saved_LDFLAGS}"
+ ])
+
+AS_IF([test "x$enable_Bsymbolic" = "xyes"], [JSON_BSYMBOLIC_LDFLAGS=-Wl[,]-Bsymbolic-functions])
+AC_SUBST(JSON_BSYMBOLIC_LDFLAGS)
+
+AC_CONFIG_FILES([
+Makefile
+json-c.pc
+tests/Makefile
+json-c-uninstalled.pc
+])
+
+AC_OUTPUT
+
diff --git a/json-c/debug.c b/json-c/debug.c
new file mode 100644
index 00000000..3b64b590
--- /dev/null
+++ b/json-c/debug.c
@@ -0,0 +1,83 @@
+/*
+ * $Id: debug.c,v 1.5 2006/01/26 02:16:28 mclark Exp $
+ *
+ * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
+ * Michael Clark
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See COPYING for details.
+ *
+ */
+
+#include "config.h"
+
+#include
+#include
+#include
+#include
+
+#if HAVE_SYSLOG_H
+# include
+#endif /* HAVE_SYSLOG_H */
+
+#if HAVE_UNISTD_H
+# include
+#endif /* HAVE_UNISTD_H */
+
+#if HAVE_SYS_PARAM_H
+#include
+#endif /* HAVE_SYS_PARAM_H */
+
+#include "debug.h"
+
+static int _syslog = 0;
+static int _debug = 0;
+
+void mc_set_debug(int debug) { _debug = debug; }
+int mc_get_debug(void) { return _debug; }
+
+extern void mc_set_syslog(int syslog)
+{
+ _syslog = syslog;
+}
+
+void mc_debug(const char *msg, ...)
+{
+ va_list ap;
+ if(_debug) {
+ va_start(ap, msg);
+#if HAVE_VSYSLOG
+ if(_syslog) {
+ vsyslog(LOG_DEBUG, msg, ap);
+ } else
+#endif
+ vprintf(msg, ap);
+ va_end(ap);
+ }
+}
+
+void mc_error(const char *msg, ...)
+{
+ va_list ap;
+ va_start(ap, msg);
+#if HAVE_VSYSLOG
+ if(_syslog) {
+ vsyslog(LOG_ERR, msg, ap);
+ } else
+#endif
+ vfprintf(stderr, msg, ap);
+ va_end(ap);
+}
+
+void mc_info(const char *msg, ...)
+{
+ va_list ap;
+ va_start(ap, msg);
+#if HAVE_VSYSLOG
+ if(_syslog) {
+ vsyslog(LOG_INFO, msg, ap);
+ } else
+#endif
+ vfprintf(stderr, msg, ap);
+ va_end(ap);
+}
diff --git a/json-c/debug.h b/json-c/debug.h
new file mode 100644
index 00000000..80ca3e43
--- /dev/null
+++ b/json-c/debug.h
@@ -0,0 +1,71 @@
+/*
+ * $Id: debug.h,v 1.5 2006/01/30 23:07:57 mclark Exp $
+ *
+ * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
+ * Michael Clark
+ * Copyright (c) 2009 Hewlett-Packard Development Company, L.P.
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See COPYING for details.
+ *
+ */
+
+#ifndef _DEBUG_H_
+#define _DEBUG_H_
+
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern void mc_set_debug(int debug);
+extern int mc_get_debug(void);
+
+extern void mc_set_syslog(int syslog);
+
+extern void mc_debug(const char *msg, ...);
+extern void mc_error(const char *msg, ...);
+extern void mc_info(const char *msg, ...);
+
+#ifndef __STRING
+#define __STRING(x) #x
+#endif
+
+#ifndef PARSER_BROKEN_FIXED
+
+#define JASSERT(cond) do {} while(0)
+
+#else
+
+#define JASSERT(cond) do { \
+ if (!(cond)) { \
+ mc_error("cjson assert failure %s:%d : cond \"" __STRING(cond) "failed\n", __FILE__, __LINE__); \
+ *(int *)0 = 1;\
+ abort(); \
+ }\
+ } while(0)
+
+#endif
+
+#define MC_ERROR(x, ...) mc_error(x, ##__VA_ARGS__)
+
+#ifdef MC_MAINTAINER_MODE
+#define MC_SET_DEBUG(x) mc_set_debug(x)
+#define MC_GET_DEBUG() mc_get_debug()
+#define MC_SET_SYSLOG(x) mc_set_syslog(x)
+#define MC_DEBUG(x, ...) mc_debug(x, ##__VA_ARGS__)
+#define MC_INFO(x, ...) mc_info(x, ##__VA_ARGS__)
+#else
+#define MC_SET_DEBUG(x) if (0) mc_set_debug(x)
+#define MC_GET_DEBUG() (0)
+#define MC_SET_SYSLOG(x) if (0) mc_set_syslog(x)
+#define MC_DEBUG(x, ...) if (0) mc_debug(x, ##__VA_ARGS__)
+#define MC_INFO(x, ...) if (0) mc_info(x, ##__VA_ARGS__)
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/json-c/json-c-uninstalled.pc.in b/json-c/json-c-uninstalled.pc.in
new file mode 100644
index 00000000..dab2bab5
--- /dev/null
+++ b/json-c/json-c-uninstalled.pc.in
@@ -0,0 +1,11 @@
+prefix=
+exec_prefix=
+libdir=@abs_top_builddir@
+includedir=@abs_top_srcdir@
+
+Name: json
+Description: JSON implementation in C
+Version: @VERSION@
+Requires:
+Libs: -L@abs_top_builddir@ -ljson-c
+Cflags: -I@abs_top_srcdir@
diff --git a/json-c/json-c.pc.in b/json-c/json-c.pc.in
new file mode 100644
index 00000000..037739d2
--- /dev/null
+++ b/json-c/json-c.pc.in
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: json-c
+Description: JSON implementation in C
+Version: @VERSION@
+Requires:
+Libs: -L${libdir} -ljson-c
+Cflags: -I${includedir}/json-c
diff --git a/json-c/json.h b/json-c/json.h
new file mode 100644
index 00000000..e198f5da
--- /dev/null
+++ b/json-c/json.h
@@ -0,0 +1,33 @@
+/*
+ * $Id: json.h,v 1.6 2006/01/26 02:16:28 mclark Exp $
+ *
+ * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
+ * Michael Clark
+ * Copyright (c) 2009 Hewlett-Packard Development Company, L.P.
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See COPYING for details.
+ *
+ */
+
+#ifndef _json_h_
+#define _json_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "debug.h"
+#include "linkhash.h"
+#include "arraylist.h"
+#include "json_util.h"
+#include "json_object.h"
+#include "json_tokener.h"
+#include "json_object_iterator.h"
+#include "json_c_version.h"
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/json-c/json_c_version.c b/json-c/json_c_version.c
new file mode 100644
index 00000000..13eb1885
--- /dev/null
+++ b/json-c/json_c_version.c
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2012 Eric Haszlakiewicz
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See COPYING for details.
+ */
+#include "config.h"
+
+#include "json_c_version.h"
+
+const char *json_c_version(void)
+{
+ return JSON_C_VERSION;
+}
+
+int json_c_version_num(void)
+{
+ return JSON_C_VERSION_NUM;
+}
+
diff --git a/json-c/json_c_version.h b/json-c/json_c_version.h
new file mode 100644
index 00000000..d77f1a74
--- /dev/null
+++ b/json-c/json_c_version.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2012 Eric Haszlakiewicz
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See COPYING for details.
+ */
+
+#ifndef _json_c_version_h_
+#define _json_c_version_h_
+
+#define JSON_C_MAJOR_VERSION 0
+#define JSON_C_MINOR_VERSION 12
+#define JSON_C_MICRO_VERSION 99
+#define JSON_C_VERSION_NUM ((JSON_C_MAJOR_VERSION << 16) | \
+ (JSON_C_MINOR_VERSION << 8) | \
+ JSON_C_MICRO_VERSION)
+#define JSON_C_VERSION "0.12.99"
+
+const char *json_c_version(void); /* Returns JSON_C_VERSION */
+int json_c_version_num(void); /* Returns JSON_C_VERSION_NUM */
+
+#endif
diff --git a/json-c/json_config.h b/json-c/json_config.h
new file mode 100644
index 00000000..965ff1c3
--- /dev/null
+++ b/json-c/json_config.h
@@ -0,0 +1,4 @@
+/* json_config.h. Generated from json_config.h.in by configure. */
+
+/* Define to 1 if you have the header file. */
+#define JSON_C_HAVE_INTTYPES_H 1
diff --git a/json-c/json_config.h.in b/json-c/json_config.h.in
new file mode 100644
index 00000000..7888e021
--- /dev/null
+++ b/json-c/json_config.h.in
@@ -0,0 +1,3 @@
+
+/* Define to 1 if you have the header file. */
+#undef JSON_C_HAVE_INTTYPES_H
diff --git a/json-c/json_inttypes.h b/json-c/json_inttypes.h
new file mode 100644
index 00000000..9de8d246
--- /dev/null
+++ b/json-c/json_inttypes.h
@@ -0,0 +1,28 @@
+
+#ifndef _json_inttypes_h_
+#define _json_inttypes_h_
+
+#include "json_config.h"
+
+#if defined(_MSC_VER) && _MSC_VER <= 1700
+
+/* Anything less than Visual Studio C++ 10 is missing stdint.h and inttypes.h */
+typedef __int32 int32_t;
+#define INT32_MIN ((int32_t)_I32_MIN)
+#define INT32_MAX ((int32_t)_I32_MAX)
+typedef __int64 int64_t;
+#define INT64_MIN ((int64_t)_I64_MIN)
+#define INT64_MAX ((int64_t)_I64_MAX)
+#define PRId64 "I64d"
+#define SCNd64 "I64d"
+
+#else
+
+#ifdef JSON_C_HAVE_INTTYPES_H
+#include
+#endif
+/* inttypes.h includes stdint.h */
+
+#endif
+
+#endif
diff --git a/json-c/json_object.c b/json-c/json_object.c
new file mode 100644
index 00000000..8ed02398
--- /dev/null
+++ b/json-c/json_object.c
@@ -0,0 +1,913 @@
+/*
+ * $Id: json_object.c,v 1.17 2006/07/25 03:24:50 mclark Exp $
+ *
+ * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
+ * Michael Clark
+ * Copyright (c) 2009 Hewlett-Packard Development Company, L.P.
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See COPYING for details.
+ *
+ */
+
+#include "config.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "debug.h"
+#include "printbuf.h"
+#include "linkhash.h"
+#include "arraylist.h"
+#include "json_inttypes.h"
+#include "json_object.h"
+#include "json_object_private.h"
+#include "json_util.h"
+#include "math_compat.h"
+
+#if !defined(HAVE_STRDUP) && defined(_MSC_VER)
+ /* MSC has the version as _strdup */
+# define strdup _strdup
+#elif !defined(HAVE_STRDUP)
+# error You do not have strdup on your system.
+#endif /* HAVE_STRDUP */
+
+#if !defined(HAVE_SNPRINTF) && defined(_MSC_VER)
+ /* MSC has the version as _snprintf */
+# define snprintf _snprintf
+#elif !defined(HAVE_SNPRINTF)
+# error You do not have snprintf on your system.
+#endif /* HAVE_SNPRINTF */
+
+// Don't define this. It's not thread-safe.
+/* #define REFCOUNT_DEBUG 1 */
+
+const char *json_number_chars = "0123456789.+-eE";
+const char *json_hex_chars = "0123456789abcdefABCDEF";
+
+static void json_object_generic_delete(struct json_object* jso);
+static struct json_object* json_object_new(enum json_type o_type);
+
+static json_object_to_json_string_fn json_object_object_to_json_string;
+static json_object_to_json_string_fn json_object_boolean_to_json_string;
+static json_object_to_json_string_fn json_object_int_to_json_string;
+static json_object_to_json_string_fn json_object_double_to_json_string;
+static json_object_to_json_string_fn json_object_string_to_json_string;
+static json_object_to_json_string_fn json_object_array_to_json_string;
+
+
+/* ref count debugging */
+
+#ifdef REFCOUNT_DEBUG
+
+static struct lh_table *json_object_table;
+
+static void json_object_init(void) __attribute__ ((constructor));
+static void json_object_init(void) {
+ MC_DEBUG("json_object_init: creating object table\n");
+ json_object_table = lh_kptr_table_new(128, "json_object_table", NULL);
+}
+
+static void json_object_fini(void) __attribute__ ((destructor));
+static void json_object_fini(void)
+{
+ struct lh_entry *ent;
+ if (MC_GET_DEBUG())
+ {
+ if (json_object_table->count)
+ {
+ MC_DEBUG("json_object_fini: %d referenced objects at exit\n",
+ json_object_table->count);
+ lh_foreach(json_object_table, ent)
+ {
+ struct json_object* obj = (struct json_object*)ent->v;
+ MC_DEBUG("\t%s:%p\n", json_type_to_name(obj->o_type), obj);
+ }
+ }
+ }
+ MC_DEBUG("json_object_fini: freeing object table\n");
+ lh_table_free(json_object_table);
+}
+#endif /* REFCOUNT_DEBUG */
+
+
+/* string escaping */
+
+static int json_escape_str(struct printbuf *pb, char *str, int len)
+{
+ int pos = 0, start_offset = 0;
+ unsigned char c;
+ while (len--)
+ {
+ c = str[pos];
+ switch(c)
+ {
+ case '\b':
+ case '\n':
+ case '\r':
+ case '\t':
+ case '\f':
+ case '"':
+ case '\\':
+ case '/':
+ if(pos - start_offset > 0)
+ printbuf_memappend(pb, str + start_offset, pos - start_offset);
+
+ if(c == '\b') printbuf_memappend(pb, "\\b", 2);
+ else if(c == '\n') printbuf_memappend(pb, "\\n", 2);
+ else if(c == '\r') printbuf_memappend(pb, "\\r", 2);
+ else if(c == '\t') printbuf_memappend(pb, "\\t", 2);
+ else if(c == '\f') printbuf_memappend(pb, "\\f", 2);
+ else if(c == '"') printbuf_memappend(pb, "\\\"", 2);
+ else if(c == '\\') printbuf_memappend(pb, "\\\\", 2);
+ else if(c == '/') printbuf_memappend(pb, "\\/", 2);
+
+ start_offset = ++pos;
+ break;
+ default:
+ if(c < ' ')
+ {
+ if(pos - start_offset > 0)
+ printbuf_memappend(pb, str + start_offset, pos - start_offset);
+ sprintbuf(pb, "\\u00%c%c",
+ json_hex_chars[c >> 4],
+ json_hex_chars[c & 0xf]);
+ start_offset = ++pos;
+ } else
+ pos++;
+ }
+ }
+ if (pos - start_offset > 0)
+ printbuf_memappend(pb, str + start_offset, pos - start_offset);
+ return 0;
+}
+
+
+/* reference counting */
+
+extern struct json_object* json_object_get(struct json_object *jso)
+{
+ if (jso)
+ jso->_ref_count++;
+ return jso;
+}
+
+int json_object_put(struct json_object *jso)
+{
+ if(jso)
+ {
+ jso->_ref_count--;
+ if(!jso->_ref_count)
+ {
+ if (jso->_user_delete)
+ jso->_user_delete(jso, jso->_userdata);
+ jso->_delete(jso);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+
+/* generic object construction and destruction parts */
+
+static void json_object_generic_delete(struct json_object* jso)
+{
+#ifdef REFCOUNT_DEBUG
+ MC_DEBUG("json_object_delete_%s: %p\n",
+ json_type_to_name(jso->o_type), jso);
+ lh_table_delete(json_object_table, jso);
+#endif /* REFCOUNT_DEBUG */
+ printbuf_free(jso->_pb);
+ free(jso);
+}
+
+static struct json_object* json_object_new(enum json_type o_type)
+{
+ struct json_object *jso;
+
+ jso = (struct json_object*)calloc(sizeof(struct json_object), 1);
+ if (!jso)
+ return NULL;
+ jso->o_type = o_type;
+ jso->_ref_count = 1;
+ jso->_delete = &json_object_generic_delete;
+#ifdef REFCOUNT_DEBUG
+ lh_table_insert(json_object_table, jso, jso);
+ MC_DEBUG("json_object_new_%s: %p\n", json_type_to_name(jso->o_type), jso);
+#endif /* REFCOUNT_DEBUG */
+ return jso;
+}
+
+
+/* type checking functions */
+
+int json_object_is_type(struct json_object *jso, enum json_type type)
+{
+ if (!jso)
+ return (type == json_type_null);
+ return (jso->o_type == type);
+}
+
+enum json_type json_object_get_type(struct json_object *jso)
+{
+ if (!jso)
+ return json_type_null;
+ return jso->o_type;
+}
+
+/* set a custom conversion to string */
+
+void json_object_set_serializer(json_object *jso,
+ json_object_to_json_string_fn to_string_func,
+ void *userdata,
+ json_object_delete_fn *user_delete)
+{
+ // First, clean up any previously existing user info
+ if (jso->_user_delete)
+ {
+ jso->_user_delete(jso, jso->_userdata);
+ }
+ jso->_userdata = NULL;
+ jso->_user_delete = NULL;
+
+ if (to_string_func == NULL)
+ {
+ // Reset to the standard serialization function
+ switch(jso->o_type)
+ {
+ case json_type_null:
+ jso->_to_json_string = NULL;
+ break;
+ case json_type_boolean:
+ jso->_to_json_string = &json_object_boolean_to_json_string;
+ break;
+ case json_type_double:
+ jso->_to_json_string = &json_object_double_to_json_string;
+ break;
+ case json_type_int:
+ jso->_to_json_string = &json_object_int_to_json_string;
+ break;
+ case json_type_object:
+ jso->_to_json_string = &json_object_object_to_json_string;
+ break;
+ case json_type_array:
+ jso->_to_json_string = &json_object_array_to_json_string;
+ break;
+ case json_type_string:
+ jso->_to_json_string = &json_object_string_to_json_string;
+ break;
+ }
+ return;
+ }
+
+ jso->_to_json_string = to_string_func;
+ jso->_userdata = userdata;
+ jso->_user_delete = user_delete;
+}
+
+
+/* extended conversion to string */
+
+const char* json_object_to_json_string_ext(struct json_object *jso, int flags)
+{
+ if (!jso)
+ return "null";
+
+ if ((!jso->_pb) && !(jso->_pb = printbuf_new()))
+ return NULL;
+
+ printbuf_reset(jso->_pb);
+
+ if(jso->_to_json_string(jso, jso->_pb, 0, flags) < 0)
+ return NULL;
+
+ return jso->_pb->buf;
+}
+
+/* backwards-compatible conversion to string */
+
+const char* json_object_to_json_string(struct json_object *jso)
+{
+ return json_object_to_json_string_ext(jso, JSON_C_TO_STRING_SPACED);
+}
+
+static void indent(struct printbuf *pb, int level, int flags)
+{
+ if (flags & JSON_C_TO_STRING_PRETTY)
+ {
+ printbuf_memset(pb, -1, ' ', level * 2);
+ }
+}
+
+/* json_object_object */
+
+static int json_object_object_to_json_string(struct json_object* jso,
+ struct printbuf *pb,
+ int level,
+ int flags)
+{
+ int had_children = 0;
+ struct json_object_iter iter;
+
+ sprintbuf(pb, "{" /*}*/);
+ if (flags & JSON_C_TO_STRING_PRETTY)
+ sprintbuf(pb, "\n");
+ json_object_object_foreachC(jso, iter)
+ {
+ if (had_children)
+ {
+ sprintbuf(pb, ",");
+ if (flags & JSON_C_TO_STRING_PRETTY)
+ sprintbuf(pb, "\n");
+ }
+ had_children = 1;
+ if (flags & JSON_C_TO_STRING_SPACED)
+ sprintbuf(pb, " ");
+ indent(pb, level+1, flags);
+ sprintbuf(pb, "\"");
+ json_escape_str(pb, iter.key, strlen(iter.key));
+ if (flags & JSON_C_TO_STRING_SPACED)
+ sprintbuf(pb, "\": ");
+ else
+ sprintbuf(pb, "\":");
+ if(iter.val == NULL)
+ sprintbuf(pb, "null");
+ else
+ iter.val->_to_json_string(iter.val, pb, level+1,flags);
+ }
+ if (flags & JSON_C_TO_STRING_PRETTY)
+ {
+ if (had_children)
+ sprintbuf(pb, "\n");
+ indent(pb,level,flags);
+ }
+ if (flags & JSON_C_TO_STRING_SPACED)
+ return sprintbuf(pb, /*{*/ " }");
+ else
+ return sprintbuf(pb, /*{*/ "}");
+}
+
+
+static void json_object_lh_entry_free(struct lh_entry *ent)
+{
+ free(ent->k);
+ json_object_put((struct json_object*)ent->v);
+}
+
+static void json_object_object_delete(struct json_object* jso)
+{
+ lh_table_free(jso->o.c_object);
+ json_object_generic_delete(jso);
+}
+
+struct json_object* json_object_new_object(void)
+{
+ struct json_object *jso = json_object_new(json_type_object);
+ if (!jso)
+ return NULL;
+ jso->_delete = &json_object_object_delete;
+ jso->_to_json_string = &json_object_object_to_json_string;
+ jso->o.c_object = lh_kchar_table_new(JSON_OBJECT_DEF_HASH_ENTRIES,
+ NULL, &json_object_lh_entry_free);
+ if (!jso->o.c_object)
+ {
+ json_object_generic_delete(jso);
+ errno = ENOMEM;
+ return NULL;
+ }
+ return jso;
+}
+
+struct lh_table* json_object_get_object(struct json_object *jso)
+{
+ if (!jso)
+ return NULL;
+ switch(jso->o_type)
+ {
+ case json_type_object:
+ return jso->o.c_object;
+ default:
+ return NULL;
+ }
+}
+
+void json_object_object_add(struct json_object* jso, const char *key,
+ struct json_object *val)
+{
+ // We lookup the entry and replace the value, rather than just deleting
+ // and re-adding it, so the existing key remains valid.
+ json_object *existing_value = NULL;
+ struct lh_entry *existing_entry;
+ existing_entry = lh_table_lookup_entry(jso->o.c_object, (void*)key);
+ if (!existing_entry)
+ {
+ lh_table_insert(jso->o.c_object, strdup(key), val);
+ return;
+ }
+ existing_value = (void *)existing_entry->v;
+ if (existing_value)
+ json_object_put(existing_value);
+ existing_entry->v = val;
+}
+
+int json_object_object_length(struct json_object *jso)
+{
+ return lh_table_length(jso->o.c_object);
+}
+
+struct json_object* json_object_object_get(struct json_object* jso, const char *key)
+{
+ struct json_object *result = NULL;
+ json_object_object_get_ex(jso, key, &result);
+ return result;
+}
+
+json_bool json_object_object_get_ex(struct json_object* jso, const char *key, struct json_object **value)
+{
+ if (value != NULL)
+ *value = NULL;
+
+ if (NULL == jso)
+ return FALSE;
+
+ switch(jso->o_type)
+ {
+ case json_type_object:
+ return lh_table_lookup_ex(jso->o.c_object, (void*)key, (void**)value);
+ default:
+ if (value != NULL)
+ *value = NULL;
+ return FALSE;
+ }
+}
+
+void json_object_object_del(struct json_object* jso, const char *key)
+{
+ lh_table_delete(jso->o.c_object, key);
+}
+
+
+/* json_object_boolean */
+
+static int json_object_boolean_to_json_string(struct json_object* jso,
+ struct printbuf *pb,
+ int level,
+ int flags)
+{
+ if (jso->o.c_boolean)
+ return sprintbuf(pb, "true");
+ else
+ return sprintbuf(pb, "false");
+}
+
+struct json_object* json_object_new_boolean(json_bool b)
+{
+ struct json_object *jso = json_object_new(json_type_boolean);
+ if (!jso)
+ return NULL;
+ jso->_to_json_string = &json_object_boolean_to_json_string;
+ jso->o.c_boolean = b;
+ return jso;
+}
+
+json_bool json_object_get_boolean(struct json_object *jso)
+{
+ if (!jso)
+ return FALSE;
+ switch(jso->o_type)
+ {
+ case json_type_boolean:
+ return jso->o.c_boolean;
+ case json_type_int:
+ return (jso->o.c_int64 != 0);
+ case json_type_double:
+ return (jso->o.c_double != 0);
+ case json_type_string:
+ return (jso->o.c_string.len != 0);
+ default:
+ return FALSE;
+ }
+}
+
+
+/* json_object_int */
+
+static int json_object_int_to_json_string(struct json_object* jso,
+ struct printbuf *pb,
+ int level,
+ int flags)
+{
+ return sprintbuf(pb, "%"PRId64, jso->o.c_int64);
+}
+
+struct json_object* json_object_new_int(int32_t i)
+{
+ struct json_object *jso = json_object_new(json_type_int);
+ if (!jso)
+ return NULL;
+ jso->_to_json_string = &json_object_int_to_json_string;
+ jso->o.c_int64 = i;
+ return jso;
+}
+
+int32_t json_object_get_int(struct json_object *jso)
+{
+ int64_t cint64;
+ enum json_type o_type;
+
+ if(!jso) return 0;
+
+ o_type = jso->o_type;
+ cint64 = jso->o.c_int64;
+
+ if (o_type == json_type_string)
+ {
+ /*
+ * Parse strings into 64-bit numbers, then use the
+ * 64-to-32-bit number handling below.
+ */
+ if (json_parse_int64(jso->o.c_string.str, &cint64) != 0)
+ return 0; /* whoops, it didn't work. */
+ o_type = json_type_int;
+ }
+
+ switch(o_type) {
+ case json_type_int:
+ /* Make sure we return the correct values for out of range numbers. */
+ if (cint64 <= INT32_MIN)
+ return INT32_MIN;
+ else if (cint64 >= INT32_MAX)
+ return INT32_MAX;
+ else
+ return (int32_t)cint64;
+ case json_type_double:
+ return (int32_t)jso->o.c_double;
+ case json_type_boolean:
+ return jso->o.c_boolean;
+ default:
+ return 0;
+ }
+}
+
+struct json_object* json_object_new_int64(int64_t i)
+{
+ struct json_object *jso = json_object_new(json_type_int);
+ if (!jso)
+ return NULL;
+ jso->_to_json_string = &json_object_int_to_json_string;
+ jso->o.c_int64 = i;
+ return jso;
+}
+
+int64_t json_object_get_int64(struct json_object *jso)
+{
+ int64_t cint;
+
+ if (!jso)
+ return 0;
+ switch(jso->o_type)
+ {
+ case json_type_int:
+ return jso->o.c_int64;
+ case json_type_double:
+ return (int64_t)jso->o.c_double;
+ case json_type_boolean:
+ return jso->o.c_boolean;
+ case json_type_string:
+ if (json_parse_int64(jso->o.c_string.str, &cint) == 0)
+ return cint;
+ default:
+ return 0;
+ }
+}
+
+
+/* json_object_double */
+
+static int json_object_double_to_json_string(struct json_object* jso,
+ struct printbuf *pb,
+ int level,
+ int flags)
+{
+ char buf[128], *p, *q;
+ int size;
+ /* Although JSON RFC does not support
+ NaN or Infinity as numeric values
+ ECMA 262 section 9.8.1 defines
+ how to handle these cases as strings */
+ if(isnan(jso->o.c_double))
+ size = snprintf(buf, sizeof(buf), "NaN");
+ else if(isinf(jso->o.c_double))
+ if(jso->o.c_double > 0)
+ size = snprintf(buf, sizeof(buf), "Infinity");
+ else
+ size = snprintf(buf, sizeof(buf), "-Infinity");
+ else
+ size = snprintf(buf, sizeof(buf), "%.17g", jso->o.c_double);
+
+ p = strchr(buf, ',');
+ if (p) {
+ *p = '.';
+ } else {
+ p = strchr(buf, '.');
+ }
+ if (p && (flags & JSON_C_TO_STRING_NOZERO)) {
+ /* last useful digit, always keep 1 zero */
+ p++;
+ for (q=p ; *q ; q++) {
+ if (*q!='0') p=q;
+ }
+ /* drop trailing zeroes */
+ *(++p) = 0;
+ size = p-buf;
+ }
+ printbuf_memappend(pb, buf, size);
+ return size;
+}
+
+struct json_object* json_object_new_double(double d)
+{
+ struct json_object *jso = json_object_new(json_type_double);
+ if (!jso)
+ return NULL;
+ jso->_to_json_string = &json_object_double_to_json_string;
+ jso->o.c_double = d;
+ return jso;
+}
+
+struct json_object* json_object_new_double_s(double d, const char *ds)
+{
+ struct json_object *jso = json_object_new_double(d);
+ if (!jso)
+ return NULL;
+
+ char *new_ds = strdup(ds);
+ if (!new_ds)
+ {
+ json_object_generic_delete(jso);
+ errno = ENOMEM;
+ return NULL;
+ }
+ json_object_set_serializer(jso, json_object_userdata_to_json_string,
+ new_ds, json_object_free_userdata);
+ return jso;
+}
+
+int json_object_userdata_to_json_string(struct json_object *jso,
+ struct printbuf *pb, int level, int flags)
+{
+ int userdata_len = strlen(jso->_userdata);
+ printbuf_memappend(pb, jso->_userdata, userdata_len);
+ return userdata_len;
+}
+
+void json_object_free_userdata(struct json_object *jso, void *userdata)
+{
+ free(userdata);
+}
+
+double json_object_get_double(struct json_object *jso)
+{
+ double cdouble;
+ char *errPtr = NULL;
+
+ if(!jso) return 0.0;
+ switch(jso->o_type) {
+ case json_type_double:
+ return jso->o.c_double;
+ case json_type_int:
+ return jso->o.c_int64;
+ case json_type_boolean:
+ return jso->o.c_boolean;
+ case json_type_string:
+ errno = 0;
+ cdouble = strtod(jso->o.c_string.str,&errPtr);
+
+ /* if conversion stopped at the first character, return 0.0 */
+ if (errPtr == jso->o.c_string.str)
+ return 0.0;
+
+ /*
+ * Check that the conversion terminated on something sensible
+ *
+ * For example, { "pay" : 123AB } would parse as 123.
+ */
+ if (*errPtr != '\0')
+ return 0.0;
+
+ /*
+ * If strtod encounters a string which would exceed the
+ * capacity of a double, it returns +/- HUGE_VAL and sets
+ * errno to ERANGE. But +/- HUGE_VAL is also a valid result
+ * from a conversion, so we need to check errno.
+ *
+ * Underflow also sets errno to ERANGE, but it returns 0 in
+ * that case, which is what we will return anyway.
+ *
+ * See CERT guideline ERR30-C
+ */
+ if ((HUGE_VAL == cdouble || -HUGE_VAL == cdouble) &&
+ (ERANGE == errno))
+ cdouble = 0.0;
+ return cdouble;
+ default:
+ return 0.0;
+ }
+}
+
+
+/* json_object_string */
+
+static int json_object_string_to_json_string(struct json_object* jso,
+ struct printbuf *pb,
+ int level,
+ int flags)
+{
+ sprintbuf(pb, "\"");
+ json_escape_str(pb, jso->o.c_string.str, jso->o.c_string.len);
+ sprintbuf(pb, "\"");
+ return 0;
+}
+
+static void json_object_string_delete(struct json_object* jso)
+{
+ free(jso->o.c_string.str);
+ json_object_generic_delete(jso);
+}
+
+struct json_object* json_object_new_string(const char *s)
+{
+ struct json_object *jso = json_object_new(json_type_string);
+ if (!jso)
+ return NULL;
+ jso->_delete = &json_object_string_delete;
+ jso->_to_json_string = &json_object_string_to_json_string;
+ jso->o.c_string.str = strdup(s);
+ if (!jso->o.c_string.str)
+ {
+ json_object_generic_delete(jso);
+ errno = ENOMEM;
+ return NULL;
+ }
+ jso->o.c_string.len = strlen(s);
+ return jso;
+}
+
+struct json_object* json_object_new_string_len(const char *s, int len)
+{
+ struct json_object *jso = json_object_new(json_type_string);
+ if (!jso)
+ return NULL;
+ jso->_delete = &json_object_string_delete;
+ jso->_to_json_string = &json_object_string_to_json_string;
+ jso->o.c_string.str = (char*)malloc(len + 1);
+ if (!jso->o.c_string.str)
+ {
+ json_object_generic_delete(jso);
+ errno = ENOMEM;
+ return NULL;
+ }
+ memcpy(jso->o.c_string.str, (void *)s, len);
+ jso->o.c_string.str[len] = '\0';
+ jso->o.c_string.len = len;
+ return jso;
+}
+
+const char* json_object_get_string(struct json_object *jso)
+{
+ if (!jso)
+ return NULL;
+ switch(jso->o_type)
+ {
+ case json_type_string:
+ return jso->o.c_string.str;
+ default:
+ return json_object_to_json_string(jso);
+ }
+}
+
+int json_object_get_string_len(struct json_object *jso)
+{
+ if (!jso)
+ return 0;
+ switch(jso->o_type)
+ {
+ case json_type_string:
+ return jso->o.c_string.len;
+ default:
+ return 0;
+ }
+}
+
+
+/* json_object_array */
+
+static int json_object_array_to_json_string(struct json_object* jso,
+ struct printbuf *pb,
+ int level,
+ int flags)
+{
+ int had_children = 0;
+ int ii;
+ sprintbuf(pb, "[");
+ if (flags & JSON_C_TO_STRING_PRETTY)
+ sprintbuf(pb, "\n");
+ for(ii=0; ii < json_object_array_length(jso); ii++)
+ {
+ struct json_object *val;
+ if (had_children)
+ {
+ sprintbuf(pb, ",");
+ if (flags & JSON_C_TO_STRING_PRETTY)
+ sprintbuf(pb, "\n");
+ }
+ had_children = 1;
+ if (flags & JSON_C_TO_STRING_SPACED)
+ sprintbuf(pb, " ");
+ indent(pb, level + 1, flags);
+ val = json_object_array_get_idx(jso, ii);
+ if(val == NULL)
+ sprintbuf(pb, "null");
+ else
+ val->_to_json_string(val, pb, level+1, flags);
+ }
+ if (flags & JSON_C_TO_STRING_PRETTY)
+ {
+ if (had_children)
+ sprintbuf(pb, "\n");
+ indent(pb,level,flags);
+ }
+
+ if (flags & JSON_C_TO_STRING_SPACED)
+ return sprintbuf(pb, " ]");
+ else
+ return sprintbuf(pb, "]");
+}
+
+static void json_object_array_entry_free(void *data)
+{
+ json_object_put((struct json_object*)data);
+}
+
+static void json_object_array_delete(struct json_object* jso)
+{
+ array_list_free(jso->o.c_array);
+ json_object_generic_delete(jso);
+}
+
+struct json_object* json_object_new_array(void)
+{
+ struct json_object *jso = json_object_new(json_type_array);
+ if (!jso)
+ return NULL;
+ jso->_delete = &json_object_array_delete;
+ jso->_to_json_string = &json_object_array_to_json_string;
+ jso->o.c_array = array_list_new(&json_object_array_entry_free);
+ return jso;
+}
+
+struct array_list* json_object_get_array(struct json_object *jso)
+{
+ if (!jso)
+ return NULL;
+ switch(jso->o_type)
+ {
+ case json_type_array:
+ return jso->o.c_array;
+ default:
+ return NULL;
+ }
+}
+
+void json_object_array_sort(struct json_object *jso, int(*sort_fn)(const void *, const void *))
+{
+ array_list_sort(jso->o.c_array, sort_fn);
+}
+
+int json_object_array_length(struct json_object *jso)
+{
+ return array_list_length(jso->o.c_array);
+}
+
+int json_object_array_add(struct json_object *jso,struct json_object *val)
+{
+ return array_list_add(jso->o.c_array, val);
+}
+
+int json_object_array_put_idx(struct json_object *jso, int idx,
+ struct json_object *val)
+{
+ return array_list_put_idx(jso->o.c_array, idx, val);
+}
+
+struct json_object* json_object_array_get_idx(struct json_object *jso,
+ int idx)
+{
+ return (struct json_object*)array_list_get_idx(jso->o.c_array, idx);
+}
+
diff --git a/json-c/json_object.h b/json-c/json_object.h
new file mode 100644
index 00000000..f5d463d8
--- /dev/null
+++ b/json-c/json_object.h
@@ -0,0 +1,617 @@
+/*
+ * $Id: json_object.h,v 1.12 2006/01/30 23:07:57 mclark Exp $
+ *
+ * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
+ * Michael Clark
+ * Copyright (c) 2009 Hewlett-Packard Development Company, L.P.
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See COPYING for details.
+ *
+ */
+
+#ifndef _json_object_h_
+#define _json_object_h_
+
+#ifdef __GNUC__
+#define THIS_FUNCTION_IS_DEPRECATED(func) func __attribute__ ((deprecated))
+#elif defined(_MSC_VER)
+#define THIS_FUNCTION_IS_DEPRECATED(func) __declspec(deprecated) func
+#else
+#define THIS_FUNCTION_IS_DEPRECATED(func) func
+#endif
+
+#include "json_inttypes.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define JSON_OBJECT_DEF_HASH_ENTRIES 16
+
+/**
+ * A flag for the json_object_to_json_string_ext() and
+ * json_object_to_file_ext() functions which causes the output
+ * to have no extra whitespace or formatting applied.
+ */
+#define JSON_C_TO_STRING_PLAIN 0
+/**
+ * A flag for the json_object_to_json_string_ext() and
+ * json_object_to_file_ext() functions which causes the output to have
+ * minimal whitespace inserted to make things slightly more readable.
+ */
+#define JSON_C_TO_STRING_SPACED (1<<0)
+/**
+ * A flag for the json_object_to_json_string_ext() and
+ * json_object_to_file_ext() functions which causes
+ * the output to be formatted.
+ *
+ * See the "Two Space Tab" option at http://jsonformatter.curiousconcept.com/
+ * for an example of the format.
+ */
+#define JSON_C_TO_STRING_PRETTY (1<<1)
+/**
+ * A flag to drop trailing zero for float values
+ */
+#define JSON_C_TO_STRING_NOZERO (1<<2)
+
+#undef FALSE
+#define FALSE ((json_bool)0)
+
+#undef TRUE
+#define TRUE ((json_bool)1)
+
+extern const char *json_number_chars;
+extern const char *json_hex_chars;
+
+/* CAW: added for ANSI C iteration correctness */
+struct json_object_iter
+{
+ char *key;
+ struct json_object *val;
+ struct lh_entry *entry;
+};
+
+/* forward structure definitions */
+
+typedef int json_bool;
+typedef struct printbuf printbuf;
+typedef struct lh_table lh_table;
+typedef struct array_list array_list;
+typedef struct json_object json_object;
+typedef struct json_object_iter json_object_iter;
+typedef struct json_tokener json_tokener;
+
+/**
+ * Type of custom user delete functions. See json_object_set_serializer.
+ */
+typedef void (json_object_delete_fn)(struct json_object *jso, void *userdata);
+
+/**
+ * Type of a custom serialization function. See json_object_set_serializer.
+ */
+typedef int (json_object_to_json_string_fn)(struct json_object *jso,
+ struct printbuf *pb,
+ int level,
+ int flags);
+
+/* supported object types */
+
+typedef enum json_type {
+ /* If you change this, be sure to update json_type_to_name() too */
+ json_type_null,
+ json_type_boolean,
+ json_type_double,
+ json_type_int,
+ json_type_object,
+ json_type_array,
+ json_type_string
+} json_type;
+
+/* reference counting functions */
+
+/**
+ * Increment the reference count of json_object, thereby grabbing shared
+ * ownership of obj.
+ *
+ * @param obj the json_object instance
+ */
+extern struct json_object* json_object_get(struct json_object *obj);
+
+/**
+ * Decrement the reference count of json_object and free if it reaches zero.
+ * You must have ownership of obj prior to doing this or you will cause an
+ * imbalance in the reference count.
+ *
+ * @param obj the json_object instance
+ * @return 1 if the object was freed.
+ */
+int json_object_put(struct json_object *obj);
+
+/**
+ * Check if the json_object is of a given type
+ * @param obj the json_object instance
+ * @param type one of:
+ json_type_null (i.e. obj == NULL),
+ json_type_boolean,
+ json_type_double,
+ json_type_int,
+ json_type_object,
+ json_type_array,
+ json_type_string
+ */
+extern int json_object_is_type(struct json_object *obj, enum json_type type);
+
+/**
+ * Get the type of the json_object. See also json_type_to_name() to turn this
+ * into a string suitable, for instance, for logging.
+ *
+ * @param obj the json_object instance
+ * @return type being one of:
+ json_type_null (i.e. obj == NULL),
+ json_type_boolean,
+ json_type_double,
+ json_type_int,
+ json_type_object,
+ json_type_array,
+ json_type_string
+ */
+extern enum json_type json_object_get_type(struct json_object *obj);
+
+
+/** Stringify object to json format.
+ * Equivalent to json_object_to_json_string_ext(obj, JSON_C_TO_STRING_SPACED)
+ * The pointer you get is an internal of your json object. You don't
+ * have to free it, later use of json_object_put() should be sufficient.
+ * If you can not ensure there's no concurrent access to *obj use
+ * strdup().
+ * @param obj the json_object instance
+ * @return a string in JSON format
+ */
+extern const char* json_object_to_json_string(struct json_object *obj);
+
+/** Stringify object to json format
+ * @see json_object_to_json_string() for details on how to free string.
+ * @param obj the json_object instance
+ * @param flags formatting options, see JSON_C_TO_STRING_PRETTY and other constants
+ * @return a string in JSON format
+ */
+extern const char* json_object_to_json_string_ext(struct json_object *obj, int
+flags);
+
+/**
+ * Set a custom serialization function to be used when this particular object
+ * is converted to a string by json_object_to_json_string.
+ *
+ * If a custom serializer is already set on this object, any existing
+ * user_delete function is called before the new one is set.
+ *
+ * If to_string_func is NULL, the other parameters are ignored
+ * and the default behaviour is reset.
+ *
+ * The userdata parameter is optional and may be passed as NULL. If provided,
+ * it is passed to to_string_func as-is. This parameter may be NULL even
+ * if user_delete is non-NULL.
+ *
+ * The user_delete parameter is optional and may be passed as NULL, even if
+ * the userdata parameter is non-NULL. It will be called just before the
+ * json_object is deleted, after it's reference count goes to zero
+ * (see json_object_put()).
+ * If this is not provided, it is up to the caller to free the userdata at
+ * an appropriate time. (i.e. after the json_object is deleted)
+ *
+ * @param jso the object to customize
+ * @param to_string_func the custom serialization function
+ * @param userdata an optional opaque cookie
+ * @param user_delete an optional function from freeing userdata
+ */
+extern void json_object_set_serializer(json_object *jso,
+ json_object_to_json_string_fn to_string_func,
+ void *userdata,
+ json_object_delete_fn *user_delete);
+
+/**
+ * Simply call free on the userdata pointer.
+ * Can be used with json_object_set_serializer().
+ *
+ * @param jso unused
+ * @param userdata the pointer that is passed to free().
+ */
+json_object_delete_fn json_object_free_userdata;
+
+/**
+ * Copy the jso->_userdata string over to pb as-is.
+ * Can be used with json_object_set_serializer().
+ *
+ * @param jso The object whose _userdata is used.
+ * @param pb The destination buffer.
+ * @param level Ignored.
+ * @param flags Ignored.
+ */
+json_object_to_json_string_fn json_object_userdata_to_json_string;
+
+
+/* object type methods */
+
+/** Create a new empty object with a reference count of 1. The caller of
+ * this object initially has sole ownership. Remember, when using
+ * json_object_object_add or json_object_array_put_idx, ownership will
+ * transfer to the object/array. Call json_object_get if you want to maintain
+ * shared ownership or also add this object as a child of multiple objects or
+ * arrays. Any ownerships you acquired but did not transfer must be released
+ * through json_object_put.
+ *
+ * @return a json_object of type json_type_object
+ */
+extern struct json_object* json_object_new_object(void);
+
+/** Get the hashtable of a json_object of type json_type_object
+ * @param obj the json_object instance
+ * @return a linkhash
+ */
+extern struct lh_table* json_object_get_object(struct json_object *obj);
+
+/** Get the size of an object in terms of the number of fields it has.
+ * @param obj the json_object whose length to return
+ */
+extern int json_object_object_length(struct json_object* obj);
+
+/** Add an object field to a json_object of type json_type_object
+ *
+ * The reference count will *not* be incremented. This is to make adding
+ * fields to objects in code more compact. If you want to retain a reference
+ * to an added object, independent of the lifetime of obj, you must wrap the
+ * passed object with json_object_get.
+ *
+ * Upon calling this, the ownership of val transfers to obj. Thus you must
+ * make sure that you do in fact have ownership over this object. For instance,
+ * json_object_new_object will give you ownership until you transfer it,
+ * whereas json_object_object_get does not.
+ *
+ * @param obj the json_object instance
+ * @param key the object field name (a private copy will be duplicated)
+ * @param val a json_object or NULL member to associate with the given field
+ */
+extern void json_object_object_add(struct json_object* obj, const char *key,
+ struct json_object *val);
+
+/** Get the json_object associate with a given object field
+ *
+ * *No* reference counts will be changed. There is no need to manually adjust
+ * reference counts through the json_object_put/json_object_get methods unless
+ * you need to have the child (value) reference maintain a different lifetime
+ * than the owning parent (obj). Ownership of the returned value is retained
+ * by obj (do not do json_object_put unless you have done a json_object_get).
+ * If you delete the value from obj (json_object_object_del) and wish to access
+ * the returned reference afterwards, make sure you have first gotten shared
+ * ownership through json_object_get (& don't forget to do a json_object_put
+ * or transfer ownership to prevent a memory leak).
+ *
+ * @param obj the json_object instance
+ * @param key the object field name
+ * @return the json_object associated with the given field name
+ * @deprecated Please use json_object_object_get_ex
+ */
+THIS_FUNCTION_IS_DEPRECATED(extern struct json_object* json_object_object_get(struct json_object* obj,
+ const char *key));
+
+/** Get the json_object associated with a given object field.
+ *
+ * This returns true if the key is found, false in all other cases (including
+ * if obj isn't a json_type_object).
+ *
+ * *No* reference counts will be changed. There is no need to manually adjust
+ * reference counts through the json_object_put/json_object_get methods unless
+ * you need to have the child (value) reference maintain a different lifetime
+ * than the owning parent (obj). Ownership of value is retained by obj.
+ *
+ * @param obj the json_object instance
+ * @param key the object field name
+ * @param value a pointer where to store a reference to the json_object
+ * associated with the given field name.
+ *
+ * It is safe to pass a NULL value.
+ * @return whether or not the key exists
+ */
+extern json_bool json_object_object_get_ex(struct json_object* obj,
+ const char *key,
+ struct json_object **value);
+
+/** Delete the given json_object field
+ *
+ * The reference count will be decremented for the deleted object. If there
+ * are no more owners of the value represented by this key, then the value is
+ * freed. Otherwise, the reference to the value will remain in memory.
+ *
+ * @param obj the json_object instance
+ * @param key the object field name
+ */
+extern void json_object_object_del(struct json_object* obj, const char *key);
+
+/**
+ * Iterate through all keys and values of an object.
+ *
+ * Adding keys to the object while iterating is NOT allowed.
+ *
+ * Deleting an existing key, or replacing an existing key with a
+ * new value IS allowed.
+ *
+ * @param obj the json_object instance
+ * @param key the local name for the char* key variable defined in the body
+ * @param val the local name for the json_object* object variable defined in
+ * the body
+ */
+#if defined(__GNUC__) && !defined(__STRICT_ANSI__) && __STDC_VERSION__ >= 199901L
+
+# define json_object_object_foreach(obj,key,val) \
+ char *key; \
+ struct json_object *val __attribute__((__unused__)); \
+ for(struct lh_entry *entry ## key = json_object_get_object(obj)->head, *entry_next ## key = NULL; \
+ ({ if(entry ## key) { \
+ key = (char*)entry ## key->k; \
+ val = (struct json_object*)entry ## key->v; \
+ entry_next ## key = entry ## key->next; \
+ } ; entry ## key; }); \
+ entry ## key = entry_next ## key )
+
+#else /* ANSI C or MSC */
+
+# define json_object_object_foreach(obj,key,val) \
+ char *key;\
+ struct json_object *val; \
+ struct lh_entry *entry ## key; \
+ struct lh_entry *entry_next ## key = NULL; \
+ for(entry ## key = json_object_get_object(obj)->head; \
+ (entry ## key ? ( \
+ key = (char*)entry ## key->k, \
+ val = (struct json_object*)entry ## key->v, \
+ entry_next ## key = entry ## key->next, \
+ entry ## key) : 0); \
+ entry ## key = entry_next ## key)
+
+#endif /* defined(__GNUC__) && !defined(__STRICT_ANSI__) && __STDC_VERSION__ >= 199901L */
+
+/** Iterate through all keys and values of an object (ANSI C Safe)
+ * @param obj the json_object instance
+ * @param iter the object iterator
+ */
+#define json_object_object_foreachC(obj,iter) \
+ for(iter.entry = json_object_get_object(obj)->head; (iter.entry ? (iter.key = (char*)iter.entry->k, iter.val = (struct json_object*)iter.entry->v, iter.entry) : 0); iter.entry = iter.entry->next)
+
+/* Array type methods */
+
+/** Create a new empty json_object of type json_type_array
+ * @return a json_object of type json_type_array
+ */
+extern struct json_object* json_object_new_array(void);
+
+/** Get the arraylist of a json_object of type json_type_array
+ * @param obj the json_object instance
+ * @return an arraylist
+ */
+extern struct array_list* json_object_get_array(struct json_object *obj);
+
+/** Get the length of a json_object of type json_type_array
+ * @param obj the json_object instance
+ * @return an int
+ */
+extern int json_object_array_length(struct json_object *obj);
+
+/** Sorts the elements of jso of type json_type_array
+*
+* Pointers to the json_object pointers will be passed as the two arguments
+* to @sort_fn
+*
+* @param obj the json_object instance
+* @param sort_fn a sorting function
+*/
+extern void json_object_array_sort(struct json_object *jso, int(*sort_fn)(const void *, const void *));
+
+/** Add an element to the end of a json_object of type json_type_array
+ *
+ * The reference count will *not* be incremented. This is to make adding
+ * fields to objects in code more compact. If you want to retain a reference
+ * to an added object you must wrap the passed object with json_object_get
+ *
+ * @param obj the json_object instance
+ * @param val the json_object to be added
+ */
+extern int json_object_array_add(struct json_object *obj,
+ struct json_object *val);
+
+/** Insert or replace an element at a specified index in an array (a json_object of type json_type_array)
+ *
+ * The reference count will *not* be incremented. This is to make adding
+ * fields to objects in code more compact. If you want to retain a reference
+ * to an added object you must wrap the passed object with json_object_get
+ *
+ * The reference count of a replaced object will be decremented.
+ *
+ * The array size will be automatically be expanded to the size of the
+ * index if the index is larger than the current size.
+ *
+ * @param obj the json_object instance
+ * @param idx the index to insert the element at
+ * @param val the json_object to be added
+ */
+extern int json_object_array_put_idx(struct json_object *obj, int idx,
+ struct json_object *val);
+
+/** Get the element at specificed index of the array (a json_object of type json_type_array)
+ * @param obj the json_object instance
+ * @param idx the index to get the element at
+ * @return the json_object at the specified index (or NULL)
+ */
+extern struct json_object* json_object_array_get_idx(struct json_object *obj,
+ int idx);
+
+/* json_bool type methods */
+
+/** Create a new empty json_object of type json_type_boolean
+ * @param b a json_bool TRUE or FALSE (0 or 1)
+ * @return a json_object of type json_type_boolean
+ */
+extern struct json_object* json_object_new_boolean(json_bool b);
+
+/** Get the json_bool value of a json_object
+ *
+ * The type is coerced to a json_bool if the passed object is not a json_bool.
+ * integer and double objects will return FALSE if there value is zero
+ * or TRUE otherwise. If the passed object is a string it will return
+ * TRUE if it has a non zero length. If any other object type is passed
+ * TRUE will be returned if the object is not NULL.
+ *
+ * @param obj the json_object instance
+ * @return a json_bool
+ */
+extern json_bool json_object_get_boolean(struct json_object *obj);
+
+
+/* int type methods */
+
+/** Create a new empty json_object of type json_type_int
+ * Note that values are stored as 64-bit values internally.
+ * To ensure the full range is maintained, use json_object_new_int64 instead.
+ * @param i the integer
+ * @return a json_object of type json_type_int
+ */
+extern struct json_object* json_object_new_int(int32_t i);
+
+
+/** Create a new empty json_object of type json_type_int
+ * @param i the integer
+ * @return a json_object of type json_type_int
+ */
+extern struct json_object* json_object_new_int64(int64_t i);
+
+
+/** Get the int value of a json_object
+ *
+ * The type is coerced to a int if the passed object is not a int.
+ * double objects will return their integer conversion. Strings will be
+ * parsed as an integer. If no conversion exists then 0 is returned
+ * and errno is set to EINVAL. null is equivalent to 0 (no error values set)
+ *
+ * Note that integers are stored internally as 64-bit values.
+ * If the value of too big or too small to fit into 32-bit, INT32_MAX or
+ * INT32_MIN are returned, respectively.
+ *
+ * @param obj the json_object instance
+ * @return an int
+ */
+extern int32_t json_object_get_int(struct json_object *obj);
+
+/** Get the int value of a json_object
+ *
+ * The type is coerced to a int64 if the passed object is not a int64.
+ * double objects will return their int64 conversion. Strings will be
+ * parsed as an int64. If no conversion exists then 0 is returned.
+ *
+ * NOTE: Set errno to 0 directly before a call to this function to determine
+ * whether or not conversion was successful (it does not clear the value for
+ * you).
+ *
+ * @param obj the json_object instance
+ * @return an int64
+ */
+extern int64_t json_object_get_int64(struct json_object *obj);
+
+
+/* double type methods */
+
+/** Create a new empty json_object of type json_type_double
+ * @param d the double
+ * @return a json_object of type json_type_double
+ */
+extern struct json_object* json_object_new_double(double d);
+
+/**
+ * Create a new json_object of type json_type_double, using
+ * the exact serialized representation of the value.
+ *
+ * This allows for numbers that would otherwise get displayed
+ * inefficiently (e.g. 12.3 => "12.300000000000001") to be
+ * serialized with the more convenient form.
+ *
+ * Note: this is used by json_tokener_parse_ex() to allow for
+ * an exact re-serialization of a parsed object.
+ *
+ * An equivalent sequence of calls is:
+ * @code
+ * jso = json_object_new_double(d);
+ * json_object_set_serializer(d, json_object_userdata_to_json_string,
+ * strdup(ds), json_object_free_userdata)
+ * @endcode
+ *
+ * @param d the numeric value of the double.
+ * @param ds the string representation of the double. This will be copied.
+ */
+extern struct json_object* json_object_new_double_s(double d, const char *ds);
+
+/** Get the double floating point value of a json_object
+ *
+ * The type is coerced to a double if the passed object is not a double.
+ * integer objects will return their double conversion. Strings will be
+ * parsed as a double. If no conversion exists then 0.0 is returned and
+ * errno is set to EINVAL. null is equivalent to 0 (no error values set)
+ *
+ * If the value is too big to fit in a double, then the value is set to
+ * the closest infinity with errno set to ERANGE. If strings cannot be
+ * converted to their double value, then EINVAL is set & NaN is returned.
+ *
+ * Arrays of length 0 are interpreted as 0 (with no error flags set).
+ * Arrays of length 1 are effectively cast to the equivalent object and
+ * converted using the above rules. All other arrays set the error to
+ * EINVAL & return NaN.
+ *
+ * NOTE: Set errno to 0 directly before a call to this function to
+ * determine whether or not conversion was successful (it does not clear
+ * the value for you).
+ *
+ * @param obj the json_object instance
+ * @return a double floating point number
+ */
+extern double json_object_get_double(struct json_object *obj);
+
+
+/* string type methods */
+
+/** Create a new empty json_object of type json_type_string
+ *
+ * A copy of the string is made and the memory is managed by the json_object
+ *
+ * @param s the string
+ * @return a json_object of type json_type_string
+ */
+extern struct json_object* json_object_new_string(const char *s);
+
+extern struct json_object* json_object_new_string_len(const char *s, int len);
+
+/** Get the string value of a json_object
+ *
+ * If the passed object is not of type json_type_string then the JSON
+ * representation of the object is returned.
+ *
+ * The returned string memory is managed by the json_object and will
+ * be freed when the reference count of the json_object drops to zero.
+ *
+ * @param obj the json_object instance
+ * @return a string
+ */
+extern const char* json_object_get_string(struct json_object *obj);
+
+/** Get the string length of a json_object
+ *
+ * If the passed object is not of type json_type_string then zero
+ * will be returned.
+ *
+ * @param obj the json_object instance
+ * @return int
+ */
+extern int json_object_get_string_len(struct json_object *obj);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/json-c/json_object_iterator.c b/json-c/json_object_iterator.c
new file mode 100644
index 00000000..7066649c
--- /dev/null
+++ b/json-c/json_object_iterator.c
@@ -0,0 +1,168 @@
+/**
+*******************************************************************************
+* @file json_object_iterator.c
+*
+* Copyright (c) 2009-2012 Hewlett-Packard Development Company, L.P.
+*
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the MIT license. See COPYING for details.
+*
+* @brief json-c forces clients to use its private data
+* structures for JSON Object iteration. This API
+* implementation corrects that by abstracting the
+* private json-c details.
+*
+*******************************************************************************
+*/
+
+#include
+
+#include "json.h"
+#include "json_object_private.h"
+
+#include "json_object_iterator.h"
+
+/**
+ * How It Works
+ *
+ * For each JSON Object, json-c maintains a linked list of zero
+ * or more lh_entry (link-hash entry) structures inside the
+ * Object's link-hash table (lh_table).
+ *
+ * Each lh_entry structure on the JSON Object's linked list
+ * represents a single name/value pair. The "next" field of the
+ * last lh_entry in the list is set to NULL, which terminates
+ * the list.
+ *
+ * We represent a valid iterator that refers to an actual
+ * name/value pair via a pointer to the pair's lh_entry
+ * structure set as the iterator's opaque_ field.
+ *
+ * We follow json-c's current pair list representation by
+ * representing a valid "end" iterator (one that refers past the
+ * last pair) with a NULL value in the iterator's opaque_ field.
+ *
+ * A JSON Object without any pairs in it will have the "head"
+ * field of its lh_table structure set to NULL. For such an
+ * object, json_object_iter_begin will return an iterator with
+ * the opaque_ field set to NULL, which is equivalent to the
+ * "end" iterator.
+ *
+ * When iterating, we simply update the iterator's opaque_ field
+ * to point to the next lh_entry structure in the linked list.
+ * opaque_ will become NULL once we iterate past the last pair
+ * in the list, which makes the iterator equivalent to the "end"
+ * iterator.
+ */
+
+/// Our current representation of the "end" iterator;
+///
+/// @note May not always be NULL
+static const void* kObjectEndIterValue = NULL;
+
+/**
+ * ****************************************************************************
+ */
+struct json_object_iterator
+json_object_iter_begin(struct json_object* obj)
+{
+ struct json_object_iterator iter;
+ struct lh_table* pTable;
+
+ /// @note json_object_get_object will return NULL if passed NULL
+ /// or a non-json_type_object instance
+ pTable = json_object_get_object(obj);
+ JASSERT(NULL != pTable);
+
+ /// @note For a pair-less Object, head is NULL, which matches our
+ /// definition of the "end" iterator
+ iter.opaque_ = pTable->head;
+ return iter;
+}
+
+/**
+ * ****************************************************************************
+ */
+struct json_object_iterator
+json_object_iter_end(const struct json_object* obj)
+{
+ struct json_object_iterator iter;
+
+ JASSERT(NULL != obj);
+ JASSERT(json_object_is_type(obj, json_type_object));
+
+ iter.opaque_ = kObjectEndIterValue;
+
+ return iter;
+}
+
+/**
+ * ****************************************************************************
+ */
+void
+json_object_iter_next(struct json_object_iterator* iter)
+{
+ JASSERT(NULL != iter);
+ JASSERT(kObjectEndIterValue != iter->opaque_);
+
+ iter->opaque_ = ((struct lh_entry *)iter->opaque_)->next;
+}
+
+
+/**
+ * ****************************************************************************
+ */
+const char*
+json_object_iter_peek_name(const struct json_object_iterator* iter)
+{
+ JASSERT(NULL != iter);
+ JASSERT(kObjectEndIterValue != iter->opaque_);
+
+ return (const char*)(((struct lh_entry *)iter->opaque_)->k);
+}
+
+
+/**
+ * ****************************************************************************
+ */
+struct json_object*
+json_object_iter_peek_value(const struct json_object_iterator* iter)
+{
+ JASSERT(NULL != iter);
+ JASSERT(kObjectEndIterValue != iter->opaque_);
+
+ return (struct json_object*)(((struct lh_entry *)iter->opaque_)->v);
+}
+
+
+/**
+ * ****************************************************************************
+ */
+json_bool
+json_object_iter_equal(const struct json_object_iterator* iter1,
+ const struct json_object_iterator* iter2)
+{
+ JASSERT(NULL != iter1);
+ JASSERT(NULL != iter2);
+
+ return (iter1->opaque_ == iter2->opaque_);
+}
+
+
+/**
+ * ****************************************************************************
+ */
+struct json_object_iterator
+json_object_iter_init_default(void)
+{
+ struct json_object_iterator iter;
+
+ /**
+ * @note Make this a negative, invalid value, such that
+ * accidental access to it would likely be trapped by the
+ * hardware as an invalid address.
+ */
+ iter.opaque_ = NULL;
+
+ return iter;
+}
diff --git a/json-c/json_object_iterator.h b/json-c/json_object_iterator.h
new file mode 100644
index 00000000..44c9fb25
--- /dev/null
+++ b/json-c/json_object_iterator.h
@@ -0,0 +1,239 @@
+/**
+*******************************************************************************
+* @file json_object_iterator.h
+*
+* Copyright (c) 2009-2012 Hewlett-Packard Development Company, L.P.
+*
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the MIT license. See COPYING for details.
+*
+* @brief json-c forces clients to use its private data
+* structures for JSON Object iteration. This API
+* corrects that by abstracting the private json-c
+* details.
+*
+* API attributes:
+* * Thread-safe: NO
+* * Reentrant: NO
+*
+*******************************************************************************
+*/
+
+
+#ifndef JSON_OBJECT_ITERATOR_H
+#define JSON_OBJECT_ITERATOR_H
+
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Forward declaration for the opaque iterator information.
+ */
+struct json_object_iter_info_;
+
+/**
+ * The opaque iterator that references a name/value pair within
+ * a JSON Object instance or the "end" iterator value.
+ */
+struct json_object_iterator {
+ const void* opaque_;
+};
+
+
+/**
+ * forward declaration of json-c's JSON value instance structure
+ */
+struct json_object;
+
+
+/**
+ * Initializes an iterator structure to a "default" value that
+ * is convenient for initializing an iterator variable to a
+ * default state (e.g., initialization list in a class'
+ * constructor).
+ *
+ * @code
+ * struct json_object_iterator iter = json_object_iter_init_default();
+ * MyClass() : iter_(json_object_iter_init_default())
+ * @endcode
+ *
+ * @note The initialized value doesn't reference any specific
+ * pair, is considered an invalid iterator, and MUST NOT
+ * be passed to any json-c API that expects a valid
+ * iterator.
+ *
+ * @note User and internal code MUST NOT make any assumptions
+ * about and dependencies on the value of the "default"
+ * iterator value.
+ *
+ * @return json_object_iterator
+ */
+struct json_object_iterator
+json_object_iter_init_default(void);
+
+/** Retrieves an iterator to the first pair of the JSON Object.
+ *
+ * @warning Any modification of the underlying pair invalidates all
+ * iterators to that pair.
+ *
+ * @param obj JSON Object instance (MUST be of type json_object)
+ *
+ * @return json_object_iterator If the JSON Object has at
+ * least one pair, on return, the iterator refers
+ * to the first pair. If the JSON Object doesn't
+ * have any pairs, the returned iterator is
+ * equivalent to the "end" iterator for the same
+ * JSON Object instance.
+ *
+ * @code
+ * struct json_object_iterator it;
+ * struct json_object_iterator itEnd;
+ * struct json_object* obj;
+ *
+ * obj = json_tokener_parse("{'first':'george', 'age':100}");
+ * it = json_object_iter_begin(obj);
+ * itEnd = json_object_iter_end(obj);
+ *
+ * while (!json_object_iter_equal(&it, &itEnd)) {
+ * printf("%s\n",
+ * json_object_iter_peek_name(&it));
+ * json_object_iter_next(&it);
+ * }
+ *
+ * @endcode
+ */
+struct json_object_iterator
+json_object_iter_begin(struct json_object* obj);
+
+/** Retrieves the iterator that represents the position beyond the
+ * last pair of the given JSON Object instance.
+ *
+ * @warning Do NOT write code that assumes that the "end"
+ * iterator value is NULL, even if it is so in a
+ * particular instance of the implementation.
+ *
+ * @note The reason we do not (and MUST NOT) provide
+ * "json_object_iter_is_end(json_object_iterator* iter)"
+ * type of API is because it would limit the underlying
+ * representation of name/value containment (or force us
+ * to add additional, otherwise unnecessary, fields to
+ * the iterator structure). The "end" iterator and the
+ * equality test method, on the other hand, permit us to
+ * cleanly abstract pretty much any reasonable underlying
+ * representation without burdening the iterator
+ * structure with unnecessary data.
+ *
+ * @note For performance reasons, memorize the "end" iterator prior
+ * to any loop.
+ *
+ * @param obj JSON Object instance (MUST be of type json_object)
+ *
+ * @return json_object_iterator On return, the iterator refers
+ * to the "end" of the Object instance's pairs
+ * (i.e., NOT the last pair, but "beyond the last
+ * pair" value)
+ */
+struct json_object_iterator
+json_object_iter_end(const struct json_object* obj);
+
+/** Returns an iterator to the next pair, if any
+ *
+ * @warning Any modification of the underlying pair
+ * invalidates all iterators to that pair.
+ *
+ * @param iter [IN/OUT] Pointer to iterator that references a
+ * name/value pair; MUST be a valid, non-end iterator.
+ * WARNING: bad things will happen if invalid or "end"
+ * iterator is passed. Upon return will contain the
+ * reference to the next pair if there is one; if there
+ * are no more pairs, will contain the "end" iterator
+ * value, which may be compared against the return value
+ * of json_object_iter_end() for the same JSON Object
+ * instance.
+ */
+void
+json_object_iter_next(struct json_object_iterator* iter);
+
+
+/** Returns a const pointer to the name of the pair referenced
+ * by the given iterator.
+ *
+ * @param iter pointer to iterator that references a name/value
+ * pair; MUST be a valid, non-end iterator.
+ *
+ * @warning bad things will happen if an invalid or
+ * "end" iterator is passed.
+ *
+ * @return const char* Pointer to the name of the referenced
+ * name/value pair. The name memory belongs to the
+ * name/value pair, will be freed when the pair is
+ * deleted or modified, and MUST NOT be modified or
+ * freed by the user.
+ */
+const char*
+json_object_iter_peek_name(const struct json_object_iterator* iter);
+
+
+/** Returns a pointer to the json-c instance representing the
+ * value of the referenced name/value pair, without altering
+ * the instance's reference count.
+ *
+ * @param iter pointer to iterator that references a name/value
+ * pair; MUST be a valid, non-end iterator.
+ *
+ * @warning bad things will happen if invalid or
+ * "end" iterator is passed.
+ *
+ * @return struct json_object* Pointer to the json-c value
+ * instance of the referenced name/value pair; the
+ * value's reference count is not changed by this
+ * function: if you plan to hold on to this json-c node,
+ * take a look at json_object_get() and
+ * json_object_put(). IMPORTANT: json-c API represents
+ * the JSON Null value as a NULL json_object instance
+ * pointer.
+ */
+struct json_object*
+json_object_iter_peek_value(const struct json_object_iterator* iter);
+
+
+/** Tests two iterators for equality. Typically used to test
+ * for end of iteration by comparing an iterator to the
+ * corresponding "end" iterator (that was derived from the same
+ * JSON Object instance).
+ *
+ * @note The reason we do not (and MUST NOT) provide
+ * "json_object_iter_is_end(json_object_iterator* iter)"
+ * type of API is because it would limit the underlying
+ * representation of name/value containment (or force us
+ * to add additional, otherwise unnecessary, fields to
+ * the iterator structure). The equality test method, on
+ * the other hand, permits us to cleanly abstract pretty
+ * much any reasonable underlying representation.
+ *
+ * @param iter1 Pointer to first valid, non-NULL iterator
+ * @param iter2 POinter to second valid, non-NULL iterator
+ *
+ * @warning if a NULL iterator pointer or an uninitialized
+ * or invalid iterator, or iterators derived from
+ * different JSON Object instances are passed, bad things
+ * will happen!
+ *
+ * @return json_bool non-zero if iterators are equal (i.e., both
+ * reference the same name/value pair or are both at
+ * "end"); zero if they are not equal.
+ */
+json_bool
+json_object_iter_equal(const struct json_object_iterator* iter1,
+ const struct json_object_iterator* iter2);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* JSON_OBJECT_ITERATOR_H */
diff --git a/json-c/json_object_private.h b/json-c/json_object_private.h
new file mode 100644
index 00000000..5ed791b5
--- /dev/null
+++ b/json-c/json_object_private.h
@@ -0,0 +1,47 @@
+/*
+ * $Id: json_object_private.h,v 1.4 2006/01/26 02:16:28 mclark Exp $
+ *
+ * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
+ * Michael Clark
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See COPYING for details.
+ *
+ */
+
+#ifndef _json_object_private_h_
+#define _json_object_private_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void (json_object_private_delete_fn)(struct json_object *o);
+
+struct json_object
+{
+ enum json_type o_type;
+ json_object_private_delete_fn *_delete;
+ json_object_to_json_string_fn *_to_json_string;
+ int _ref_count;
+ struct printbuf *_pb;
+ union data {
+ json_bool c_boolean;
+ double c_double;
+ int64_t c_int64;
+ struct lh_table *c_object;
+ struct array_list *c_array;
+ struct {
+ char *str;
+ int len;
+ } c_string;
+ } o;
+ json_object_delete_fn *_user_delete;
+ void *_userdata;
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/json-c/json_tokener.c b/json-c/json_tokener.c
new file mode 100644
index 00000000..60e81f27
--- /dev/null
+++ b/json-c/json_tokener.c
@@ -0,0 +1,887 @@
+/*
+ * $Id: json_tokener.c,v 1.20 2006/07/25 03:24:50 mclark Exp $
+ *
+ * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
+ * Michael Clark
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See COPYING for details.
+ *
+ *
+ * Copyright (c) 2008-2009 Yahoo! Inc. All rights reserved.
+ * The copyrights to the contents of this file are licensed under the MIT License
+ * (http://www.opensource.org/licenses/mit-license.php)
+ */
+
+#include "config.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "debug.h"
+#include "printbuf.h"
+#include "arraylist.h"
+#include "json_inttypes.h"
+#include "json_object.h"
+#include "json_tokener.h"
+#include "json_util.h"
+
+#ifdef HAVE_LOCALE_H
+#include
+#endif /* HAVE_LOCALE_H */
+
+#define jt_hexdigit(x) (((x) <= '9') ? (x) - '0' : ((x) & 7) + 9)
+
+#if !HAVE_STRDUP && defined(_MSC_VER)
+ /* MSC has the version as _strdup */
+# define strdup _strdup
+#elif !HAVE_STRDUP
+# error You do not have strdup on your system.
+#endif /* HAVE_STRDUP */
+
+#if !HAVE_STRNCASECMP && defined(_MSC_VER)
+ /* MSC has the version as _strnicmp */
+# define strncasecmp _strnicmp
+#elif !HAVE_STRNCASECMP
+# error You do not have strncasecmp on your system.
+#endif /* HAVE_STRNCASECMP */
+
+/* Use C99 NAN by default; if not available, nan("") should work too. */
+#ifndef NAN
+#define NAN nan("")
+#endif /* !NAN */
+
+static const char json_null_str[] = "null";
+static const int json_null_str_len = sizeof(json_null_str) - 1;
+static const char json_inf_str[] = "Infinity";
+static const int json_inf_str_len = sizeof(json_inf_str) - 1;
+static const char json_nan_str[] = "NaN";
+static const int json_nan_str_len = sizeof(json_nan_str) - 1;
+static const char json_true_str[] = "true";
+static const int json_true_str_len = sizeof(json_true_str) - 1;
+static const char json_false_str[] = "false";
+static const int json_false_str_len = sizeof(json_false_str) - 1;
+
+static const char* json_tokener_errors[] = {
+ "success",
+ "continue",
+ "nesting too deep",
+ "unexpected end of data",
+ "unexpected character",
+ "null expected",
+ "boolean expected",
+ "number expected",
+ "array value separator ',' expected",
+ "quoted object property name expected",
+ "object property name separator ':' expected",
+ "object value separator ',' expected",
+ "invalid string sequence",
+ "expected comment",
+ "buffer size overflow"
+};
+
+const char *json_tokener_error_desc(enum json_tokener_error jerr)
+{
+ int jerr_int = (int)jerr;
+ if (jerr_int < 0 || jerr_int >= (int)(sizeof(json_tokener_errors) / sizeof(json_tokener_errors[0])))
+ return "Unknown error, invalid json_tokener_error value passed to json_tokener_error_desc()";
+ return json_tokener_errors[jerr];
+}
+
+enum json_tokener_error json_tokener_get_error(json_tokener *tok)
+{
+ return tok->err;
+}
+
+/* Stuff for decoding unicode sequences */
+#define IS_HIGH_SURROGATE(uc) (((uc) & 0xFC00) == 0xD800)
+#define IS_LOW_SURROGATE(uc) (((uc) & 0xFC00) == 0xDC00)
+#define DECODE_SURROGATE_PAIR(hi,lo) ((((hi) & 0x3FF) << 10) + ((lo) & 0x3FF) + 0x10000)
+static unsigned char utf8_replacement_char[3] = { 0xEF, 0xBF, 0xBD };
+
+struct json_tokener* json_tokener_new_ex(int depth)
+{
+ struct json_tokener *tok;
+
+ tok = (struct json_tokener*)calloc(1, sizeof(struct json_tokener));
+ if (!tok) return NULL;
+ tok->stack = (struct json_tokener_srec *)calloc(depth, sizeof(struct json_tokener_srec));
+ if (!tok->stack) {
+ free(tok);
+ return NULL;
+ }
+ tok->pb = printbuf_new();
+ tok->max_depth = depth;
+ json_tokener_reset(tok);
+ return tok;
+}
+
+struct json_tokener* json_tokener_new(void)
+{
+ return json_tokener_new_ex(JSON_TOKENER_DEFAULT_DEPTH);
+}
+
+void json_tokener_free(struct json_tokener *tok)
+{
+ json_tokener_reset(tok);
+ if (tok->pb) printbuf_free(tok->pb);
+ if (tok->stack) free(tok->stack);
+ free(tok);
+}
+
+static void json_tokener_reset_level(struct json_tokener *tok, int depth)
+{
+ tok->stack[depth].state = json_tokener_state_eatws;
+ tok->stack[depth].saved_state = json_tokener_state_start;
+ json_object_put(tok->stack[depth].current);
+ tok->stack[depth].current = NULL;
+ free(tok->stack[depth].obj_field_name);
+ tok->stack[depth].obj_field_name = NULL;
+}
+
+void json_tokener_reset(struct json_tokener *tok)
+{
+ int i;
+ if (!tok)
+ return;
+
+ for(i = tok->depth; i >= 0; i--)
+ json_tokener_reset_level(tok, i);
+ tok->depth = 0;
+ tok->err = json_tokener_success;
+}
+
+struct json_object* json_tokener_parse(const char *str)
+{
+ enum json_tokener_error jerr_ignored;
+ struct json_object* obj;
+ obj = json_tokener_parse_verbose(str, &jerr_ignored);
+ return obj;
+}
+
+struct json_object* json_tokener_parse_verbose(const char *str, enum json_tokener_error *error)
+{
+ struct json_tokener* tok;
+ struct json_object* obj;
+
+ tok = json_tokener_new();
+ if (!tok)
+ return NULL;
+ obj = json_tokener_parse_ex(tok, str, -1);
+ *error = tok->err;
+ if(tok->err != json_tokener_success) {
+ if (obj != NULL)
+ json_object_put(obj);
+ obj = NULL;
+ }
+
+ json_tokener_free(tok);
+ return obj;
+}
+
+#define state tok->stack[tok->depth].state
+#define saved_state tok->stack[tok->depth].saved_state
+#define current tok->stack[tok->depth].current
+#define obj_field_name tok->stack[tok->depth].obj_field_name
+
+/* Optimization:
+ * json_tokener_parse_ex() consumed a lot of CPU in its main loop,
+ * iterating character-by character. A large performance boost is
+ * achieved by using tighter loops to locally handle units such as
+ * comments and strings. Loops that handle an entire token within
+ * their scope also gather entire strings and pass them to
+ * printbuf_memappend() in a single call, rather than calling
+ * printbuf_memappend() one char at a time.
+ *
+ * PEEK_CHAR() and ADVANCE_CHAR() macros are used for code that is
+ * common to both the main loop and the tighter loops.
+ */
+
+/* PEEK_CHAR(dest, tok) macro:
+ * Peeks at the current char and stores it in dest.
+ * Returns 1 on success, sets tok->err and returns 0 if no more chars.
+ * Implicit inputs: str, len vars
+ */
+#define PEEK_CHAR(dest, tok) \
+ (((tok)->char_offset == len) ? \
+ (((tok)->depth == 0 && state == json_tokener_state_eatws && saved_state == json_tokener_state_finish) ? \
+ (((tok)->err = json_tokener_success), 0) \
+ : \
+ (((tok)->err = json_tokener_continue), 0) \
+ ) : \
+ (((dest) = *str), 1) \
+ )
+
+/* ADVANCE_CHAR() macro:
+ * Incrementes str & tok->char_offset.
+ * For convenience of existing conditionals, returns the old value of c (0 on eof)
+ * Implicit inputs: c var
+ */
+#define ADVANCE_CHAR(str, tok) \
+ ( ++(str), ((tok)->char_offset)++, c)
+
+
+/* End optimization macro defs */
+
+
+struct json_object* json_tokener_parse_ex(struct json_tokener *tok,
+ const char *str, int len)
+{
+ struct json_object *obj = NULL;
+ char c = '\1';
+#ifdef HAVE_SETLOCALE
+ char *oldlocale=NULL, *tmplocale;
+
+ tmplocale = setlocale(LC_NUMERIC, NULL);
+ if (tmplocale) oldlocale = strdup(tmplocale);
+ setlocale(LC_NUMERIC, "C");
+#endif
+
+ tok->char_offset = 0;
+ tok->err = json_tokener_success;
+
+ /* this interface is presently not 64-bit clean due to the int len argument
+ and the internal printbuf interface that takes 32-bit int len arguments
+ so the function limits the maximum string size to INT32_MAX (2GB).
+ If the function is called with len == -1 then strlen is called to check
+ the string length is less than INT32_MAX (2GB) */
+ if ((len < -1) || (len == -1 && strlen(str) > INT32_MAX)) {
+ tok->err = json_tokener_error_size;
+ return NULL;
+ }
+
+ while (PEEK_CHAR(c, tok)) {
+
+ redo_char:
+ switch(state) {
+
+ case json_tokener_state_eatws:
+ /* Advance until we change state */
+ while (isspace((int)c)) {
+ if ((!ADVANCE_CHAR(str, tok)) || (!PEEK_CHAR(c, tok)))
+ goto out;
+ }
+ if(c == '/' && !(tok->flags & JSON_TOKENER_STRICT)) {
+ printbuf_reset(tok->pb);
+ printbuf_memappend_fast(tok->pb, &c, 1);
+ state = json_tokener_state_comment_start;
+ } else {
+ state = saved_state;
+ goto redo_char;
+ }
+ break;
+
+ case json_tokener_state_start:
+ switch(c) {
+ case '{':
+ state = json_tokener_state_eatws;
+ saved_state = json_tokener_state_object_field_start;
+ current = json_object_new_object();
+ break;
+ case '[':
+ state = json_tokener_state_eatws;
+ saved_state = json_tokener_state_array;
+ current = json_object_new_array();
+ break;
+ case 'I':
+ case 'i':
+ state = json_tokener_state_inf;
+ printbuf_reset(tok->pb);
+ tok->st_pos = 0;
+ goto redo_char;
+ case 'N':
+ case 'n':
+ state = json_tokener_state_null; // or NaN
+ printbuf_reset(tok->pb);
+ tok->st_pos = 0;
+ goto redo_char;
+ case '\'':
+ if (tok->flags & JSON_TOKENER_STRICT) {
+ /* in STRICT mode only double-quote are allowed */
+ tok->err = json_tokener_error_parse_unexpected;
+ goto out;
+ }
+ case '"':
+ state = json_tokener_state_string;
+ printbuf_reset(tok->pb);
+ tok->quote_char = c;
+ break;
+ case 'T':
+ case 't':
+ case 'F':
+ case 'f':
+ state = json_tokener_state_boolean;
+ printbuf_reset(tok->pb);
+ tok->st_pos = 0;
+ goto redo_char;
+#if defined(__GNUC__)
+ case '0' ... '9':
+#else
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+#endif
+ case '-':
+ state = json_tokener_state_number;
+ printbuf_reset(tok->pb);
+ tok->is_double = 0;
+ goto redo_char;
+ default:
+ tok->err = json_tokener_error_parse_unexpected;
+ goto out;
+ }
+ break;
+
+ case json_tokener_state_finish:
+ if(tok->depth == 0) goto out;
+ obj = json_object_get(current);
+ json_tokener_reset_level(tok, tok->depth);
+ tok->depth--;
+ goto redo_char;
+
+ case json_tokener_state_inf: /* aka starts with 'i' */
+ {
+ int size_inf;
+ int is_negative = 0;
+
+ printbuf_memappend_fast(tok->pb, &c, 1);
+ size_inf = json_min(tok->st_pos+1, json_inf_str_len);
+ char *infbuf = tok->pb->buf;
+ if (*infbuf == '-')
+ {
+ infbuf++;
+ is_negative = 1;
+ }
+ if ((!(tok->flags & JSON_TOKENER_STRICT) &&
+ strncasecmp(json_inf_str, infbuf, size_inf) == 0) ||
+ (strncmp(json_inf_str, infbuf, size_inf) == 0)
+ )
+ {
+ if (tok->st_pos == json_inf_str_len)
+ {
+ current = json_object_new_double(is_negative ? -INFINITY : INFINITY);
+ saved_state = json_tokener_state_finish;
+ state = json_tokener_state_eatws;
+ goto redo_char;
+ }
+ } else {
+ tok->err = json_tokener_error_parse_unexpected;
+ goto out;
+ }
+ tok->st_pos++;
+ }
+ break;
+ case json_tokener_state_null: /* aka starts with 'n' */
+ {
+ int size;
+ int size_nan;
+ printbuf_memappend_fast(tok->pb, &c, 1);
+ size = json_min(tok->st_pos+1, json_null_str_len);
+ size_nan = json_min(tok->st_pos+1, json_nan_str_len);
+ if((!(tok->flags & JSON_TOKENER_STRICT) &&
+ strncasecmp(json_null_str, tok->pb->buf, size) == 0)
+ || (strncmp(json_null_str, tok->pb->buf, size) == 0)
+ ) {
+ if (tok->st_pos == json_null_str_len) {
+ current = NULL;
+ saved_state = json_tokener_state_finish;
+ state = json_tokener_state_eatws;
+ goto redo_char;
+ }
+ }
+ else if ((!(tok->flags & JSON_TOKENER_STRICT) &&
+ strncasecmp(json_nan_str, tok->pb->buf, size_nan) == 0) ||
+ (strncmp(json_nan_str, tok->pb->buf, size_nan) == 0)
+ )
+ {
+ if (tok->st_pos == json_nan_str_len)
+ {
+ current = json_object_new_double(NAN);
+ saved_state = json_tokener_state_finish;
+ state = json_tokener_state_eatws;
+ goto redo_char;
+ }
+ } else {
+ tok->err = json_tokener_error_parse_null;
+ goto out;
+ }
+ tok->st_pos++;
+ }
+ break;
+
+ case json_tokener_state_comment_start:
+ if(c == '*') {
+ state = json_tokener_state_comment;
+ } else if(c == '/') {
+ state = json_tokener_state_comment_eol;
+ } else {
+ tok->err = json_tokener_error_parse_comment;
+ goto out;
+ }
+ printbuf_memappend_fast(tok->pb, &c, 1);
+ break;
+
+ case json_tokener_state_comment:
+ {
+ /* Advance until we change state */
+ const char *case_start = str;
+ while(c != '*') {
+ if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) {
+ printbuf_memappend_fast(tok->pb, case_start, str-case_start);
+ goto out;
+ }
+ }
+ printbuf_memappend_fast(tok->pb, case_start, 1+str-case_start);
+ state = json_tokener_state_comment_end;
+ }
+ break;
+
+ case json_tokener_state_comment_eol:
+ {
+ /* Advance until we change state */
+ const char *case_start = str;
+ while(c != '\n') {
+ if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) {
+ printbuf_memappend_fast(tok->pb, case_start, str-case_start);
+ goto out;
+ }
+ }
+ printbuf_memappend_fast(tok->pb, case_start, str-case_start);
+ MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf);
+ state = json_tokener_state_eatws;
+ }
+ break;
+
+ case json_tokener_state_comment_end:
+ printbuf_memappend_fast(tok->pb, &c, 1);
+ if(c == '/') {
+ MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf);
+ state = json_tokener_state_eatws;
+ } else {
+ state = json_tokener_state_comment;
+ }
+ break;
+
+ case json_tokener_state_string:
+ {
+ /* Advance until we change state */
+ const char *case_start = str;
+ while(1) {
+ if(c == tok->quote_char) {
+ printbuf_memappend_fast(tok->pb, case_start, str-case_start);
+ current = json_object_new_string_len(tok->pb->buf, tok->pb->bpos);
+ saved_state = json_tokener_state_finish;
+ state = json_tokener_state_eatws;
+ break;
+ } else if(c == '\\') {
+ printbuf_memappend_fast(tok->pb, case_start, str-case_start);
+ saved_state = json_tokener_state_string;
+ state = json_tokener_state_string_escape;
+ break;
+ }
+ if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) {
+ printbuf_memappend_fast(tok->pb, case_start, str-case_start);
+ goto out;
+ }
+ }
+ }
+ break;
+
+ case json_tokener_state_string_escape:
+ switch(c) {
+ case '"':
+ case '\\':
+ case '/':
+ printbuf_memappend_fast(tok->pb, &c, 1);
+ state = saved_state;
+ break;
+ case 'b':
+ case 'n':
+ case 'r':
+ case 't':
+ case 'f':
+ if(c == 'b') printbuf_memappend_fast(tok->pb, "\b", 1);
+ else if(c == 'n') printbuf_memappend_fast(tok->pb, "\n", 1);
+ else if(c == 'r') printbuf_memappend_fast(tok->pb, "\r", 1);
+ else if(c == 't') printbuf_memappend_fast(tok->pb, "\t", 1);
+ else if(c == 'f') printbuf_memappend_fast(tok->pb, "\f", 1);
+ state = saved_state;
+ break;
+ case 'u':
+ tok->ucs_char = 0;
+ tok->st_pos = 0;
+ state = json_tokener_state_escape_unicode;
+ break;
+ default:
+ tok->err = json_tokener_error_parse_string;
+ goto out;
+ }
+ break;
+
+ case json_tokener_state_escape_unicode:
+ {
+ unsigned int got_hi_surrogate = 0;
+
+ /* Handle a 4-byte sequence, or two sequences if a surrogate pair */
+ while(1) {
+ if(strchr(json_hex_chars, c)) {
+ tok->ucs_char += ((unsigned int)jt_hexdigit(c) << ((3-tok->st_pos++)*4));
+ if(tok->st_pos == 4) {
+ unsigned char unescaped_utf[4];
+
+ if (got_hi_surrogate) {
+ if (IS_LOW_SURROGATE(tok->ucs_char)) {
+ /* Recalculate the ucs_char, then fall thru to process normally */
+ tok->ucs_char = DECODE_SURROGATE_PAIR(got_hi_surrogate, tok->ucs_char);
+ } else {
+ /* Hi surrogate was not followed by a low surrogate */
+ /* Replace the hi and process the rest normally */
+ printbuf_memappend_fast(tok->pb, (char*)utf8_replacement_char, 3);
+ }
+ got_hi_surrogate = 0;
+ }
+
+ if (tok->ucs_char < 0x80) {
+ unescaped_utf[0] = tok->ucs_char;
+ printbuf_memappend_fast(tok->pb, (char*)unescaped_utf, 1);
+ } else if (tok->ucs_char < 0x800) {
+ unescaped_utf[0] = 0xc0 | (tok->ucs_char >> 6);
+ unescaped_utf[1] = 0x80 | (tok->ucs_char & 0x3f);
+ printbuf_memappend_fast(tok->pb, (char*)unescaped_utf, 2);
+ } else if (IS_HIGH_SURROGATE(tok->ucs_char)) {
+ /* Got a high surrogate. Remember it and look for the
+ * the beginning of another sequence, which should be the
+ * low surrogate.
+ */
+ got_hi_surrogate = tok->ucs_char;
+ /* Not at end, and the next two chars should be "\u" */
+ if ((tok->char_offset+1 != len) &&
+ (tok->char_offset+2 != len) &&
+ (str[1] == '\\') &&
+ (str[2] == 'u'))
+ {
+ /* Advance through the 16 bit surrogate, and move on to the
+ * next sequence. The next step is to process the following
+ * characters.
+ */
+ if( !ADVANCE_CHAR(str, tok) || !ADVANCE_CHAR(str, tok) ) {
+ printbuf_memappend_fast(tok->pb, (char*)utf8_replacement_char, 3);
+ }
+ /* Advance to the first char of the next sequence and
+ * continue processing with the next sequence.
+ */
+ if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) {
+ printbuf_memappend_fast(tok->pb, (char*)utf8_replacement_char, 3);
+ goto out;
+ }
+ tok->ucs_char = 0;
+ tok->st_pos = 0;
+ continue; /* other json_tokener_state_escape_unicode */
+ } else {
+ /* Got a high surrogate without another sequence following
+ * it. Put a replacement char in for the hi surrogate
+ * and pretend we finished.
+ */
+ printbuf_memappend_fast(tok->pb, (char*)utf8_replacement_char, 3);
+ }
+ } else if (IS_LOW_SURROGATE(tok->ucs_char)) {
+ /* Got a low surrogate not preceded by a high */
+ printbuf_memappend_fast(tok->pb, (char*)utf8_replacement_char, 3);
+ } else if (tok->ucs_char < 0x10000) {
+ unescaped_utf[0] = 0xe0 | (tok->ucs_char >> 12);
+ unescaped_utf[1] = 0x80 | ((tok->ucs_char >> 6) & 0x3f);
+ unescaped_utf[2] = 0x80 | (tok->ucs_char & 0x3f);
+ printbuf_memappend_fast(tok->pb, (char*)unescaped_utf, 3);
+ } else if (tok->ucs_char < 0x110000) {
+ unescaped_utf[0] = 0xf0 | ((tok->ucs_char >> 18) & 0x07);
+ unescaped_utf[1] = 0x80 | ((tok->ucs_char >> 12) & 0x3f);
+ unescaped_utf[2] = 0x80 | ((tok->ucs_char >> 6) & 0x3f);
+ unescaped_utf[3] = 0x80 | (tok->ucs_char & 0x3f);
+ printbuf_memappend_fast(tok->pb, (char*)unescaped_utf, 4);
+ } else {
+ /* Don't know what we got--insert the replacement char */
+ printbuf_memappend_fast(tok->pb, (char*)utf8_replacement_char, 3);
+ }
+ state = saved_state;
+ break;
+ }
+ } else {
+ tok->err = json_tokener_error_parse_string;
+ goto out;
+ }
+ if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) {
+ if (got_hi_surrogate) /* Clean up any pending chars */
+ printbuf_memappend_fast(tok->pb, (char*)utf8_replacement_char, 3);
+ goto out;
+ }
+ }
+ }
+ break;
+
+ case json_tokener_state_boolean:
+ {
+ int size1, size2;
+ printbuf_memappend_fast(tok->pb, &c, 1);
+ size1 = json_min(tok->st_pos+1, json_true_str_len);
+ size2 = json_min(tok->st_pos+1, json_false_str_len);
+ if((!(tok->flags & JSON_TOKENER_STRICT) &&
+ strncasecmp(json_true_str, tok->pb->buf, size1) == 0)
+ || (strncmp(json_true_str, tok->pb->buf, size1) == 0)
+ ) {
+ if(tok->st_pos == json_true_str_len) {
+ current = json_object_new_boolean(1);
+ saved_state = json_tokener_state_finish;
+ state = json_tokener_state_eatws;
+ goto redo_char;
+ }
+ } else if((!(tok->flags & JSON_TOKENER_STRICT) &&
+ strncasecmp(json_false_str, tok->pb->buf, size2) == 0)
+ || (strncmp(json_false_str, tok->pb->buf, size2) == 0)) {
+ if(tok->st_pos == json_false_str_len) {
+ current = json_object_new_boolean(0);
+ saved_state = json_tokener_state_finish;
+ state = json_tokener_state_eatws;
+ goto redo_char;
+ }
+ } else {
+ tok->err = json_tokener_error_parse_boolean;
+ goto out;
+ }
+ tok->st_pos++;
+ }
+ break;
+
+ case json_tokener_state_number:
+ {
+ /* Advance until we change state */
+ const char *case_start = str;
+ int case_len=0;
+ while(c && strchr(json_number_chars, c)) {
+ ++case_len;
+ if(c == '.' || c == 'e' || c == 'E')
+ tok->is_double = 1;
+ if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) {
+ printbuf_memappend_fast(tok->pb, case_start, case_len);
+ goto out;
+ }
+ }
+ if (case_len>0)
+ printbuf_memappend_fast(tok->pb, case_start, case_len);
+
+ // Check for -Infinity
+ if (tok->pb->buf[0] == '-' && case_len == 1 &&
+ (c == 'i' || c == 'I'))
+ {
+ state = json_tokener_state_inf;
+ goto redo_char;
+ }
+ }
+ {
+ int64_t num64;
+ double numd;
+ if (!tok->is_double && json_parse_int64(tok->pb->buf, &num64) == 0) {
+ if (num64 && tok->pb->buf[0]=='0' && (tok->flags & JSON_TOKENER_STRICT)) {
+ /* in strict mode, number must not start with 0 */
+ tok->err = json_tokener_error_parse_number;
+ goto out;
+ }
+ current = json_object_new_int64(num64);
+ }
+ else if(tok->is_double && json_parse_double(tok->pb->buf, &numd) == 0)
+ {
+ current = json_object_new_double_s(numd, tok->pb->buf);
+ } else {
+ tok->err = json_tokener_error_parse_number;
+ goto out;
+ }
+ saved_state = json_tokener_state_finish;
+ state = json_tokener_state_eatws;
+ goto redo_char;
+ }
+ break;
+
+ case json_tokener_state_array_after_sep:
+ case json_tokener_state_array:
+ if(c == ']') {
+ if (state == json_tokener_state_array_after_sep &&
+ (tok->flags & JSON_TOKENER_STRICT))
+ {
+ tok->err = json_tokener_error_parse_unexpected;
+ goto out;
+ }
+ saved_state = json_tokener_state_finish;
+ state = json_tokener_state_eatws;
+ } else {
+ if(tok->depth >= tok->max_depth-1) {
+ tok->err = json_tokener_error_depth;
+ goto out;
+ }
+ state = json_tokener_state_array_add;
+ tok->depth++;
+ json_tokener_reset_level(tok, tok->depth);
+ goto redo_char;
+ }
+ break;
+
+ case json_tokener_state_array_add:
+ json_object_array_add(current, obj);
+ saved_state = json_tokener_state_array_sep;
+ state = json_tokener_state_eatws;
+ goto redo_char;
+
+ case json_tokener_state_array_sep:
+ if(c == ']') {
+ saved_state = json_tokener_state_finish;
+ state = json_tokener_state_eatws;
+ } else if(c == ',') {
+ saved_state = json_tokener_state_array_after_sep;
+ state = json_tokener_state_eatws;
+ } else {
+ tok->err = json_tokener_error_parse_array;
+ goto out;
+ }
+ break;
+
+ case json_tokener_state_object_field_start:
+ case json_tokener_state_object_field_start_after_sep:
+ if(c == '}') {
+ if (state == json_tokener_state_object_field_start_after_sep &&
+ (tok->flags & JSON_TOKENER_STRICT))
+ {
+ tok->err = json_tokener_error_parse_unexpected;
+ goto out;
+ }
+ saved_state = json_tokener_state_finish;
+ state = json_tokener_state_eatws;
+ } else if (c == '"' || c == '\'') {
+ tok->quote_char = c;
+ printbuf_reset(tok->pb);
+ state = json_tokener_state_object_field;
+ } else {
+ tok->err = json_tokener_error_parse_object_key_name;
+ goto out;
+ }
+ break;
+
+ case json_tokener_state_object_field:
+ {
+ /* Advance until we change state */
+ const char *case_start = str;
+ while(1) {
+ if(c == tok->quote_char) {
+ printbuf_memappend_fast(tok->pb, case_start, str-case_start);
+ obj_field_name = strdup(tok->pb->buf);
+ saved_state = json_tokener_state_object_field_end;
+ state = json_tokener_state_eatws;
+ break;
+ } else if(c == '\\') {
+ printbuf_memappend_fast(tok->pb, case_start, str-case_start);
+ saved_state = json_tokener_state_object_field;
+ state = json_tokener_state_string_escape;
+ break;
+ }
+ if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) {
+ printbuf_memappend_fast(tok->pb, case_start, str-case_start);
+ goto out;
+ }
+ }
+ }
+ break;
+
+ case json_tokener_state_object_field_end:
+ if(c == ':') {
+ saved_state = json_tokener_state_object_value;
+ state = json_tokener_state_eatws;
+ } else {
+ tok->err = json_tokener_error_parse_object_key_sep;
+ goto out;
+ }
+ break;
+
+ case json_tokener_state_object_value:
+ if(tok->depth >= tok->max_depth-1) {
+ tok->err = json_tokener_error_depth;
+ goto out;
+ }
+ state = json_tokener_state_object_value_add;
+ tok->depth++;
+ json_tokener_reset_level(tok, tok->depth);
+ goto redo_char;
+
+ case json_tokener_state_object_value_add:
+ json_object_object_add(current, obj_field_name, obj);
+ free(obj_field_name);
+ obj_field_name = NULL;
+ saved_state = json_tokener_state_object_sep;
+ state = json_tokener_state_eatws;
+ goto redo_char;
+
+ case json_tokener_state_object_sep:
+ if(c == '}') {
+ saved_state = json_tokener_state_finish;
+ state = json_tokener_state_eatws;
+ } else if(c == ',') {
+ saved_state = json_tokener_state_object_field_start_after_sep;
+ state = json_tokener_state_eatws;
+ } else {
+ tok->err = json_tokener_error_parse_object_value_sep;
+ goto out;
+ }
+ break;
+
+ }
+ if (!ADVANCE_CHAR(str, tok))
+ goto out;
+ } /* while(POP_CHAR) */
+
+ out:
+ if (c &&
+ (state == json_tokener_state_finish) &&
+ (tok->depth == 0) &&
+ (tok->flags & JSON_TOKENER_STRICT)) {
+ /* unexpected char after JSON data */
+ tok->err = json_tokener_error_parse_unexpected;
+ }
+ if (!c) { /* We hit an eof char (0) */
+ if(state != json_tokener_state_finish &&
+ saved_state != json_tokener_state_finish)
+ tok->err = json_tokener_error_parse_eof;
+ }
+
+#ifdef HAVE_SETLOCALE
+ setlocale(LC_NUMERIC, oldlocale);
+ if (oldlocale) free(oldlocale);
+#endif
+
+ if (tok->err == json_tokener_success)
+ {
+ json_object *ret = json_object_get(current);
+ int ii;
+
+ /* Partially reset, so we parse additional objects on subsequent calls. */
+ for(ii = tok->depth; ii >= 0; ii--)
+ json_tokener_reset_level(tok, ii);
+ return ret;
+ }
+
+ MC_DEBUG("json_tokener_parse_ex: error %s at offset %d\n",
+ json_tokener_errors[tok->err], tok->char_offset);
+ return NULL;
+}
+
+void json_tokener_set_flags(struct json_tokener *tok, int flags)
+{
+ tok->flags = flags;
+}
diff --git a/json-c/json_tokener.h b/json-c/json_tokener.h
new file mode 100644
index 00000000..a72d2bde
--- /dev/null
+++ b/json-c/json_tokener.h
@@ -0,0 +1,208 @@
+/*
+ * $Id: json_tokener.h,v 1.10 2006/07/25 03:24:50 mclark Exp $
+ *
+ * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
+ * Michael Clark
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See COPYING for details.
+ *
+ */
+
+#ifndef _json_tokener_h_
+#define _json_tokener_h_
+
+#include
+#include "json_object.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum json_tokener_error {
+ json_tokener_success,
+ json_tokener_continue,
+ json_tokener_error_depth,
+ json_tokener_error_parse_eof,
+ json_tokener_error_parse_unexpected,
+ json_tokener_error_parse_null,
+ json_tokener_error_parse_boolean,
+ json_tokener_error_parse_number,
+ json_tokener_error_parse_array,
+ json_tokener_error_parse_object_key_name,
+ json_tokener_error_parse_object_key_sep,
+ json_tokener_error_parse_object_value_sep,
+ json_tokener_error_parse_string,
+ json_tokener_error_parse_comment,
+ json_tokener_error_size
+};
+
+enum json_tokener_state {
+ json_tokener_state_eatws,
+ json_tokener_state_start,
+ json_tokener_state_finish,
+ json_tokener_state_null,
+ json_tokener_state_comment_start,
+ json_tokener_state_comment,
+ json_tokener_state_comment_eol,
+ json_tokener_state_comment_end,
+ json_tokener_state_string,
+ json_tokener_state_string_escape,
+ json_tokener_state_escape_unicode,
+ json_tokener_state_boolean,
+ json_tokener_state_number,
+ json_tokener_state_array,
+ json_tokener_state_array_add,
+ json_tokener_state_array_sep,
+ json_tokener_state_object_field_start,
+ json_tokener_state_object_field,
+ json_tokener_state_object_field_end,
+ json_tokener_state_object_value,
+ json_tokener_state_object_value_add,
+ json_tokener_state_object_sep,
+ json_tokener_state_array_after_sep,
+ json_tokener_state_object_field_start_after_sep,
+ json_tokener_state_inf
+};
+
+struct json_tokener_srec
+{
+ enum json_tokener_state state, saved_state;
+ struct json_object *obj;
+ struct json_object *current;
+ char *obj_field_name;
+};
+
+#define JSON_TOKENER_DEFAULT_DEPTH 32
+
+struct json_tokener
+{
+ char *str;
+ struct printbuf *pb;
+ int max_depth, depth, is_double, st_pos, char_offset;
+ enum json_tokener_error err;
+ unsigned int ucs_char;
+ char quote_char;
+ struct json_tokener_srec *stack;
+ int flags;
+};
+
+/**
+ * Be strict when parsing JSON input. Use caution with
+ * this flag as what is considered valid may become more
+ * restrictive from one release to the next, causing your
+ * code to fail on previously working input.
+ *
+ * This flag is not set by default.
+ *
+ * @see json_tokener_set_flags()
+ */
+#define JSON_TOKENER_STRICT 0x01
+
+/**
+ * Given an error previously returned by json_tokener_get_error(),
+ * return a human readable description of the error.
+ *
+ * @return a generic error message is returned if an invalid error value is provided.
+ */
+const char *json_tokener_error_desc(enum json_tokener_error jerr);
+
+/**
+ * Retrieve the error caused by the last call to json_tokener_parse_ex(),
+ * or json_tokener_success if there is no error.
+ *
+ * When parsing a JSON string in pieces, if the tokener is in the middle
+ * of parsing this will return json_tokener_continue.
+ *
+ * See also json_tokener_error_desc().
+ */
+enum json_tokener_error json_tokener_get_error(struct json_tokener *tok);
+
+extern struct json_tokener* json_tokener_new(void);
+extern struct json_tokener* json_tokener_new_ex(int depth);
+extern void json_tokener_free(struct json_tokener *tok);
+extern void json_tokener_reset(struct json_tokener *tok);
+extern struct json_object* json_tokener_parse(const char *str);
+extern struct json_object* json_tokener_parse_verbose(const char *str, enum json_tokener_error *error);
+
+/**
+ * Set flags that control how parsing will be done.
+ */
+extern void json_tokener_set_flags(struct json_tokener *tok, int flags);
+
+/**
+ * Parse a string and return a non-NULL json_object if a valid JSON value
+ * is found. The string does not need to be a JSON object or array;
+ * it can also be a string, number or boolean value.
+ *
+ * A partial JSON string can be parsed. If the parsing is incomplete,
+ * NULL will be returned and json_tokener_get_error() will be return
+ * json_tokener_continue.
+ * json_tokener_parse_ex() can then be called with additional bytes in str
+ * to continue the parsing.
+ *
+ * If json_tokener_parse_ex() returns NULL and the error anything other than
+ * json_tokener_continue, a fatal error has occurred and parsing must be
+ * halted. Then tok object must not be re-used until json_tokener_reset() is
+ * called.
+ *
+ * When a valid JSON value is parsed, a non-NULL json_object will be
+ * returned. Also, json_tokener_get_error() will return json_tokener_success.
+ * Be sure to check the type with json_object_is_type() or
+ * json_object_get_type() before using the object.
+ *
+ * @b XXX this shouldn't use internal fields:
+ * Trailing characters after the parsed value do not automatically cause an
+ * error. It is up to the caller to decide whether to treat this as an
+ * error or to handle the additional characters, perhaps by parsing another
+ * json value starting from that point.
+ *
+ * Extra characters can be detected by comparing the tok->char_offset against
+ * the length of the last len parameter passed in.
+ *
+ * The tokener does \b not maintain an internal buffer so the caller is
+ * responsible for calling json_tokener_parse_ex with an appropriate str
+ * parameter starting with the extra characters.
+ *
+ * This interface is presently not 64-bit clean due to the int len argument
+ * so the function limits the maximum string size to INT32_MAX (2GB).
+ * If the function is called with len == -1 then strlen is called to check
+ * the string length is less than INT32_MAX (2GB)
+ *
+ * Example:
+ * @code
+json_object *jobj = NULL;
+const char *mystring = NULL;
+int stringlen = 0;
+enum json_tokener_error jerr;
+do {
+ mystring = ... // get JSON string, e.g. read from file, etc...
+ stringlen = strlen(mystring);
+ jobj = json_tokener_parse_ex(tok, mystring, stringlen);
+} while ((jerr = json_tokener_get_error(tok)) == json_tokener_continue);
+if (jerr != json_tokener_success)
+{
+ fprintf(stderr, "Error: %s\n", json_tokener_error_desc(jerr));
+ // Handle errors, as appropriate for your application.
+}
+if (tok->char_offset < stringlen) // XXX shouldn't access internal fields
+{
+ // Handle extra characters after parsed object as desired.
+ // e.g. issue an error, parse another object from that point, etc...
+}
+// Success, use jobj here.
+
+@endcode
+ *
+ * @param tok a json_tokener previously allocated with json_tokener_new()
+ * @param str an string with any valid JSON expression, or portion of. This does not need to be null terminated.
+ * @param len the length of str
+ */
+extern struct json_object* json_tokener_parse_ex(struct json_tokener *tok,
+ const char *str, int len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/json-c/json_util.c b/json-c/json_util.c
new file mode 100644
index 00000000..2a5621b0
--- /dev/null
+++ b/json-c/json_util.c
@@ -0,0 +1,299 @@
+/*
+ * $Id: json_util.c,v 1.4 2006/01/30 23:07:57 mclark Exp $
+ *
+ * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
+ * Michael Clark
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See COPYING for details.
+ *
+ */
+
+#include "config.h"
+#undef realloc
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#ifdef HAVE_SYS_TYPES_H
+#include
+#endif /* HAVE_SYS_TYPES_H */
+
+#ifdef HAVE_SYS_STAT_H
+#include
+#endif /* HAVE_SYS_STAT_H */
+
+#ifdef HAVE_FCNTL_H
+#include
+#endif /* HAVE_FCNTL_H */
+
+#ifdef HAVE_UNISTD_H
+# include
+#endif /* HAVE_UNISTD_H */
+
+#ifdef WIN32
+# define WIN32_LEAN_AND_MEAN
+# include
+# include
+#endif /* defined(WIN32) */
+
+#if !defined(HAVE_OPEN) && defined(WIN32)
+# define open _open
+#endif
+
+#if !defined(HAVE_SNPRINTF) && defined(_MSC_VER)
+ /* MSC has the version as _snprintf */
+# define snprintf _snprintf
+#elif !defined(HAVE_SNPRINTF)
+# error You do not have snprintf on your system.
+#endif /* HAVE_SNPRINTF */
+
+#include "debug.h"
+#include "printbuf.h"
+#include "json_inttypes.h"
+#include "json_object.h"
+#include "json_tokener.h"
+#include "json_util.h"
+
+static int sscanf_is_broken = 0;
+static int sscanf_is_broken_testdone = 0;
+static void sscanf_is_broken_test(void);
+
+struct json_object* json_object_from_file(const char *filename)
+{
+ struct printbuf *pb;
+ struct json_object *obj;
+ char buf[JSON_FILE_BUF_SIZE];
+ int fd, ret;
+
+ if((fd = open(filename, O_RDONLY)) < 0) {
+ MC_ERROR("json_object_from_file: error opening file %s: %s\n",
+ filename, strerror(errno));
+ return NULL;
+ }
+ if(!(pb = printbuf_new())) {
+ close(fd);
+ MC_ERROR("json_object_from_file: printbuf_new failed\n");
+ return NULL;
+ }
+ while((ret = read(fd, buf, JSON_FILE_BUF_SIZE)) > 0) {
+ printbuf_memappend(pb, buf, ret);
+ }
+ close(fd);
+ if(ret < 0) {
+ MC_ERROR("json_object_from_file: error reading file %s: %s\n",
+ filename, strerror(errno));
+ printbuf_free(pb);
+ return NULL;
+ }
+ obj = json_tokener_parse(pb->buf);
+ printbuf_free(pb);
+ return obj;
+}
+
+/* extended "format and write to file" function */
+
+int json_object_to_file_ext(const char *filename, struct json_object *obj, int flags)
+{
+ const char *json_str;
+ int fd, ret;
+ unsigned int wpos, wsize;
+
+ if(!obj) {
+ MC_ERROR("json_object_to_file: object is null\n");
+ return -1;
+ }
+
+ if((fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, 0644)) < 0) {
+ MC_ERROR("json_object_to_file: error opening file %s: %s\n",
+ filename, strerror(errno));
+ return -1;
+ }
+
+ if(!(json_str = json_object_to_json_string_ext(obj,flags))) {
+ close(fd);
+ return -1;
+ }
+
+ wsize = (unsigned int)(strlen(json_str) & UINT_MAX); /* CAW: probably unnecessary, but the most 64bit safe */
+ wpos = 0;
+ while(wpos < wsize) {
+ if((ret = write(fd, json_str + wpos, wsize-wpos)) < 0) {
+ close(fd);
+ MC_ERROR("json_object_to_file: error writing file %s: %s\n",
+ filename, strerror(errno));
+ return -1;
+ }
+
+ /* because of the above check for ret < 0, we can safely cast and add */
+ wpos += (unsigned int)ret;
+ }
+
+ close(fd);
+ return 0;
+}
+
+// backwards compatible "format and write to file" function
+
+int json_object_to_file(const char *filename, struct json_object *obj)
+{
+ return json_object_to_file_ext(filename, obj, JSON_C_TO_STRING_PLAIN);
+}
+
+int json_parse_double(const char *buf, double *retval)
+{
+ return (sscanf(buf, "%lf", retval)==1 ? 0 : 1);
+}
+
+/*
+ * Not all implementations of sscanf actually work properly.
+ * Check whether the one we're currently using does, and if
+ * it's broken, enable the workaround code.
+ */
+static void sscanf_is_broken_test()
+{
+ int64_t num64;
+ int ret_errno, is_int64_min, ret_errno2, is_int64_max;
+
+ (void)sscanf(" -01234567890123456789012345", "%" SCNd64, &num64);
+ ret_errno = errno;
+ is_int64_min = (num64 == INT64_MIN);
+
+ (void)sscanf(" 01234567890123456789012345", "%" SCNd64, &num64);
+ ret_errno2 = errno;
+ is_int64_max = (num64 == INT64_MAX);
+
+ if (ret_errno != ERANGE || !is_int64_min ||
+ ret_errno2 != ERANGE || !is_int64_max)
+ {
+ MC_DEBUG("sscanf_is_broken_test failed, enabling workaround code\n");
+ sscanf_is_broken = 1;
+ }
+}
+
+int json_parse_int64(const char *buf, int64_t *retval)
+{
+ int64_t num64;
+ const char *buf_sig_digits;
+ int orig_has_neg;
+ int saved_errno;
+
+ if (!sscanf_is_broken_testdone)
+ {
+ sscanf_is_broken_test();
+ sscanf_is_broken_testdone = 1;
+ }
+
+ // Skip leading spaces
+ while (isspace((int)*buf) && *buf)
+ buf++;
+
+ errno = 0; // sscanf won't always set errno, so initialize
+ if (sscanf(buf, "%" SCNd64, &num64) != 1)
+ {
+ MC_DEBUG("Failed to parse, sscanf != 1\n");
+ return 1;
+ }
+
+ saved_errno = errno;
+ buf_sig_digits = buf;
+ orig_has_neg = 0;
+ if (*buf_sig_digits == '-')
+ {
+ buf_sig_digits++;
+ orig_has_neg = 1;
+ }
+
+ // Not all sscanf implementations actually work
+ if (sscanf_is_broken && saved_errno != ERANGE)
+ {
+ char buf_cmp[100];
+ char *buf_cmp_start = buf_cmp;
+ int recheck_has_neg = 0;
+ int buf_cmp_len;
+
+ // Skip leading zeros, but keep at least one digit
+ while (buf_sig_digits[0] == '0' && buf_sig_digits[1] != '\0')
+ buf_sig_digits++;
+ if (num64 == 0) // assume all sscanf impl's will parse -0 to 0
+ orig_has_neg = 0; // "-0" is the same as just plain "0"
+
+ snprintf(buf_cmp_start, sizeof(buf_cmp), "%" PRId64, num64);
+ if (*buf_cmp_start == '-')
+ {
+ recheck_has_neg = 1;
+ buf_cmp_start++;
+ }
+ // No need to skip leading spaces or zeros here.
+
+ buf_cmp_len = strlen(buf_cmp_start);
+ /**
+ * If the sign is different, or
+ * some of the digits are different, or
+ * there is another digit present in the original string
+ * then we have NOT successfully parsed the value.
+ */
+ if (orig_has_neg != recheck_has_neg ||
+ strncmp(buf_sig_digits, buf_cmp_start, strlen(buf_cmp_start)) != 0 ||
+ ((int)strlen(buf_sig_digits) != buf_cmp_len &&
+ isdigit((int)buf_sig_digits[buf_cmp_len])
+ )
+ )
+ {
+ saved_errno = ERANGE;
+ }
+ }
+
+ // Not all sscanf impl's set the value properly when out of range.
+ // Always do this, even for properly functioning implementations,
+ // since it shouldn't slow things down much.
+ if (saved_errno == ERANGE)
+ {
+ if (orig_has_neg)
+ num64 = INT64_MIN;
+ else
+ num64 = INT64_MAX;
+ }
+ *retval = num64;
+ return 0;
+}
+
+#ifndef HAVE_REALLOC
+void* rpl_realloc(void* p, size_t n)
+{
+ if (n == 0)
+ n = 1;
+ if (p == 0)
+ return malloc(n);
+ return realloc(p, n);
+}
+#endif
+
+#define NELEM(a) (sizeof(a) / sizeof(a[0]))
+static const char* json_type_name[] = {
+ /* If you change this, be sure to update the enum json_type definition too */
+ "null",
+ "boolean",
+ "double",
+ "int",
+ "object",
+ "array",
+ "string",
+};
+
+const char *json_type_to_name(enum json_type o_type)
+{
+ int o_type_int = (int)o_type;
+ if (o_type_int < 0 || o_type_int >= (int)NELEM(json_type_name))
+ {
+ MC_ERROR("json_type_to_name: type %d is out of range [0,%d]\n", o_type, NELEM(json_type_name));
+ return NULL;
+ }
+ return json_type_name[o_type];
+}
+
diff --git a/json-c/json_util.h b/json-c/json_util.h
new file mode 100644
index 00000000..387dbc47
--- /dev/null
+++ b/json-c/json_util.h
@@ -0,0 +1,50 @@
+/*
+ * $Id: json_util.h,v 1.4 2006/01/30 23:07:57 mclark Exp $
+ *
+ * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
+ * Michael Clark
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See COPYING for details.
+ *
+ */
+
+#ifndef _json_util_h_
+#define _json_util_h_
+
+#include "json_object.h"
+
+#ifndef json_min
+#define json_min(a,b) ((a) < (b) ? (a) : (b))
+#endif
+
+#ifndef json_max
+#define json_max(a,b) ((a) > (b) ? (a) : (b))
+#endif
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define JSON_FILE_BUF_SIZE 4096
+
+/* utility functions */
+extern struct json_object* json_object_from_file(const char *filename);
+extern int json_object_to_file(const char *filename, struct json_object *obj);
+extern int json_object_to_file_ext(const char *filename, struct json_object *obj, int flags);
+extern int json_parse_int64(const char *buf, int64_t *retval);
+extern int json_parse_double(const char *buf, double *retval);
+
+
+/**
+ * Return a string describing the type of the object.
+ * e.g. "int", or "object", etc...
+ */
+extern const char *json_type_to_name(enum json_type o_type);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/json-c/libjson.c b/json-c/libjson.c
new file mode 100644
index 00000000..5284fd0e
--- /dev/null
+++ b/json-c/libjson.c
@@ -0,0 +1,26 @@
+
+/* dummy source file for compatibility purposes */
+
+#if defined(HAVE_CDEFS_H)
+#include
+#endif
+
+#ifndef __warn_references
+
+#if defined(__GNUC__) && defined (HAS_GNU_WARNING_LONG)
+
+#define __warn_references(sym,msg) \
+ __asm__(".section .gnu" #sym ",\n\t.ascii \"" msg "\"\n\t.text");
+
+#else
+#define __warn_references(sym,msg) /* nothing */
+#endif
+
+#endif
+
+#include "json_object.h"
+
+__warn_references(json_object_get, "Warning: please link against libjson-c instead of libjson");
+
+/* __asm__(".section .gnu.warning." __STRING(sym) \
+ " ; .ascii \"" msg "\" ; .text") */
diff --git a/json-c/linkhash.c b/json-c/linkhash.c
new file mode 100644
index 00000000..156a4b55
--- /dev/null
+++ b/json-c/linkhash.c
@@ -0,0 +1,602 @@
+/*
+ * $Id: linkhash.c,v 1.4 2006/01/26 02:16:28 mclark Exp $
+ *
+ * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
+ * Michael Clark
+ * Copyright (c) 2009 Hewlett-Packard Development Company, L.P.
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See COPYING for details.
+ *
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#ifdef HAVE_ENDIAN_H
+# include /* attempt to define endianness */
+#endif
+
+#include "random_seed.h"
+#include "linkhash.h"
+
+void lh_abort(const char *msg, ...)
+{
+ va_list ap;
+ va_start(ap, msg);
+ vprintf(msg, ap);
+ va_end(ap);
+ exit(1);
+}
+
+unsigned long lh_ptr_hash(const void *k)
+{
+ /* CAW: refactored to be 64bit nice */
+ return (unsigned long)((((ptrdiff_t)k * LH_PRIME) >> 4) & ULONG_MAX);
+}
+
+int lh_ptr_equal(const void *k1, const void *k2)
+{
+ return (k1 == k2);
+}
+
+/*
+ * hashlittle from lookup3.c, by Bob Jenkins, May 2006, Public Domain.
+ * http://burtleburtle.net/bob/c/lookup3.c
+ * minor modifications to make functions static so no symbols are exported
+ * minor mofifications to compile with -Werror
+ */
+
+/*
+-------------------------------------------------------------------------------
+lookup3.c, by Bob Jenkins, May 2006, Public Domain.
+
+These are functions for producing 32-bit hashes for hash table lookup.
+hashword(), hashlittle(), hashlittle2(), hashbig(), mix(), and final()
+are externally useful functions. Routines to test the hash are included
+if SELF_TEST is defined. You can use this free for any purpose. It's in
+the public domain. It has no warranty.
+
+You probably want to use hashlittle(). hashlittle() and hashbig()
+hash byte arrays. hashlittle() is is faster than hashbig() on
+little-endian machines. Intel and AMD are little-endian machines.
+On second thought, you probably want hashlittle2(), which is identical to
+hashlittle() except it returns two 32-bit hashes for the price of one.
+You could implement hashbig2() if you wanted but I haven't bothered here.
+
+If you want to find a hash of, say, exactly 7 integers, do
+ a = i1; b = i2; c = i3;
+ mix(a,b,c);
+ a += i4; b += i5; c += i6;
+ mix(a,b,c);
+ a += i7;
+ final(a,b,c);
+then use c as the hash value. If you have a variable length array of
+4-byte integers to hash, use hashword(). If you have a byte array (like
+a character string), use hashlittle(). If you have several byte arrays, or
+a mix of things, see the comments above hashlittle().
+
+Why is this so big? I read 12 bytes at a time into 3 4-byte integers,
+then mix those integers. This is fast (you can do a lot more thorough
+mixing with 12*3 instructions on 3 integers than you can with 3 instructions
+on 1 byte), but shoehorning those bytes into integers efficiently is messy.
+-------------------------------------------------------------------------------
+*/
+
+/*
+ * My best guess at if you are big-endian or little-endian. This may
+ * need adjustment.
+ */
+#if (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && \
+ __BYTE_ORDER == __LITTLE_ENDIAN) || \
+ (defined(i386) || defined(__i386__) || defined(__i486__) || \
+ defined(__i586__) || defined(__i686__) || defined(vax) || defined(MIPSEL))
+# define HASH_LITTLE_ENDIAN 1
+# define HASH_BIG_ENDIAN 0
+#elif (defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && \
+ __BYTE_ORDER == __BIG_ENDIAN) || \
+ (defined(sparc) || defined(POWERPC) || defined(mc68000) || defined(sel))
+# define HASH_LITTLE_ENDIAN 0
+# define HASH_BIG_ENDIAN 1
+#else
+# define HASH_LITTLE_ENDIAN 0
+# define HASH_BIG_ENDIAN 0
+#endif
+
+#define hashsize(n) ((uint32_t)1<<(n))
+#define hashmask(n) (hashsize(n)-1)
+#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k))))
+
+/*
+-------------------------------------------------------------------------------
+mix -- mix 3 32-bit values reversibly.
+
+This is reversible, so any information in (a,b,c) before mix() is
+still in (a,b,c) after mix().
+
+If four pairs of (a,b,c) inputs are run through mix(), or through
+mix() in reverse, there are at least 32 bits of the output that
+are sometimes the same for one pair and different for another pair.
+This was tested for:
+* pairs that differed by one bit, by two bits, in any combination
+ of top bits of (a,b,c), or in any combination of bottom bits of
+ (a,b,c).
+* "differ" is defined as +, -, ^, or ~^. For + and -, I transformed
+ the output delta to a Gray code (a^(a>>1)) so a string of 1's (as
+ is commonly produced by subtraction) look like a single 1-bit
+ difference.
+* the base values were pseudorandom, all zero but one bit set, or
+ all zero plus a counter that starts at zero.
+
+Some k values for my "a-=c; a^=rot(c,k); c+=b;" arrangement that
+satisfy this are
+ 4 6 8 16 19 4
+ 9 15 3 18 27 15
+ 14 9 3 7 17 3
+Well, "9 15 3 18 27 15" didn't quite get 32 bits diffing
+for "differ" defined as + with a one-bit base and a two-bit delta. I
+used http://burtleburtle.net/bob/hash/avalanche.html to choose
+the operations, constants, and arrangements of the variables.
+
+This does not achieve avalanche. There are input bits of (a,b,c)
+that fail to affect some output bits of (a,b,c), especially of a. The
+most thoroughly mixed value is c, but it doesn't really even achieve
+avalanche in c.
+
+This allows some parallelism. Read-after-writes are good at doubling
+the number of bits affected, so the goal of mixing pulls in the opposite
+direction as the goal of parallelism. I did what I could. Rotates
+seem to cost as much as shifts on every machine I could lay my hands
+on, and rotates are much kinder to the top and bottom bits, so I used
+rotates.
+-------------------------------------------------------------------------------
+*/
+#define mix(a,b,c) \
+{ \
+ a -= c; a ^= rot(c, 4); c += b; \
+ b -= a; b ^= rot(a, 6); a += c; \
+ c -= b; c ^= rot(b, 8); b += a; \
+ a -= c; a ^= rot(c,16); c += b; \
+ b -= a; b ^= rot(a,19); a += c; \
+ c -= b; c ^= rot(b, 4); b += a; \
+}
+
+/*
+-------------------------------------------------------------------------------
+final -- final mixing of 3 32-bit values (a,b,c) into c
+
+Pairs of (a,b,c) values differing in only a few bits will usually
+produce values of c that look totally different. This was tested for
+* pairs that differed by one bit, by two bits, in any combination
+ of top bits of (a,b,c), or in any combination of bottom bits of
+ (a,b,c).
+* "differ" is defined as +, -, ^, or ~^. For + and -, I transformed
+ the output delta to a Gray code (a^(a>>1)) so a string of 1's (as
+ is commonly produced by subtraction) look like a single 1-bit
+ difference.
+* the base values were pseudorandom, all zero but one bit set, or
+ all zero plus a counter that starts at zero.
+
+These constants passed:
+ 14 11 25 16 4 14 24
+ 12 14 25 16 4 14 24
+and these came close:
+ 4 8 15 26 3 22 24
+ 10 8 15 26 3 22 24
+ 11 8 15 26 3 22 24
+-------------------------------------------------------------------------------
+*/
+#define final(a,b,c) \
+{ \
+ c ^= b; c -= rot(b,14); \
+ a ^= c; a -= rot(c,11); \
+ b ^= a; b -= rot(a,25); \
+ c ^= b; c -= rot(b,16); \
+ a ^= c; a -= rot(c,4); \
+ b ^= a; b -= rot(a,14); \
+ c ^= b; c -= rot(b,24); \
+}
+
+
+/*
+-------------------------------------------------------------------------------
+hashlittle() -- hash a variable-length key into a 32-bit value
+ k : the key (the unaligned variable-length array of bytes)
+ length : the length of the key, counting by bytes
+ initval : can be any 4-byte value
+Returns a 32-bit value. Every bit of the key affects every bit of
+the return value. Two keys differing by one or two bits will have
+totally different hash values.
+
+The best hash table sizes are powers of 2. There is no need to do
+mod a prime (mod is sooo slow!). If you need less than 32 bits,
+use a bitmask. For example, if you need only 10 bits, do
+ h = (h & hashmask(10));
+In which case, the hash table should have hashsize(10) elements.
+
+If you are hashing n strings (uint8_t **)k, do it like this:
+ for (i=0, h=0; i 12)
+ {
+ a += k[0];
+ b += k[1];
+ c += k[2];
+ mix(a,b,c);
+ length -= 12;
+ k += 3;
+ }
+
+ /*----------------------------- handle the last (probably partial) block */
+ /*
+ * "k[2]&0xffffff" actually reads beyond the end of the string, but
+ * then masks off the part it's not allowed to read. Because the
+ * string is aligned, the masked-off tail is in the same word as the
+ * rest of the string. Every machine with memory protection I've seen
+ * does it on word boundaries, so is OK with this. But VALGRIND will
+ * still catch it and complain. The masking trick does make the hash
+ * noticably faster for short strings (like English words).
+ */
+#ifndef VALGRIND
+
+ switch(length)
+ {
+ case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;
+ case 11: c+=k[2]&0xffffff; b+=k[1]; a+=k[0]; break;
+ case 10: c+=k[2]&0xffff; b+=k[1]; a+=k[0]; break;
+ case 9 : c+=k[2]&0xff; b+=k[1]; a+=k[0]; break;
+ case 8 : b+=k[1]; a+=k[0]; break;
+ case 7 : b+=k[1]&0xffffff; a+=k[0]; break;
+ case 6 : b+=k[1]&0xffff; a+=k[0]; break;
+ case 5 : b+=k[1]&0xff; a+=k[0]; break;
+ case 4 : a+=k[0]; break;
+ case 3 : a+=k[0]&0xffffff; break;
+ case 2 : a+=k[0]&0xffff; break;
+ case 1 : a+=k[0]&0xff; break;
+ case 0 : return c; /* zero length strings require no mixing */
+ }
+
+#else /* make valgrind happy */
+
+ const uint8_t *k8 = (const uint8_t *)k;
+ switch(length)
+ {
+ case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;
+ case 11: c+=((uint32_t)k8[10])<<16; /* fall through */
+ case 10: c+=((uint32_t)k8[9])<<8; /* fall through */
+ case 9 : c+=k8[8]; /* fall through */
+ case 8 : b+=k[1]; a+=k[0]; break;
+ case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */
+ case 6 : b+=((uint32_t)k8[5])<<8; /* fall through */
+ case 5 : b+=k8[4]; /* fall through */
+ case 4 : a+=k[0]; break;
+ case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */
+ case 2 : a+=((uint32_t)k8[1])<<8; /* fall through */
+ case 1 : a+=k8[0]; break;
+ case 0 : return c;
+ }
+
+#endif /* !valgrind */
+
+ } else if (HASH_LITTLE_ENDIAN && ((u.i & 0x1) == 0)) {
+ const uint16_t *k = (const uint16_t *)key; /* read 16-bit chunks */
+ const uint8_t *k8;
+
+ /*--------------- all but last block: aligned reads and different mixing */
+ while (length > 12)
+ {
+ a += k[0] + (((uint32_t)k[1])<<16);
+ b += k[2] + (((uint32_t)k[3])<<16);
+ c += k[4] + (((uint32_t)k[5])<<16);
+ mix(a,b,c);
+ length -= 12;
+ k += 6;
+ }
+
+ /*----------------------------- handle the last (probably partial) block */
+ k8 = (const uint8_t *)k;
+ switch(length)
+ {
+ case 12: c+=k[4]+(((uint32_t)k[5])<<16);
+ b+=k[2]+(((uint32_t)k[3])<<16);
+ a+=k[0]+(((uint32_t)k[1])<<16);
+ break;
+ case 11: c+=((uint32_t)k8[10])<<16; /* fall through */
+ case 10: c+=k[4];
+ b+=k[2]+(((uint32_t)k[3])<<16);
+ a+=k[0]+(((uint32_t)k[1])<<16);
+ break;
+ case 9 : c+=k8[8]; /* fall through */
+ case 8 : b+=k[2]+(((uint32_t)k[3])<<16);
+ a+=k[0]+(((uint32_t)k[1])<<16);
+ break;
+ case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */
+ case 6 : b+=k[2];
+ a+=k[0]+(((uint32_t)k[1])<<16);
+ break;
+ case 5 : b+=k8[4]; /* fall through */
+ case 4 : a+=k[0]+(((uint32_t)k[1])<<16);
+ break;
+ case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */
+ case 2 : a+=k[0];
+ break;
+ case 1 : a+=k8[0];
+ break;
+ case 0 : return c; /* zero length requires no mixing */
+ }
+
+ } else { /* need to read the key one byte at a time */
+ const uint8_t *k = (const uint8_t *)key;
+
+ /*--------------- all but the last block: affect some 32 bits of (a,b,c) */
+ while (length > 12)
+ {
+ a += k[0];
+ a += ((uint32_t)k[1])<<8;
+ a += ((uint32_t)k[2])<<16;
+ a += ((uint32_t)k[3])<<24;
+ b += k[4];
+ b += ((uint32_t)k[5])<<8;
+ b += ((uint32_t)k[6])<<16;
+ b += ((uint32_t)k[7])<<24;
+ c += k[8];
+ c += ((uint32_t)k[9])<<8;
+ c += ((uint32_t)k[10])<<16;
+ c += ((uint32_t)k[11])<<24;
+ mix(a,b,c);
+ length -= 12;
+ k += 12;
+ }
+
+ /*-------------------------------- last block: affect all 32 bits of (c) */
+ switch(length) /* all the case statements fall through */
+ {
+ case 12: c+=((uint32_t)k[11])<<24;
+ case 11: c+=((uint32_t)k[10])<<16;
+ case 10: c+=((uint32_t)k[9])<<8;
+ case 9 : c+=k[8];
+ case 8 : b+=((uint32_t)k[7])<<24;
+ case 7 : b+=((uint32_t)k[6])<<16;
+ case 6 : b+=((uint32_t)k[5])<<8;
+ case 5 : b+=k[4];
+ case 4 : a+=((uint32_t)k[3])<<24;
+ case 3 : a+=((uint32_t)k[2])<<16;
+ case 2 : a+=((uint32_t)k[1])<<8;
+ case 1 : a+=k[0];
+ break;
+ case 0 : return c;
+ }
+ }
+
+ final(a,b,c);
+ return c;
+}
+
+unsigned long lh_char_hash(const void *k)
+{
+ static volatile int random_seed = -1;
+
+ if (random_seed == -1) {
+ int seed;
+ /* we can't use -1 as it is the uninitialized sentinel */
+ while ((seed = json_c_get_random_seed()) == -1);
+#if defined __GNUC__
+ __sync_val_compare_and_swap(&random_seed, -1, seed);
+#elif defined _MSC_VER
+ InterlockedCompareExchange(&random_seed, seed, -1);
+#else
+#warning "racy random seed initializtion if used by multiple threads"
+ random_seed = seed; /* potentially racy */
+#endif
+ }
+
+ return hashlittle((const char*)k, strlen((const char*)k), random_seed);
+}
+
+int lh_char_equal(const void *k1, const void *k2)
+{
+ return (strcmp((const char*)k1, (const char*)k2) == 0);
+}
+
+struct lh_table* lh_table_new(int size, const char *name,
+ lh_entry_free_fn *free_fn,
+ lh_hash_fn *hash_fn,
+ lh_equal_fn *equal_fn)
+{
+ int i;
+ struct lh_table *t;
+
+ t = (struct lh_table*)calloc(1, sizeof(struct lh_table));
+ if(!t) lh_abort("lh_table_new: calloc failed\n");
+ t->count = 0;
+ t->size = size;
+ t->name = name;
+ t->table = (struct lh_entry*)calloc(size, sizeof(struct lh_entry));
+ if(!t->table) lh_abort("lh_table_new: calloc failed\n");
+ t->free_fn = free_fn;
+ t->hash_fn = hash_fn;
+ t->equal_fn = equal_fn;
+ for(i = 0; i < size; i++) t->table[i].k = LH_EMPTY;
+ return t;
+}
+
+struct lh_table* lh_kchar_table_new(int size, const char *name,
+ lh_entry_free_fn *free_fn)
+{
+ return lh_table_new(size, name, free_fn, lh_char_hash, lh_char_equal);
+}
+
+struct lh_table* lh_kptr_table_new(int size, const char *name,
+ lh_entry_free_fn *free_fn)
+{
+ return lh_table_new(size, name, free_fn, lh_ptr_hash, lh_ptr_equal);
+}
+
+void lh_table_resize(struct lh_table *t, int new_size)
+{
+ struct lh_table *new_t;
+ struct lh_entry *ent;
+
+ new_t = lh_table_new(new_size, t->name, NULL, t->hash_fn, t->equal_fn);
+ ent = t->head;
+ while(ent) {
+ lh_table_insert(new_t, ent->k, ent->v);
+ ent = ent->next;
+ }
+ free(t->table);
+ t->table = new_t->table;
+ t->size = new_size;
+ t->head = new_t->head;
+ t->tail = new_t->tail;
+ t->resizes++;
+ free(new_t);
+}
+
+void lh_table_free(struct lh_table *t)
+{
+ struct lh_entry *c;
+ for(c = t->head; c != NULL; c = c->next) {
+ if(t->free_fn) {
+ t->free_fn(c);
+ }
+ }
+ free(t->table);
+ free(t);
+}
+
+
+int lh_table_insert(struct lh_table *t, void *k, const void *v)
+{
+ unsigned long h, n;
+
+ t->inserts++;
+ if(t->count >= t->size * LH_LOAD_FACTOR) lh_table_resize(t, t->size * 2);
+
+ h = t->hash_fn(k);
+ n = h % t->size;
+
+ while( 1 ) {
+ if(t->table[n].k == LH_EMPTY || t->table[n].k == LH_FREED) break;
+ t->collisions++;
+ if ((int)++n == t->size) n = 0;
+ }
+
+ t->table[n].k = k;
+ t->table[n].v = v;
+ t->count++;
+
+ if(t->head == NULL) {
+ t->head = t->tail = &t->table[n];
+ t->table[n].next = t->table[n].prev = NULL;
+ } else {
+ t->tail->next = &t->table[n];
+ t->table[n].prev = t->tail;
+ t->table[n].next = NULL;
+ t->tail = &t->table[n];
+ }
+
+ return 0;
+}
+
+
+struct lh_entry* lh_table_lookup_entry(struct lh_table *t, const void *k)
+{
+ unsigned long h = t->hash_fn(k);
+ unsigned long n = h % t->size;
+ int count = 0;
+
+ t->lookups++;
+ while( count < t->size ) {
+ if(t->table[n].k == LH_EMPTY) return NULL;
+ if(t->table[n].k != LH_FREED &&
+ t->equal_fn(t->table[n].k, k)) return &t->table[n];
+ if ((int)++n == t->size) n = 0;
+ count++;
+ }
+ return NULL;
+}
+
+
+const void* lh_table_lookup(struct lh_table *t, const void *k)
+{
+ void *result;
+ lh_table_lookup_ex(t, k, &result);
+ return result;
+}
+
+json_bool lh_table_lookup_ex(struct lh_table* t, const void* k, void **v)
+{
+ struct lh_entry *e = lh_table_lookup_entry(t, k);
+ if (e != NULL) {
+ if (v != NULL) *v = (void *)e->v;
+ return TRUE; /* key found */
+ }
+ if (v != NULL) *v = NULL;
+ return FALSE; /* key not found */
+}
+
+int lh_table_delete_entry(struct lh_table *t, struct lh_entry *e)
+{
+ ptrdiff_t n = (ptrdiff_t)(e - t->table); /* CAW: fixed to be 64bit nice, still need the crazy negative case... */
+
+ /* CAW: this is bad, really bad, maybe stack goes other direction on this machine... */
+ if(n < 0) { return -2; }
+
+ if(t->table[n].k == LH_EMPTY || t->table[n].k == LH_FREED) return -1;
+ t->count--;
+ if(t->free_fn) t->free_fn(e);
+ t->table[n].v = NULL;
+ t->table[n].k = LH_FREED;
+ if(t->tail == &t->table[n] && t->head == &t->table[n]) {
+ t->head = t->tail = NULL;
+ } else if (t->head == &t->table[n]) {
+ t->head->next->prev = NULL;
+ t->head = t->head->next;
+ } else if (t->tail == &t->table[n]) {
+ t->tail->prev->next = NULL;
+ t->tail = t->tail->prev;
+ } else {
+ t->table[n].prev->next = t->table[n].next;
+ t->table[n].next->prev = t->table[n].prev;
+ }
+ t->table[n].next = t->table[n].prev = NULL;
+ return 0;
+}
+
+
+int lh_table_delete(struct lh_table *t, const void *k)
+{
+ struct lh_entry *e = lh_table_lookup_entry(t, k);
+ if(!e) return -1;
+ return lh_table_delete_entry(t, e);
+}
+
+int lh_table_length(struct lh_table *t)
+{
+ return t->count;
+}
diff --git a/json-c/linkhash.h b/json-c/linkhash.h
new file mode 100644
index 00000000..950d09f3
--- /dev/null
+++ b/json-c/linkhash.h
@@ -0,0 +1,292 @@
+/*
+ * $Id: linkhash.h,v 1.6 2006/01/30 23:07:57 mclark Exp $
+ *
+ * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
+ * Michael Clark
+ * Copyright (c) 2009 Hewlett-Packard Development Company, L.P.
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See COPYING for details.
+ *
+ */
+
+#ifndef _linkhash_h_
+#define _linkhash_h_
+
+#include "json_object.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * golden prime used in hash functions
+ */
+#define LH_PRIME 0x9e370001UL
+
+/**
+ * The fraction of filled hash buckets until an insert will cause the table
+ * to be resized.
+ * This can range from just above 0 up to 1.0.
+ */
+#define LH_LOAD_FACTOR 0.66
+
+/**
+ * sentinel pointer value for empty slots
+ */
+#define LH_EMPTY (void*)-1
+
+/**
+ * sentinel pointer value for freed slots
+ */
+#define LH_FREED (void*)-2
+
+struct lh_entry;
+
+/**
+ * callback function prototypes
+ */
+typedef void (lh_entry_free_fn) (struct lh_entry *e);
+/**
+ * callback function prototypes
+ */
+typedef unsigned long (lh_hash_fn) (const void *k);
+/**
+ * callback function prototypes
+ */
+typedef int (lh_equal_fn) (const void *k1, const void *k2);
+
+/**
+ * An entry in the hash table
+ */
+struct lh_entry {
+ /**
+ * The key.
+ */
+ void *k;
+ /**
+ * The value.
+ */
+ const void *v;
+ /**
+ * The next entry
+ */
+ struct lh_entry *next;
+ /**
+ * The previous entry.
+ */
+ struct lh_entry *prev;
+};
+
+
+/**
+ * The hash table structure.
+ */
+struct lh_table {
+ /**
+ * Size of our hash.
+ */
+ int size;
+ /**
+ * Numbers of entries.
+ */
+ int count;
+
+ /**
+ * Number of collisions.
+ */
+ int collisions;
+
+ /**
+ * Number of resizes.
+ */
+ int resizes;
+
+ /**
+ * Number of lookups.
+ */
+ int lookups;
+
+ /**
+ * Number of inserts.
+ */
+ int inserts;
+
+ /**
+ * Number of deletes.
+ */
+ int deletes;
+
+ /**
+ * Name of the hash table.
+ */
+ const char *name;
+
+ /**
+ * The first entry.
+ */
+ struct lh_entry *head;
+
+ /**
+ * The last entry.
+ */
+ struct lh_entry *tail;
+
+ struct lh_entry *table;
+
+ /**
+ * A pointer onto the function responsible for freeing an entry.
+ */
+ lh_entry_free_fn *free_fn;
+ lh_hash_fn *hash_fn;
+ lh_equal_fn *equal_fn;
+};
+
+
+/**
+ * Pre-defined hash and equality functions
+ */
+extern unsigned long lh_ptr_hash(const void *k);
+extern int lh_ptr_equal(const void *k1, const void *k2);
+
+extern unsigned long lh_char_hash(const void *k);
+extern int lh_char_equal(const void *k1, const void *k2);
+
+
+/**
+ * Convenience list iterator.
+ */
+#define lh_foreach(table, entry) \
+for(entry = table->head; entry; entry = entry->next)
+
+/**
+ * lh_foreach_safe allows calling of deletion routine while iterating.
+ */
+#define lh_foreach_safe(table, entry, tmp) \
+for(entry = table->head; entry && ((tmp = entry->next) || 1); entry = tmp)
+
+
+
+/**
+ * Create a new linkhash table.
+ * @param size initial table size. The table is automatically resized
+ * although this incurs a performance penalty.
+ * @param name the table name.
+ * @param free_fn callback function used to free memory for entries
+ * when lh_table_free or lh_table_delete is called.
+ * If NULL is provided, then memory for keys and values
+ * must be freed by the caller.
+ * @param hash_fn function used to hash keys. 2 standard ones are defined:
+ * lh_ptr_hash and lh_char_hash for hashing pointer values
+ * and C strings respectively.
+ * @param equal_fn comparison function to compare keys. 2 standard ones defined:
+ * lh_ptr_hash and lh_char_hash for comparing pointer values
+ * and C strings respectively.
+ * @return a pointer onto the linkhash table.
+ */
+extern struct lh_table* lh_table_new(int size, const char *name,
+ lh_entry_free_fn *free_fn,
+ lh_hash_fn *hash_fn,
+ lh_equal_fn *equal_fn);
+
+/**
+ * Convenience function to create a new linkhash
+ * table with char keys.
+ * @param size initial table size.
+ * @param name table name.
+ * @param free_fn callback function used to free memory for entries.
+ * @return a pointer onto the linkhash table.
+ */
+extern struct lh_table* lh_kchar_table_new(int size, const char *name,
+ lh_entry_free_fn *free_fn);
+
+
+/**
+ * Convenience function to create a new linkhash
+ * table with ptr keys.
+ * @param size initial table size.
+ * @param name table name.
+ * @param free_fn callback function used to free memory for entries.
+ * @return a pointer onto the linkhash table.
+ */
+extern struct lh_table* lh_kptr_table_new(int size, const char *name,
+ lh_entry_free_fn *free_fn);
+
+
+/**
+ * Free a linkhash table.
+ * If a callback free function is provided then it is called for all
+ * entries in the table.
+ * @param t table to free.
+ */
+extern void lh_table_free(struct lh_table *t);
+
+
+/**
+ * Insert a record into the table.
+ * @param t the table to insert into.
+ * @param k a pointer to the key to insert.
+ * @param v a pointer to the value to insert.
+ */
+extern int lh_table_insert(struct lh_table *t, void *k, const void *v);
+
+
+/**
+ * Lookup a record into the table.
+ * @param t the table to lookup
+ * @param k a pointer to the key to lookup
+ * @return a pointer to the record structure of the value or NULL if it does not exist.
+ */
+extern struct lh_entry* lh_table_lookup_entry(struct lh_table *t, const void *k);
+
+/**
+ * Lookup a record into the table
+ * @param t the table to lookup
+ * @param k a pointer to the key to lookup
+ * @return a pointer to the found value or NULL if it does not exist.
+ * @deprecated Use lh_table_lookup_ex instead.
+ */
+THIS_FUNCTION_IS_DEPRECATED(extern const void* lh_table_lookup(struct lh_table *t, const void *k));
+
+/**
+ * Lookup a record in the table
+ * @param t the table to lookup
+ * @param k a pointer to the key to lookup
+ * @param v a pointer to a where to store the found value (set to NULL if it doesn't exist).
+ * @return whether or not the key was found
+ */
+extern json_bool lh_table_lookup_ex(struct lh_table *t, const void *k, void **v);
+
+/**
+ * Delete a record from the table.
+ * If a callback free function is provided then it is called for the
+ * for the item being deleted.
+ * @param t the table to delete from.
+ * @param e a pointer to the entry to delete.
+ * @return 0 if the item was deleted.
+ * @return -1 if it was not found.
+ */
+extern int lh_table_delete_entry(struct lh_table *t, struct lh_entry *e);
+
+
+/**
+ * Delete a record from the table.
+ * If a callback free function is provided then it is called for the
+ * for the item being deleted.
+ * @param t the table to delete from.
+ * @param k a pointer to the key to delete.
+ * @return 0 if the item was deleted.
+ * @return -1 if it was not found.
+ */
+extern int lh_table_delete(struct lh_table *t, const void *k);
+
+extern int lh_table_length(struct lh_table *t);
+
+void lh_abort(const char *msg, ...);
+void lh_table_resize(struct lh_table *t, int new_size);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/json-c/math_compat.h b/json-c/math_compat.h
new file mode 100644
index 00000000..f40b8faf
--- /dev/null
+++ b/json-c/math_compat.h
@@ -0,0 +1,28 @@
+#ifndef __math_compat_h
+#define __math_compat_h
+
+/* Define isnan and isinf on Windows/MSVC */
+
+#ifndef HAVE_DECL_ISNAN
+# ifdef HAVE_DECL__ISNAN
+#include
+#define isnan(x) _isnan(x)
+# endif
+#endif
+
+#ifndef HAVE_DECL_ISINF
+# ifdef HAVE_DECL__FINITE
+#include
+#define isinf(x) (!_finite(x))
+# endif
+#endif
+
+#ifndef HAVE_DECL_NAN
+#error This platform does not have nan()
+#endif
+
+#ifndef HAVE_DECL_INFINITY
+#error This platform does not have INFINITY
+#endif
+
+#endif
diff --git a/json-c/printbuf.c b/json-c/printbuf.c
new file mode 100644
index 00000000..fe952b45
--- /dev/null
+++ b/json-c/printbuf.c
@@ -0,0 +1,193 @@
+/*
+ * $Id: printbuf.c,v 1.5 2006/01/26 02:16:28 mclark Exp $
+ *
+ * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
+ * Michael Clark
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See COPYING for details.
+ *
+ *
+ * Copyright (c) 2008-2009 Yahoo! Inc. All rights reserved.
+ * The copyrights to the contents of this file are licensed under the MIT License
+ * (http://www.opensource.org/licenses/mit-license.php)
+ */
+
+#include "config.h"
+
+#include
+#include
+#include
+
+#ifdef HAVE_STDARG_H
+# include
+#else /* !HAVE_STDARG_H */
+# error Not enough var arg support!
+#endif /* HAVE_STDARG_H */
+
+#include "debug.h"
+#include "printbuf.h"
+
+static int printbuf_extend(struct printbuf *p, int min_size);
+
+struct printbuf* printbuf_new(void)
+{
+ struct printbuf *p;
+
+ p = (struct printbuf*)calloc(1, sizeof(struct printbuf));
+ if(!p) return NULL;
+ p->size = 32;
+ p->bpos = 0;
+ if(!(p->buf = (char*)malloc(p->size))) {
+ free(p);
+ return NULL;
+ }
+ return p;
+}
+
+
+/**
+ * Extend the buffer p so it has a size of at least min_size.
+ *
+ * If the current size is large enough, nothing is changed.
+ *
+ * Note: this does not check the available space! The caller
+ * is responsible for performing those calculations.
+ */
+static int printbuf_extend(struct printbuf *p, int min_size)
+{
+ char *t;
+ int new_size;
+
+ if (p->size >= min_size)
+ return 0;
+
+ new_size = p->size * 2;
+ if (new_size < min_size + 8)
+ new_size = min_size + 8;
+#ifdef PRINTBUF_DEBUG
+ MC_DEBUG("printbuf_memappend: realloc "
+ "bpos=%d min_size=%d old_size=%d new_size=%d\n",
+ p->bpos, min_size, p->size, new_size);
+#endif /* PRINTBUF_DEBUG */
+ if(!(t = (char*)realloc(p->buf, new_size)))
+ return -1;
+ p->size = new_size;
+ p->buf = t;
+ return 0;
+}
+
+int printbuf_memappend(struct printbuf *p, const char *buf, int size)
+{
+ if (p->size <= p->bpos + size + 1) {
+ if (printbuf_extend(p, p->bpos + size + 1) < 0)
+ return -1;
+ }
+ memcpy(p->buf + p->bpos, buf, size);
+ p->bpos += size;
+ p->buf[p->bpos]= '\0';
+ return size;
+}
+
+int printbuf_memset(struct printbuf *pb, int offset, int charvalue, int len)
+{
+ int size_needed;
+
+ if (offset == -1)
+ offset = pb->bpos;
+ size_needed = offset + len;
+ if (pb->size < size_needed)
+ {
+ if (printbuf_extend(pb, size_needed) < 0)
+ return -1;
+ }
+
+ memset(pb->buf + offset, charvalue, len);
+ if (pb->bpos < size_needed)
+ pb->bpos = size_needed;
+
+ return 0;
+}
+
+#if !defined(HAVE_VSNPRINTF) && defined(_MSC_VER)
+# define vsnprintf _vsnprintf
+#elif !defined(HAVE_VSNPRINTF) /* !HAVE_VSNPRINTF */
+# error Need vsnprintf!
+#endif /* !HAVE_VSNPRINTF && defined(WIN32) */
+
+#if !defined(HAVE_VASPRINTF)
+/* CAW: compliant version of vasprintf */
+static int vasprintf(char **buf, const char *fmt, va_list ap)
+{
+#ifndef WIN32
+ static char _T_emptybuffer = '\0';
+#endif /* !defined(WIN32) */
+ int chars;
+ char *b;
+
+ if(!buf) { return -1; }
+
+#ifdef WIN32
+ chars = _vscprintf(fmt, ap)+1;
+#else /* !defined(WIN32) */
+ /* CAW: RAWR! We have to hope to god here that vsnprintf doesn't overwrite
+ our buffer like on some 64bit sun systems.... but hey, its time to move on */
+ chars = vsnprintf(&_T_emptybuffer, 0, fmt, ap)+1;
+ if(chars < 0) { chars *= -1; } /* CAW: old glibc versions have this problem */
+#endif /* defined(WIN32) */
+
+ b = (char*)malloc(sizeof(char)*chars);
+ if(!b) { return -1; }
+
+ if((chars = vsprintf(b, fmt, ap)) < 0)
+ {
+ free(b);
+ } else {
+ *buf = b;
+ }
+
+ return chars;
+}
+#endif /* !HAVE_VASPRINTF */
+
+int sprintbuf(struct printbuf *p, const char *msg, ...)
+{
+ va_list ap;
+ char *t;
+ int size;
+ char buf[128];
+
+ /* user stack buffer first */
+ va_start(ap, msg);
+ size = vsnprintf(buf, 128, msg, ap);
+ va_end(ap);
+ /* if string is greater than stack buffer, then use dynamic string
+ with vasprintf. Note: some implementation of vsnprintf return -1
+ if output is truncated whereas some return the number of bytes that
+ would have been written - this code handles both cases. */
+ if(size == -1 || size > 127) {
+ va_start(ap, msg);
+ if((size = vasprintf(&t, msg, ap)) < 0) { va_end(ap); return -1; }
+ va_end(ap);
+ printbuf_memappend(p, t, size);
+ free(t);
+ return size;
+ } else {
+ printbuf_memappend(p, buf, size);
+ return size;
+ }
+}
+
+void printbuf_reset(struct printbuf *p)
+{
+ p->buf[0] = '\0';
+ p->bpos = 0;
+}
+
+void printbuf_free(struct printbuf *p)
+{
+ if(p) {
+ free(p->buf);
+ free(p);
+ }
+}
diff --git a/json-c/printbuf.h b/json-c/printbuf.h
new file mode 100644
index 00000000..b1bde7f9
--- /dev/null
+++ b/json-c/printbuf.h
@@ -0,0 +1,77 @@
+/*
+ * $Id: printbuf.h,v 1.4 2006/01/26 02:16:28 mclark Exp $
+ *
+ * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
+ * Michael Clark
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See COPYING for details.
+ *
+ *
+ * Copyright (c) 2008-2009 Yahoo! Inc. All rights reserved.
+ * The copyrights to the contents of this file are licensed under the MIT License
+ * (http://www.opensource.org/licenses/mit-license.php)
+ */
+
+#ifndef _printbuf_h_
+#define _printbuf_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct printbuf {
+ char *buf;
+ int bpos;
+ int size;
+};
+
+extern struct printbuf*
+printbuf_new(void);
+
+/* As an optimization, printbuf_memappend_fast is defined as a macro
+ * that handles copying data if the buffer is large enough; otherwise
+ * it invokes printbuf_memappend_real() which performs the heavy
+ * lifting of realloc()ing the buffer and copying data.
+ * Your code should not use printbuf_memappend directly--use
+ * printbuf_memappend_fast instead.
+ */
+extern int
+printbuf_memappend(struct printbuf *p, const char *buf, int size);
+
+#define printbuf_memappend_fast(p, bufptr, bufsize) \
+do { \
+ if ((p->size - p->bpos) > bufsize) { \
+ memcpy(p->buf + p->bpos, (bufptr), bufsize); \
+ p->bpos += bufsize; \
+ p->buf[p->bpos]= '\0'; \
+ } else { printbuf_memappend(p, (bufptr), bufsize); } \
+} while (0)
+
+#define printbuf_length(p) ((p)->bpos)
+
+/**
+ * Set len bytes of the buffer to charvalue, starting at offset offset.
+ * Similar to calling memset(x, charvalue, len);
+ *
+ * The memory allocated for the buffer is extended as necessary.
+ *
+ * If offset is -1, this starts at the end of the current data in the buffer.
+ */
+extern int
+printbuf_memset(struct printbuf *pb, int offset, int charvalue, int len);
+
+extern int
+sprintbuf(struct printbuf *p, const char *msg, ...);
+
+extern void
+printbuf_reset(struct printbuf *p);
+
+extern void
+printbuf_free(struct printbuf *p);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/json-c/random_seed.c b/json-c/random_seed.c
new file mode 100644
index 00000000..f6719298
--- /dev/null
+++ b/json-c/random_seed.c
@@ -0,0 +1,237 @@
+/*
+ * random_seed.c
+ *
+ * Copyright (c) 2013 Metaparadigm Pte. Ltd.
+ * Michael Clark
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See COPYING for details.
+ *
+ */
+
+#include
+#include "config.h"
+
+#define DEBUG_SEED(s)
+
+
+#if defined ENABLE_RDRAND
+
+/* cpuid */
+
+#if defined __GNUC__ && (defined __i386__ || defined __x86_64__)
+#define HAS_X86_CPUID 1
+
+static void do_cpuid(int regs[], int h)
+{
+ __asm__ __volatile__(
+#if defined __x86_64__
+ "pushq %%rbx;\n"
+#else
+ "pushl %%ebx;\n"
+#endif
+ "cpuid;\n"
+#if defined __x86_64__
+ "popq %%rbx;\n"
+#else
+ "popl %%ebx;\n"
+#endif
+ : "=a"(regs[0]), [ebx] "=r"(regs[1]), "=c"(regs[2]), "=d"(regs[3])
+ : "a"(h));
+}
+
+#elif defined _MSC_VER
+
+#define HAS_X86_CPUID 1
+#define do_cpuid __cpuid
+
+#endif
+
+/* has_rdrand */
+
+#if HAS_X86_CPUID
+
+static int has_rdrand()
+{
+ // CPUID.01H:ECX.RDRAND[bit 30] == 1
+ int regs[4];
+ do_cpuid(regs, 1);
+ return (regs[2] & (1 << 30)) != 0;
+}
+
+#endif
+
+/* get_rdrand_seed - GCC x86 and X64 */
+
+#if defined __GNUC__ && (defined __i386__ || defined __x86_64__)
+
+#define HAVE_RDRAND 1
+
+static int get_rdrand_seed()
+{
+ DEBUG_SEED("get_rdrand_seed");
+ int _eax;
+ // rdrand eax
+ __asm__ __volatile__("1: .byte 0x0F\n"
+ " .byte 0xC7\n"
+ " .byte 0xF0\n"
+ " jnc 1b;\n"
+ : "=a" (_eax));
+ return _eax;
+}
+
+#endif
+
+#if defined _MSC_VER
+
+#if _MSC_VER >= 1700
+#define HAVE_RDRAND 1
+
+/* get_rdrand_seed - Visual Studio 2012 and above */
+
+static int get_rdrand_seed()
+{
+ DEBUG_SEED("get_rdrand_seed");
+ int r;
+ while (_rdrand32_step(&r) == 0);
+ return r;
+}
+
+#elif defined _M_IX86
+#define HAVE_RDRAND 1
+
+/* get_rdrand_seed - Visual Studio 2010 and below - x86 only */
+
+static int get_rdrand_seed()
+{
+ DEBUG_SEED("get_rdrand_seed");
+ int _eax;
+retry:
+ // rdrand eax
+ __asm _emit 0x0F __asm _emit 0xC7 __asm _emit 0xF0
+ __asm jnc retry
+ __asm mov _eax, eax
+ return _eax;
+}
+
+#endif
+#endif
+
+#endif /* defined ENABLE_RDRAND */
+
+
+/* has_dev_urandom */
+
+#if defined (__APPLE__) || defined(__unix__) || defined(__linux__)
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define HAVE_DEV_RANDOM 1
+
+static const char *dev_random_file = "/dev/urandom";
+
+static int has_dev_urandom()
+{
+ struct stat buf;
+ if (stat(dev_random_file, &buf)) {
+ return 0;
+ }
+ return ((buf.st_mode & S_IFCHR) != 0);
+}
+
+
+/* get_dev_random_seed */
+
+static int get_dev_random_seed()
+{
+ DEBUG_SEED("get_dev_random_seed");
+
+ int fd = open(dev_random_file, O_RDONLY);
+ if (fd < 0) {
+ fprintf(stderr, "error opening %s: %s", dev_random_file, strerror(errno));
+ exit(1);
+ }
+
+ int r;
+ ssize_t nread = read(fd, &r, sizeof(r));
+ if (nread != sizeof(r)) {
+ fprintf(stderr, "error short read %s: %s", dev_random_file, strerror(errno));
+ exit(1);
+ }
+
+ close(fd);
+ return r;
+}
+
+#endif
+
+
+/* get_cryptgenrandom_seed */
+
+#ifdef WIN32
+
+#define HAVE_CRYPTGENRANDOM 1
+
+#include
+#include
+#ifndef __GNUC__
+#pragma comment(lib, "advapi32.lib")
+#endif
+
+static int get_cryptgenrandom_seed()
+{
+ DEBUG_SEED("get_cryptgenrandom_seed");
+
+ HCRYPTPROV hProvider = 0;
+ int r;
+
+ if (!CryptAcquireContextW(&hProvider, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) {
+ fprintf(stderr, "error CryptAcquireContextW");
+ exit(1);
+ }
+
+ if (!CryptGenRandom(hProvider, sizeof(r), (BYTE*)&r)) {
+ fprintf(stderr, "error CryptGenRandom");
+ exit(1);
+ }
+
+ CryptReleaseContext(hProvider, 0);
+
+ return r;
+}
+
+#endif
+
+
+/* get_time_seed */
+
+#include
+
+static int get_time_seed()
+{
+ DEBUG_SEED("get_time_seed");
+
+ return (int)time(NULL) * 433494437;
+}
+
+
+/* json_c_get_random_seed */
+
+int json_c_get_random_seed()
+{
+#if HAVE_RDRAND
+ if (has_rdrand()) return get_rdrand_seed();
+#endif
+#if HAVE_DEV_RANDOM
+ if (has_dev_urandom()) return get_dev_random_seed();
+#endif
+#if HAVE_CRYPTGENRANDOM
+ return get_cryptgenrandom_seed();
+#endif
+ return get_time_seed();
+}
diff --git a/json-c/random_seed.h b/json-c/random_seed.h
new file mode 100644
index 00000000..7362d67d
--- /dev/null
+++ b/json-c/random_seed.h
@@ -0,0 +1,25 @@
+/*
+ * random_seed.h
+ *
+ * Copyright (c) 2013 Metaparadigm Pte. Ltd.
+ * Michael Clark
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See COPYING for details.
+ *
+ */
+
+#ifndef seed_h
+#define seed_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int json_c_get_random_seed();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/keymaster/Android.bp b/keymaster/Android.bp
new file mode 100644
index 00000000..02d52a96
--- /dev/null
+++ b/keymaster/Android.bp
@@ -0,0 +1,27 @@
+//
+// Copyright (C) 2018 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.
+
+cc_binary {
+ name: "wait_for_strongbox",
+ relative_install_path: "hw",
+ srcs: [ "wait_for_strongbox.cpp" ],
+ cflags: [ "-Werror", "-Wall" ],
+ shared_libs: [
+ "android.hardware.keymaster@4.0",
+ "libbase",
+ "libkeymaster4support",
+ ],
+ proprietary: true,
+}
diff --git a/keymaster/wait_for_strongbox.cpp b/keymaster/wait_for_strongbox.cpp
new file mode 100644
index 00000000..8f957410
--- /dev/null
+++ b/keymaster/wait_for_strongbox.cpp
@@ -0,0 +1,59 @@
+/*
+ ** Copyright 2018, 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
+
+#define LOG_TAG "wait_for_strongbox"
+#include
+
+#include
+
+using android::hardware::keymaster::V4_0::SecurityLevel;
+using android::hardware::keymaster::V4_0::support::Keymaster;
+
+useconds_t kWaitTimeMicroseconds = 1 * 1000; // 1 milliseconds
+
+int main() {
+ for (unsigned cycleCount = 0; /* Forever */; ++cycleCount) {
+ auto keymasters = Keymaster::enumerateAvailableDevices();
+
+ bool foundStrongBox = false;
+ bool foundTee = false;
+ for (auto &dev : keymasters) {
+ SecurityLevel securityLevel = dev->halVersion().securityLevel;
+ uint8_t majorVersion = dev->halVersion().majorVersion;
+ if (securityLevel == SecurityLevel::STRONGBOX && majorVersion == 4) {
+ foundStrongBox = true;
+ }
+ if (securityLevel == SecurityLevel::TRUSTED_ENVIRONMENT && majorVersion == 4) {
+ foundTee = true;
+ }
+ }
+
+ if (foundTee && foundStrongBox) {
+ return 0;
+ }
+ if (cycleCount % 10 == 1) {
+ if (!foundStrongBox) {
+ LOG(WARNING) << "Still waiting for StrongBox Keymaster";
+ }
+ if (!foundTee) {
+ LOG(WARNING) << "Still waiting for TEE Keymaster";
+ }
+ }
+ usleep(kWaitTimeMicroseconds);
+ }
+}
diff --git a/manifest.xml b/manifest.xml
new file mode 100644
index 00000000..6af5a55f
--- /dev/null
+++ b/manifest.xml
@@ -0,0 +1,614 @@
+
+
+
+ android.hardware.boot
+ hwbinder
+
+ 1.0
+
+ IBootControl
+ default
+
+
+
+ android.hardware.health
+ hwbinder
+ 2.0
+
+ IHealth
+ default
+
+
+
+ android.hardware.audio
+ hwbinder
+ 5.0
+
+ IDevicesFactory
+ default
+
+
+
+ android.hardware.audio.effect
+ hwbinder
+ 5.0
+
+ IEffectsFactory
+ default
+
+
+
+ android.hardware.authsecret
+ hwbinder
+ 1.0
+
+ IAuthSecret
+ default
+
+
+
+ android.hardware.biometrics.fingerprint
+ hwbinder
+ 2.1
+
+ IBiometricsFingerprint
+ default
+
+
+
+ android.hardware.usb
+ hwbinder
+ 1.2
+
+ IUsb
+ default
+
+
+
+ android.hardware.usb.gadget
+ hwbinder
+ 1.0
+
+ IUsbGadget
+ default
+
+
+
+ android.hardware.confirmationui
+ hwbinder
+ 1.0
+
+ IConfirmationUI
+ default
+
+
+
+ android.hardware.soundtrigger
+ hwbinder
+ 2.2
+
+ ISoundTriggerHw
+ default
+
+
+
+
+ android.hardware.media.omx
+ hwbinder
+
+ 1.0
+
+ IOmx
+ default
+
+
+ IOmxStore
+ default
+
+
+
+
+
+ android.hardware.graphics.allocator
+ hwbinder
+
+ 3.0
+
+ IAllocator
+ default
+
+
+
+ android.hardware.graphics.mapper
+ passthrough
+
+ 3.0
+
+ IMapper
+ default
+
+
+
+ vendor.qti.hardware.display.allocator
+ hwbinder
+ 1.0
+
+ IQtiAllocator
+ default
+
+
+
+ vendor.qti.hardware.display.mapper
+ passthrough
+ 2.0
+
+ IQtiMapper
+ default
+
+
+
+ vendor.qti.hardware.display.mapperextensions
+ passthrough
+ 1.0
+
+ IQtiMapperExtensions
+ default
+
+
+
+ android.hardware.graphics.composer
+ hwbinder
+
+ 2.3
+
+ IComposer
+ default
+
+
+
+ vendor.display.config
+ hwbinder
+
+ 1.9
+
+ IDisplayConfig
+ default
+
+
+
+ vendor.google.radioext
+ hwbinder
+ 1.1
+
+ IRadioExt
+ default
+
+
+
+ android.hardware.configstore
+ hwbinder
+
+ 1.1
+
+ ISurfaceFlingerConfigs
+ default
+
+
+
+ android.hardware.memtrack
+ hwbinder
+
+ 1.0
+
+ IMemtrack
+ default
+
+
+
+ android.hardware.secure_element
+ hwbinder
+ 1.0
+
+ ISecureElement
+ eSE1
+ SIM1
+
+
+
+ android.hardware.sensors
+ hwbinder
+ 2.0
+
+ ISensors
+ default
+
+
+
+ android.hardware.camera.provider
+ hwbinder
+
+ 2.4
+
+ ICameraProvider
+ internal/0
+
+
+
+
+ android.hardware.gatekeeper
+ hwbinder
+ 1.0
+
+ IGatekeeper
+ default
+
+
+
+ android.hardware.gnss
+ hwbinder
+ @1.1::IGnss/default
+ @2.0::IGnss/default
+
+
+
+ vendor.qti.hardware.radio.qcrilhook
+ hwbinder
+ 1.0
+
+ IQtiOemHook
+ oemhook0
+ oemhook1
+
+
+
+ vendor.qti.hardware.radio.ims
+ hwbinder
+ 1.5
+
+ IImsRadio
+ imsradio0
+ imsradio1
+
+
+
+ vendor.qti.hardware.radio.uim
+ hwbinder
+ 1.2
+
+ IUim
+ Uim0
+ Uim1
+
+
+
+
+ vendor.qti.hardware.radio.uim_remote_client
+ hwbinder
+ 1.0
+
+ IUimRemoteServiceClient
+ uimRemoteClient0
+ uimRemoteClient1
+
+
+
+
+ vendor.qti.hardware.radio.uim_remote_server
+ hwbinder
+ 1.0
+
+ IUimRemoteServiceServer
+ uimRemoteServer0
+ uimRemoteServer1
+
+
+
+
+ vendor.qti.imsrtpservice
+ hwbinder
+
+ 2.1
+
+ IRTPService
+ imsrtpservice
+
+
+
+
+ android.hardware.bluetooth
+ hwbinder
+
+ 1.0
+
+ IBluetoothHci
+ default
+
+
+
+ android.hardware.bluetooth.a2dp
+ hwbinder
+ 1.0
+
+ IBluetoothAudioOffload
+ default
+
+
+
+ android.hardware.bluetooth.audio
+ hwbinder
+ 2.0
+
+ IBluetoothAudioProvidersFactory
+ default
+
+
+
+
+ com.qualcomm.qti.uceservice
+ hwbinder
+ 2.1
+
+ IUceService
+ com.qualcomm.qti.uceservice
+
+
+
+
+ vendor.qti.ims.callinfo
+ hwbinder
+ 1.0
+
+ IService
+ default
+
+
+
+ com.qualcomm.qti.imscmservice
+ hwbinder
+ 2.2
+
+ IImsCmService
+ qti.ims.connectionmanagerservice
+
+
+
+ vendor.qti.hardware.radio.am
+ hwbinder
+ 1.0
+
+ IQcRilAudio
+ slot1
+ slot2
+
+
+
+ android.hardware.wifi
+ hwbinder
+ 1.3
+
+ IWifi
+ default
+
+
+
+ android.hardware.wifi.supplicant
+ hwbinder
+ 1.2
+
+ ISupplicant
+ default
+
+
+
+ android.hardware.wifi.hostapd
+ hwbinder
+ 1.1
+
+ IHostapd
+ default
+
+
+
+ vendor.qti.data.factory
+ hwbinder
+ 2.0
+
+ IFactory
+ default
+
+
+
+ com.quicinc.cne.server
+ hwbinder
+
+ 2.2
+
+ IServer
+ cnd
+
+
+
+ com.quicinc.cne.api
+ hwbinder
+
+ 1.1
+
+ IApiService
+ cnd
+
+
+
+ android.hardware.drm
+ hwbinder
+
+ 1.0
+
+ ICryptoFactory
+ widevine
+ default
+
+
+ IDrmFactory
+ widevine
+ default
+
+ @1.2::ICryptoFactory/clearkey
+ @1.2::IDrmFactory/clearkey
+ @1.2::ICryptoFactory/widevine
+ @1.2::IDrmFactory/widevine
+
+
+ android.hardware.radio
+ hwbinder
+ 1.2
+
+ IRadio
+ slot1
+ slot2
+
+
+ ISap
+ slot1
+
+
+
+ android.hardware.radio.config
+ hwbinder
+ 1.1
+
+ IRadioConfig
+ default
+
+
+
+ android.hardware.nfc
+ hwbinder
+ 1.2
+
+ INfc
+ default
+
+
+
+
+ android.hardware.contexthub
+ hwbinder
+ 1.0
+
+ IContexthub
+ default
+
+
+
+
+ android.hardware.neuralnetworks
+ hwbinder
+ 1.2
+
+ IDevice
+ darwinn
+ default
+
+
+
+
+ android.hardware.keymaster
+ hwbinder
+ 4.0
+
+ IKeymasterDevice
+ default
+ strongbox
+
+
+
+ android.hardware.power.stats
+ hwbinder
+ 1.0
+
+ IPowerStats
+ default
+
+
+
+
+ android.hardware.light
+ hwbinder
+ 2.0
+
+ ILight
+ default
+
+
+
+ hardware.google.light
+ hwbinder
+ 1.0
+
+ ILight
+ default
+
+
+
+ android.hardware.weaver
+ hwbinder
+ 1.0
+
+ IWeaver
+ default
+
+
+
+ android.hardware.dumpstate
+ hwbinder
+ 1.0
+
+ IDumpstateDevice
+ default
+
+
+
+ vendor.qti.hardware.bluetooth_sar
+ hwbinder
+ 1.0
+
+ IBluetoothSar
+ default
+
+
+
+ vendor.qti.hardware.tui_comm
+ hwbinder
+ 1.0
+
+ ITuiComm
+ default
+
+
+
diff --git a/media_codecs.xml b/media_codecs.xml
new file mode 100644
index 00000000..12eb7cb3
--- /dev/null
+++ b/media_codecs.xml
@@ -0,0 +1,378 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/media_profiles.xml b/media_profiles.xml
new file mode 100644
index 00000000..f2b5120f
--- /dev/null
+++ b/media_profiles.xml
@@ -0,0 +1,869 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/media_profiles_V1_0.xml b/media_profiles_V1_0.xml
new file mode 100644
index 00000000..bee4016e
--- /dev/null
+++ b/media_profiles_V1_0.xml
@@ -0,0 +1,551 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/nfc/libese-hal-st.conf b/nfc/libese-hal-st.conf
new file mode 100644
index 00000000..1954bf72
--- /dev/null
+++ b/nfc/libese-hal-st.conf
@@ -0,0 +1,6 @@
+########################### Start of libese-hal-st.conf ###########################
+###############################################################################
+###############################################################################
+# ST HAL trace log level
+STESE_HAL_LOGLEVEL=1
+ST_ESE_DEV_NODE="/dev/st54j_se"
diff --git a/nfc/libnfc-hal-st.conf b/nfc/libnfc-hal-st.conf
new file mode 100644
index 00000000..47153d9b
--- /dev/null
+++ b/nfc/libnfc-hal-st.conf
@@ -0,0 +1,148 @@
+########################### Start of libnf-hal-st_aosp.conf ###########################
+
+###############################################################################
+###############################################################################
+# ST HAL trace log level
+STNFC_HAL_LOGLEVEL=1
+NFC_DEBUG_ENABLED=0
+
+###############################################################################
+# Vendor specific mode to enable FW (RF & SWP) traces.
+STNFC_FW_DEBUG_ENABLED=0
+
+###############################################################################
+# File used for NFA storage
+NFA_STORAGE="/data/nfc"
+
+###############################################################################
+# Keep the nfa storage file.
+PRESERVE_STORAGE=1
+
+###############################################################################
+# In Switch OFF mode (phone switched-off), specify the desired CE mode to
+# the controller.
+# 0: No card-emulation; DEFAULT
+# 1: Switch-off card-emulation enabled
+CE_ON_SWITCH_OFF_STATE=1
+
+###############################################################################
+# Vendor specific mode to support the USB charging mode if VPSIO=1 in switch off.
+STNFC_USB_CHARGING_MODE=1
+
+###############################################################################
+# Vendor Specific Proprietary Protocol & Discovery Configuration
+# Set to 0xFF if unsupported
+# byte[0] NCI_PROTOCOL_18092_ACTIVE
+# byte[1] NCI_PROTOCOL_B_PRIME
+# byte[2] NCI_PROTOCOL_DUAL
+# byte[3] NCI_PROTOCOL_15693
+# byte[4] NCI_PROTOCOL_KOVIO
+# byte[5] NCI_PROTOCOL_MIFARE
+# byte[6] NCI_DISCOVERY_TYPE_POLL_KOVIO
+# byte[7] NCI_DISCOVERY_TYPE_POLL_B_PRIME
+# byte[8] NCI_DISCOVERY_TYPE_LISTEN_B_PRIME
+NFA_PROPRIETARY_CFG={05:FF:FF:06:8A:90:77:FF:FF}
+
+###############################################################################
+# Choose the presence-check algorithm for type-4 tag. If not defined,
+# the default value is 1.
+# 0 NFA_RW_PRES_CHK_DEFAULT; Let stack selects an algorithm
+# 1 NFA_RW_PRES_CHK_I_BLOCK; ISO-DEP protocol's empty I-block
+# 2 NFA_RW_PRES_CHK_RESET; Deactivate to Sleep, then re-activate
+# 3 NFA_RW_PRES_CHK_RB_CH0; Type-4 tag protocol's ReadBinary command on channel 0
+# 4 NFA_RW_PRES_CHK_RB_CH3; Type-4 tag protocol's ReadBinary command on channel 3
+# 5 NFA_RW_PRES_CHK_ISO_DEP_NAK; presence check command ISO-DEP NAK as per NCI2.0
+PRESENCE_CHECK_ALGORITHM=5
+
+###############################################################################
+# Name of the NCI HAL module to use
+# If unset, falls back to nfc_nci.bcm2079x
+NCI_HAL_MODULE="nfc_nci.st21nfc"
+
+###############################################################################
+# White list to be set at startup.
+DEVICE_HOST_WHITE_LIST={02:C0}
+
+###############################################################################
+# BAIL OUT value for P2P
+# Implements algorithm for NFC-DEP protocol priority over ISO-DEP protocol.
+POLL_BAIL_OUT_MODE=1
+
+###############################################################################
+# Extended APDU length for ISO_DEP
+ISO_DEP_MAX_TRANSCEIVE=0xFEFF
+
+###############################################################################
+# Configure the NFC Extras to open and use a static pipe. If the value is
+# not set or set to 0, then the default is use a dynamic pipe based on a
+# destination gate (see NFA_HCI_DEFAULT_DEST_GATE). Note there is a value
+# for each EE (ESE/SIM)
+OFF_HOST_ESE_PIPE_ID=0x5E
+OFF_HOST_SIM_PIPE_ID=0x3E
+
+###############################################################################
+#Set the default Felica T3T System Code OffHost route Location :
+#This settings will be used when application does not set this parameter
+# host 0x00
+# eSE 0x82 (eSE), 0x86 (eUICC/SPI-SE)
+# UICC 0x81 (UICC_1), 0x85 (UICC_2)
+DEFAULT_SYS_CODE_ROUTE=0x86
+
+###############################################################################
+#Set the Felica T3T System Code supported power state:
+DEFAULT_SYS_CODE_PWR_STATE=0x3B
+
+###############################################################################
+# Path and Files used for FW update binaries storage
+STNFC_FW_PATH_STORAGE="/vendor/firmware"
+STNFC_FW_BIN_NAME="/st54j_fw.bin"
+STNFC_FW_CONF_NAME="/st54j_conf.bin"
+
+###############################################################################
+# Default off-host route for Felica.
+# This settings will be used when application does not set this parameter
+# host 0x00
+# eSE 0x82 (eSE), 0x86 (eUICC/SPI-SE)
+# UICC 0x81 (UICC_1), 0x85 (UICC_2)
+DEFAULT_NFCF_ROUTE=0x86
+
+###############################################################################
+# Configure the default off-host route.
+# used for technology A and B routing
+# eSE 0x82 (eSE), 0x86 (eUICC/SPI-SE)
+# UICC 0x81 (UICC_1), 0x85 (UICC_2)
+DEFAULT_OFFHOST_ROUTE=0x81
+
+###############################################################################
+# Configure the default AID route.
+# host 0x00
+# eSE 0x82 (eSE), 0x86 (eUICC/SPI-SE)
+# UICC 0x81 (UICC_1), 0x85 (UICC_2)
+DEFAULT_ROUTE=0x00
+
+###############################################################################
+# Configure the NFCEEIDs of offhost UICC.
+# UICC 0x81 (UICC_1), 0x85 (UICC_2)
+OFFHOST_ROUTE_UICC={81}
+
+###############################################################################
+# Configure the NFCEEIDs of offhost eSEs.
+# eSE 0x82 (eSE), 0x86 (eUICC/SPI-SE)
+OFFHOST_ROUTE_ESE={86}
+
+###############################################################################
+# Configure the list of NFCEE for the ISO-DEP routing.
+# host 0x00
+# eSE 0x82 (eSE), 0x86 (eUICC/SPI-SE)
+# UICC 0x81 (UICC_1), 0x85 (UICC_2)
+DEFAULT_ISODEP_ROUTE=0x81
+
+###############################################################################
+# Core configuration settings
+CORE_CONF_PROP={ 20, 02, 0a, 03,
+ a1, 01, 1e,
+ a2, 01, 19,
+ 80, 01, 01
+}
+
+
diff --git a/nfc/libnfc-nci.conf b/nfc/libnfc-nci.conf
new file mode 100644
index 00000000..149f1bb7
--- /dev/null
+++ b/nfc/libnfc-nci.conf
@@ -0,0 +1,102 @@
+###############################################################################
+# Application options
+NFC_DEBUG_ENABLED=0
+
+###############################################################################
+# File used for NFA storage
+NFA_STORAGE="/data/nfc"
+
+###############################################################################
+# Force UICC to only listen to the following technology(s).
+# The bits are defined as tNFA_TECHNOLOGY_MASK in nfa_api.h.
+# Default is NFA_TECHNOLOGY_MASK_A | NFA_TECHNOLOGY_MASK_B | NFA_TECHNOLOGY_MASK_F
+UICC_LISTEN_TECH_MASK=0x07
+
+###############################################################################
+# AID for Empty Select command
+# If specified, this AID will be substituted when an Empty SELECT command is
+# detected. The first byte is the length of the AID. Maximum length is 16.
+AID_FOR_EMPTY_SELECT={08:A0:00:00:01:51:00:00:00}
+
+###############################################################################
+# When screen is turned off, specify the desired power state of the controller.
+# 0: power-off-sleep state; DEFAULT
+# 1: full-power state
+# 2: screen-off card-emulation (CE4/CE3/CE1 modes are used)
+SCREEN_OFF_POWER_STATE=1
+
+###############################################################################
+# Force tag polling for the following technology(s).
+# The bits are defined as tNFA_TECHNOLOGY_MASK in nfa_api.h.
+# Default is NFA_TECHNOLOGY_MASK_A | NFA_TECHNOLOGY_MASK_B |
+# NFA_TECHNOLOGY_MASK_F | NFA_TECHNOLOGY_MASK_ISO15693 |
+# NFA_TECHNOLOGY_MASK_B_PRIME | NFA_TECHNOLOGY_MASK_KOVIO |
+# NFA_TECHNOLOGY_MASK_ACTIVE
+#
+# Notable bits:
+# NFA_TECHNOLOGY_MASK_A 0x01 /* NFC Technology A */
+# NFA_TECHNOLOGY_MASK_B 0x02 /* NFC Technology B */
+# NFA_TECHNOLOGY_MASK_F 0x04 /* NFC Technology F */
+# NFA_TECHNOLOGY_MASK_ISO15693 0x08 /* Proprietary Technology */
+# NFA_TECHNOLOGY_MASK_KOVIO 0x20 /* Proprietary Technology */
+# NFA_TECHNOLOGY_MASK_ACTIVE 0x40 /* NFC Technology Active */
+POLLING_TECH_MASK=0x2F
+
+###############################################################################
+# Force P2P to only listen for the following technology(s).
+# The bits are defined as tNFA_TECHNOLOGY_MASK in nfa_api.h.
+# Default is NFA_TECHNOLOGY_MASK_A | NFA_TECHNOLOGY_MASK_F |
+# NFA_TECHNOLOGY_MASK_ACTIVE
+#
+# Notable bits:
+# NFA_TECHNOLOGY_MASK_A 0x01 /* NFC Technology A */
+# NFA_TECHNOLOGY_MASK_F 0x04 /* NFC Technology F */
+# NFA_TECHNOLOGY_MASK_ACTIVE 0x40 /* NFC Technology Active */
+P2P_LISTEN_TECH_MASK=0x00
+
+PRESERVE_STORAGE=0x01
+
+###############################################################################
+# Override the stack default for NFA_EE_MAX_EE_SUPPORTED set in nfc_target.h.
+# The value is set to 3 by default as it assumes we will discover 0xF2,
+# 0xF3, and 0xF4. If a platform will exclude and SE, this value can be reduced
+# so that the stack will not wait any longer than necessary.
+# Maximum EE supported number
+# NXP PN547C2 0x02
+# NXP PN65T 0x03
+# NXP PN548C2 0x02
+# NXP PN66T 0x03
+NFA_MAX_EE_SUPPORTED=0x02
+
+###############################################################################
+# AID_MATCHING constants
+# AID_MATCHING_EXACT_ONLY 0x00
+# AID_MATCHING_EXACT_OR_PREFIX 0x01
+# AID_MATCHING_PREFIX_ONLY 0x02
+# AID_MATCHING_EXACT_OR_SUBSET_OR_PREFIX 0x03
+AID_MATCHING_MODE=0x03
+
+###############################################################################
+#Set the default Felica T3T System Code :
+#This settings will be used when application does not set this parameter
+DEFAULT_SYS_CODE={FE:FE}
+
+###############################################################################
+# Value of NIC parameter NFCC_COFNIG_CONTROL
+# 0x00 NFCC is not allowed to manage RF configuration
+# 0x01 NFCC is allowed to manage RF configuration
+NFCC_CONFIG_CONTROL=0x01
+
+###############################################################################
+#Set if the AID routing should be blocked for the power modes not supported.
+NFA_AID_BLOCK_ROUTE=1
+
+###############################################################################
+#Set the OffHost AID supported power state:
+OFFHOST_AID_ROUTE_PWR_STATE=0x3B
+
+###############################################################################
+# Mifare Tag implementation
+# 0: General implementation
+# 1: Legacy implementation
+LEGACY_MIFARE_READER=0
diff --git a/overlay/frameworks/base/core/res/res/values-mcc440-mnc20/config.xml b/overlay/frameworks/base/core/res/res/values-mcc440-mnc20/config.xml
new file mode 100644
index 00000000..0fdd49e6
--- /dev/null
+++ b/overlay/frameworks/base/core/res/res/values-mcc440-mnc20/config.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+ - com.google.android.tetheringentitlement
+ - com.google.android.tetheringentitlement.CarrierEntitlementActivity
+
+ com.google.android.carrierentitlement.SILENT_ENTITLEMENT_CHECK
+ com.google.android.carrierentitlement.SILENT_ENTITLEMENT_CHECK_RESULT
+
\ No newline at end of file
diff --git a/overlay/frameworks/base/core/res/res/values/config.xml b/overlay/frameworks/base/core/res/res/values/config.xml
new file mode 100755
index 00000000..6bbec7c8
--- /dev/null
+++ b/overlay/frameworks/base/core/res/res/values/config.xml
@@ -0,0 +1,293 @@
+
+
+
+
+
+
+ true
+
+
+ 2000
+ 4000
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+
+ - 0
+ - 1
+ - 3
+
+
+
+ 2
+
+
+ true
+
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+ 4
+
+
+ true
+
+
+
+ - "usb\\d"
+ - "rndis\\d"
+
+
+
+
+ - "wlan\\d"
+
+
+
+
+ - "bt-pan"
+
+
+
+ true
+
+ true
+
+
+
+
+
+
+ - "wifi,1,1,1,-1,true"
+ - "mobile,0,0,0,-1,true"
+ - "mobile_mms,2,0,2,60000,true"
+ - "mobile_supl,3,0,2,60000,true"
+ - "mobile_dun,4,0,2,60000,true"
+ - "mobile_hipri,5,0,3,60000,true"
+ - "mobile_fota,10,0,2,60000,true"
+ - "mobile_ims,11,0,2,60000,true"
+ - "mobile_cbs,12,0,2,60000,true"
+ - "mobile_ia,14,0,2,-1,true"
+ - "bluetooth,7,7,2,-1,true"
+ - "ethernet,9,9,9,-1,true"
+ - "mobile_emergency,15,0,2,-1,true
+
+
+
+
+
+ - "1,1"
+ - "0,1"
+ - "7,1"
+ - "9,1"
+
+
+
+ 0x80000000
+
+
+ 0x80000000
+
+
+ true
+
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+
+ true
+
+
+ false
+
+
+ true
+
+
+ org.codeaurora.ims
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+
+ - umts:131072,262144,1452032,4096,16384,399360
+ - hspa:131072,262144,2441216,4096,16384,399360
+ - hsupa:131072,262144,2441216,4096,16384,399360
+ - hsdpa:131072,262144,2441216,4096,16384,399360
+ - hspap:131072,262144,2441216,4096,16384,399360
+ - edge:16384,32768,131072,4096,16384,65536
+ - gprs:4096,8192,24576,4096,8192,24576
+ - 1xrtt:16384,32768,131070,4096,16384,102400
+ - evdo:131072,262144,1048576,4096,16384,524288
+ - lte:524288,1048576,8388608,262144,524288,4194304
+
+
+
+ 524288,2097152,8388608,262144,524288,4194304
+
+
+ 1
+
+
+ 100
+
+
+ 250
+
+
+ 3800
+
+
+ 6
+
+
+ false
+
+
+ 2
+
+
+ false
+
+
+ false
+
+
+
+ - "gsm,11"
+ - "utran,11"
+ - "cdma1x,1"
+ - "hrpd,3"
+ - "ehrpd,12"
+ - "eutran,11"
+
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+ -77
+ -80
+
+ -80
+ -83
+
+
+ true
+
+ true
+
+
diff --git a/overlay/frameworks/base/core/res/res/values/strings.xml b/overlay/frameworks/base/core/res/res/values/strings.xml
new file mode 100644
index 00000000..e1daaadc
--- /dev/null
+++ b/overlay/frameworks/base/core/res/res/values/strings.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+ Pixel
+
diff --git a/overlay/frameworks/base/packages/SystemUI/res/values-mcc440-mnc20/config.xml b/overlay/frameworks/base/packages/SystemUI/res/values-mcc440-mnc20/config.xml
new file mode 100644
index 00000000..f9741d75
--- /dev/null
+++ b/overlay/frameworks/base/packages/SystemUI/res/values-mcc440-mnc20/config.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+ false
+
diff --git a/overlay/packages/apps/Bluetooth/res/values/config.xml b/overlay/packages/apps/Bluetooth/res/values/config.xml
new file mode 100644
index 00000000..9b1b2415
--- /dev/null
+++ b/overlay/packages/apps/Bluetooth/res/values/config.xml
@@ -0,0 +1,18 @@
+
+
+
+ true
+
diff --git a/overlay/packages/apps/Settings/res/raw/face_enroll_introduction_animation.mp4 b/overlay/packages/apps/Settings/res/raw/face_enroll_introduction_animation.mp4
new file mode 100644
index 00000000..03aea2f9
Binary files /dev/null and b/overlay/packages/apps/Settings/res/raw/face_enroll_introduction_animation.mp4 differ
diff --git a/overlay/packages/apps/Settings/res/values-mcc262-mnc01/strings.xml b/overlay/packages/apps/Settings/res/values-mcc262-mnc01/strings.xml
new file mode 100644
index 00000000..cff4d804
--- /dev/null
+++ b/overlay/packages/apps/Settings/res/values-mcc262-mnc01/strings.xml
@@ -0,0 +1,22 @@
+
+
+
+
+ WLAN Call
+
diff --git a/overlay/packages/apps/Settings/res/values/bools.xml b/overlay/packages/apps/Settings/res/values/bools.xml
new file mode 100755
index 00000000..bb937893
--- /dev/null
+++ b/overlay/packages/apps/Settings/res/values/bools.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+ false
+
diff --git a/overlay/packages/apps/Settings/res/values/config.xml b/overlay/packages/apps/Settings/res/values/config.xml
new file mode 100755
index 00000000..c2ac3b4f
--- /dev/null
+++ b/overlay/packages/apps/Settings/res/values/config.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+ true
+
diff --git a/overlay/packages/services/Telephony/res/values/config.xml b/overlay/packages/services/Telephony/res/values/config.xml
new file mode 100644
index 00000000..4072b9e3
--- /dev/null
+++ b/overlay/packages/services/Telephony/res/values/config.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+ true
+
+
+ true
+
+
+ true
+
diff --git a/overlay/packages/services/apps/Bluetooth/res/values/config.xml b/overlay/packages/services/apps/Bluetooth/res/values/config.xml
new file mode 100644
index 00000000..9b1b2415
--- /dev/null
+++ b/overlay/packages/services/apps/Bluetooth/res/values/config.xml
@@ -0,0 +1,18 @@
+
+
+
+ true
+
diff --git a/overlay/packages/services/apps/Settings/res/raw/face_enroll_introduction_animation.mp4 b/overlay/packages/services/apps/Settings/res/raw/face_enroll_introduction_animation.mp4
new file mode 100644
index 00000000..03aea2f9
Binary files /dev/null and b/overlay/packages/services/apps/Settings/res/raw/face_enroll_introduction_animation.mp4 differ
diff --git a/overlay/packages/services/apps/Settings/res/values-mcc262-mnc01/strings.xml b/overlay/packages/services/apps/Settings/res/values-mcc262-mnc01/strings.xml
new file mode 100644
index 00000000..cff4d804
--- /dev/null
+++ b/overlay/packages/services/apps/Settings/res/values-mcc262-mnc01/strings.xml
@@ -0,0 +1,22 @@
+
+
+
+
+ WLAN Call
+
diff --git a/overlay/packages/services/apps/Settings/res/values/bools.xml b/overlay/packages/services/apps/Settings/res/values/bools.xml
new file mode 100755
index 00000000..bb937893
--- /dev/null
+++ b/overlay/packages/services/apps/Settings/res/values/bools.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+ false
+
diff --git a/overlay/packages/services/apps/Settings/res/values/config.xml b/overlay/packages/services/apps/Settings/res/values/config.xml
new file mode 100755
index 00000000..c2ac3b4f
--- /dev/null
+++ b/overlay/packages/services/apps/Settings/res/values/config.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+ true
+
diff --git a/p2p_supplicant_overlay.conf b/p2p_supplicant_overlay.conf
new file mode 100644
index 00000000..d66504cc
--- /dev/null
+++ b/p2p_supplicant_overlay.conf
@@ -0,0 +1,2 @@
+disable_scan_offload=1
+p2p_go_vht=1
diff --git a/pixelstats/Android.bp b/pixelstats/Android.bp
new file mode 100644
index 00000000..d096d40e
--- /dev/null
+++ b/pixelstats/Android.bp
@@ -0,0 +1,36 @@
+//
+// Copyright (C) 2019 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.
+
+cc_binary {
+ name: "pixelstats-vendor",
+ init_rc: ["pixelstats-vendor.sunfish.rc"],
+ srcs: [
+ "service.cpp",
+ ],
+ shared_libs: [
+ "libbase",
+ "libbinder",
+ "libcutils",
+ "libhidlbase",
+ "libhidltransport",
+ "liblog",
+ "libutils",
+ "libpixelstats",
+ ],
+ proprietary: true,
+ static_libs: ["chre_client"],
+ header_libs: ["chre_api"],
+}
+
diff --git a/pixelstats/pixelstats-vendor.sunfish.rc b/pixelstats/pixelstats-vendor.sunfish.rc
new file mode 100644
index 00000000..9410090c
--- /dev/null
+++ b/pixelstats/pixelstats-vendor.sunfish.rc
@@ -0,0 +1,4 @@
+service vendor.pixelstats_vendor /vendor/bin/pixelstats-vendor
+ class hal
+ user system
+ group system
diff --git a/pixelstats/service.cpp b/pixelstats/service.cpp
new file mode 100644
index 00000000..5e8abc55
--- /dev/null
+++ b/pixelstats/service.cpp
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2018 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 "pixelstats"
+
+#include
+#include
+
+#include
+#include
+#include
+
+using android::sp;
+using android::hardware::google::pixel::DropDetect;
+using android::hardware::google::pixel::SysfsCollector;
+using android::hardware::google::pixel::UeventListener;
+
+#define UFSHC_PATH(filename) "/sys/devices/platform/soc/1d84000.ufshc/" #filename
+const struct SysfsCollector::SysfsPaths sysfs_paths = {
+ .SlowioReadCntPath = UFSHC_PATH(slowio_read_cnt),
+ .SlowioWriteCntPath = UFSHC_PATH(slowio_write_cnt),
+ .SlowioUnmapCntPath = UFSHC_PATH(slowio_unmap_cnt),
+ .SlowioSyncCntPath = UFSHC_PATH(slowio_sync_cnt),
+ .CycleCountBinsPath = "/sys/class/power_supply/maxfg/cycle_counts_bins",
+ .ImpedancePath = "/sys/class/misc/msm_cirrus_playback/resistance_left_right",
+ .CodecPath = "", // b/117976641
+};
+
+const char *const kAudioUevent = "/kernel/q6audio/q6voice_uevent";
+
+int main() {
+ LOG(INFO) << "starting PixelStats";
+
+ // b/118713028 Expect failure until drop detect nanoapp is enabled
+ sp dropDetector = DropDetect::start();
+ if (!dropDetector) {
+ LOG(ERROR) << "Unable to launch drop detection";
+ return 1;
+ }
+
+ UeventListener ueventListener(kAudioUevent);
+ std::thread listenThread(&UeventListener::ListenForever, &ueventListener);
+ listenThread.detach();
+
+ SysfsCollector collector(sysfs_paths);
+ collector.collect(); // This blocks forever.
+
+ return 0;
+}
diff --git a/power/hint-data.h b/power/hint-data.h
new file mode 100644
index 00000000..0cb54c24
--- /dev/null
+++ b/power/hint-data.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2012, 2013, 2015, 2017, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* Default use-case hint IDs */
+#define DEFAULT_VIDEO_ENCODE_HINT_ID (0x0A00)
+#define DEFAULT_VIDEO_DECODE_HINT_ID (0x0B00)
+#define DISPLAY_STATE_HINT_ID (0x0C00)
+#define DISPLAY_STATE_HINT_ID_2 (0x0D00)
+#define CAM_PREVIEW_HINT_ID (0x0E00)
+#define SUSTAINED_PERF_HINT_ID (0x0F00)
+#define VR_MODE_HINT_ID (0x1000)
+#define VR_MODE_SUSTAINED_PERF_HINT_ID (0x1001)
+
+#define AOSP_DELTA (0x1200)
+
+#define VSYNC_HINT AOSP_DELTA + POWER_HINT_VSYNC
+#define INTERACTION_HINT AOSP_DELTA + POWER_HINT_INTERACTION
+#define VIDEO_DECODE_HINT AOSP_DELTA + POWER_HINT_VIDEO_DECODE
+#define VIDEO_ENCODE_HINT AOSP_DELTA + POWER_HINT_VIDEO_ENCODE
+#define LOW_POWER_HINT AOSP_DELTA + POWER_HINT_LOW_POWER
+#define SUSTAINED_PERF_HINT AOSP_DELTA + POWER_HINT_SUSTAINED_PERFORMANCE
+#define VR_MODE_HINT AOSP_DELTA + POWER_HINT_VR_MODE
+#define LAUNCH_HINT AOSP_DELTA + POWER_HINT_LAUNCH
+#define DISABLE_TOUCH_HINT AOSP_DELTA + POWER_HINT_DISABLE_TOUCH
+
+#define VR_MODE_SUSTAINED_PERF_HINT (0x1301)
+
+
+struct hint_data {
+ unsigned long hint_id; /* This is our key. */
+ unsigned long perflock_handle;
+};
+
+int hint_compare(struct hint_data *first_hint,
+ struct hint_data *other_hint);
+void hint_dump(struct hint_data *hint);
diff --git a/power/list.h b/power/list.h
new file mode 100644
index 00000000..d68c3df1
--- /dev/null
+++ b/power/list.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+struct list_node {
+ struct list_node *next;
+ void *data;
+ int (*compare)(void *data1, void *data2);
+ void (*dump)(void *data);
+};
+
+int init_list_head(struct list_node *head);
+struct list_node * add_list_node(struct list_node *head, void *data);
+int remove_list_node(struct list_node *head, struct list_node *del_node);
+void dump_list(struct list_node *head);
+struct list_node *find_node(struct list_node *head, void *comparison_data);
diff --git a/power/metadata-defs.h b/power/metadata-defs.h
new file mode 100644
index 00000000..c4649007
--- /dev/null
+++ b/power/metadata-defs.h
@@ -0,0 +1,54 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#define ATTRIBUTE_VALUE_DELIM ('=')
+#define ATTRIBUTE_STRING_DELIM (";")
+
+#define METADATA_PARSING_ERR (-1)
+#define METADATA_PARSING_CONTINUE (0)
+#define METADATA_PARSING_DONE (1)
+
+#define MIN(x,y) (((x)>(y))?(y):(x))
+
+struct video_encode_metadata_t {
+ int hint_id;
+ int state;
+};
+
+struct video_decode_metadata_t {
+ int hint_id;
+ int state;
+};
+
+int parse_metadata(char *metadata, char **metadata_saveptr,
+ char *attribute, int attribute_size, char *value, int value_size);
+int parse_video_encode_metadata(char *metadata,
+ struct video_encode_metadata_t *video_encode_metadata);
+int parse_video_decode_metadata(char *metadata,
+ struct video_decode_metadata_t *video_decode_metadata);
diff --git a/power/performance.h b/power/performance.h
new file mode 100644
index 00000000..b7bf34b2
--- /dev/null
+++ b/power/performance.h
@@ -0,0 +1,265 @@
+/* Copyright (c) 2012, 2014, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define FAILED -1
+#define SUCCESS 0
+#define INDEFINITE_DURATION 0
+
+/* Hints sent to perf HAL from power HAL
+ * These have to be kept in sync with Perf HAL side definitions
+ */
+#define VENDOR_HINT_DISPLAY_OFF 0x00001040
+#define VENDOR_HINT_DISPLAY_ON 0x00001041
+
+enum SCREEN_DISPLAY_TYPE {
+ DISPLAY_OFF = 0x00FF,
+};
+
+enum PWR_CLSP_TYPE {
+ ALL_CPUS_PWR_CLPS_DIS = 0x101,
+};
+
+/* For CPUx min freq, the leftmost byte
+ * represents the CPU and the
+ * rightmost byte represents the frequency
+ * All intermediate frequencies on the
+ * device are supported. The hex value
+ * passed into PerfLock will be multiplied
+ * by 10^5. This frequency or the next
+ * highest frequency available will be set
+ *
+ * For example, if 1.4 Ghz is required on
+ * CPU0, use 0x20E
+ *
+ * If the highest available frequency
+ * on the device is required, use
+ * CPUx_MIN_FREQ_TURBO_MAX
+ * where x represents the CPU
+ */
+enum CPU0_MIN_FREQ_LVL {
+ CPU0_MIN_FREQ_NONTURBO_MAX = 0x20A,
+ CPU0_MIN_FREQ_TURBO_MAX = 0x2FE,
+};
+
+enum CPU1_MIN_FREQ_LVL {
+ CPU1_MIN_FREQ_NONTURBO_MAX = 0x30A,
+ CPU1_MIN_FREQ_TURBO_MAX = 0x3FE,
+};
+
+enum CPU2_MIN_FREQ_LVL {
+ CPU2_MIN_FREQ_NONTURBO_MAX = 0x40A,
+ CPU2_MIN_FREQ_TURBO_MAX = 0x4FE,
+};
+
+enum CPU3_MIN_FREQ_LVL {
+ CPU3_MIN_FREQ_NONTURBO_MAX = 0x50A,
+ CPU3_MIN_FREQ_TURBO_MAX = 0x5FE,
+};
+
+enum CPU0_MAX_FREQ_LVL {
+ CPU0_MAX_FREQ_NONTURBO_MAX = 0x150A,
+};
+
+enum CPU1_MAX_FREQ_LVL {
+ CPU1_MAX_FREQ_NONTURBO_MAX = 0x160A,
+};
+
+enum CPU2_MAX_FREQ_LVL {
+ CPU2_MAX_FREQ_NONTURBO_MAX = 0x170A,
+};
+
+enum CPU3_MAX_FREQ_LVL {
+ CPU3_MAX_FREQ_NONTURBO_MAX = 0x180A,
+};
+
+enum MIN_CPUS_ONLINE_LVL {
+ CPUS_ONLINE_MIN_2 = 0x702,
+ CPUS_ONLINE_MIN_3 = 0x703,
+ CPUS_ONLINE_MIN_4 = 0x704,
+ CPUS_ONLINE_MPD_OVERRIDE = 0x777,
+ CPUS_ONLINE_MAX = 0x7FF,
+};
+
+enum MAX_CPUS_ONLINE_LVL {
+ CPUS_ONLINE_MAX_LIMIT_1 = 0x8FE,
+ CPUS_ONLINE_MAX_LIMIT_2 = 0x8FD,
+ CPUS_ONLINE_MAX_LIMIT_3 = 0x8FC,
+ CPUS_ONLINE_MAX_LIMIT_4 = 0x8FB,
+ CPUS_ONLINE_MAX_LIMIT_MAX = 0x8FB,
+};
+
+enum SAMPLING_RATE_LVL {
+ MS_500 = 0xBCD,
+ MS_50 = 0xBFA,
+ MS_20 = 0xBFD,
+};
+
+enum ONDEMAND_IO_BUSY_LVL {
+ IO_BUSY_OFF = 0xC00,
+ IO_BUSY_ON = 0xC01,
+};
+
+enum ONDEMAND_SAMPLING_DOWN_FACTOR_LVL {
+ SAMPLING_DOWN_FACTOR_1 = 0xD01,
+ SAMPLING_DOWN_FACTOR_4 = 0xD04,
+};
+
+enum INTERACTIVE_TIMER_RATE_LVL {
+ TR_MS_500 = 0xECD,
+ TR_MS_100 = 0xEF5,
+ TR_MS_50 = 0xEFA,
+ TR_MS_30 = 0xEFC,
+ TR_MS_20 = 0xEFD,
+};
+
+/* This timer rate applicable to cpu0
+ across 8939 series chipset */
+enum INTERACTIVE_TIMER_RATE_LVL_CPU0_8939 {
+ TR_MS_CPU0_500 = 0x30CD,
+ TR_MS_CPU0_100 = 0x30F5,
+ TR_MS_CPU0_50 = 0x30FA,
+ TR_MS_CPU0_30 = 0x30FC,
+ TR_MS_CPU0_20 = 0x30FD,
+};
+
+/* This timer rate applicable to cpu4
+ across 8939 series chipset */
+enum INTERACTIVE_TIMER_RATE_LVL_CPU4_8939 {
+ TR_MS_CPU4_500 = 0x3BCD,
+ TR_MS_CPU4_100 = 0x3BF5,
+ TR_MS_CPU4_50 = 0x3BFA,
+ TR_MS_CPU4_30 = 0x3BFC,
+ TR_MS_CPU4_20 = 0x3BFD,
+};
+
+/* This timer rate applicable to big.little arch */
+enum INTERACTIVE_TIMER_RATE_LVL_BIG_LITTLE {
+ BIG_LITTLE_TR_MS_100 = 0x64,
+ BIG_LITTLE_TR_MS_50 = 0x32,
+ BIG_LITTLE_TR_MS_40 = 0x28,
+ BIG_LITTLE_TR_MS_30 = 0x1E,
+ BIG_LITTLE_TR_MS_20 = 0x14,
+};
+
+/* INTERACTIVE opcodes */
+enum INTERACTIVE_OPCODES {
+ INT_OP_CLUSTER0_TIMER_RATE = 0x41424000,
+ INT_OP_CLUSTER1_TIMER_RATE = 0x41424100,
+ INT_OP_CLUSTER0_USE_SCHED_LOAD = 0x41430000,
+ INT_OP_CLUSTER1_USE_SCHED_LOAD = 0x41430100,
+ INT_OP_CLUSTER0_USE_MIGRATION_NOTIF = 0x41434000,
+ INT_OP_CLUSTER1_USE_MIGRATION_NOTIF = 0x41434100,
+ INT_OP_NOTIFY_ON_MIGRATE = 0x4241C000
+};
+
+enum INTERACTIVE_HISPEED_FREQ_LVL {
+ HS_FREQ_1026 = 0xF0A,
+};
+
+enum INTERACTIVE_HISPEED_LOAD_LVL {
+ HISPEED_LOAD_90 = 0x105A,
+};
+
+enum SYNC_FREQ_LVL {
+ SYNC_FREQ_300 = 0x1103,
+ SYNC_FREQ_600 = 0X1106,
+ SYNC_FREQ_384 = 0x1103,
+ SYNC_FREQ_NONTURBO_MAX = 0x110A,
+ SYNC_FREQ_TURBO = 0x110F,
+};
+
+enum OPTIMAL_FREQ_LVL {
+ OPTIMAL_FREQ_300 = 0x1203,
+ OPTIMAL_FREQ_600 = 0x1206,
+ OPTIMAL_FREQ_384 = 0x1203,
+ OPTIMAL_FREQ_NONTURBO_MAX = 0x120A,
+ OPTIMAL_FREQ_TURBO = 0x120F,
+};
+
+enum SCREEN_PWR_CLPS_LVL {
+ PWR_CLPS_DIS = 0x1300,
+ PWR_CLPS_ENA = 0x1301,
+};
+
+enum THREAD_MIGRATION_LVL {
+ THREAD_MIGRATION_SYNC_OFF = 0x1400,
+};
+
+enum INTERACTIVE_IO_BUSY_LVL {
+ INTERACTIVE_IO_BUSY_OFF = 0x1B00,
+ INTERACTIVE_IO_BUSY_ON = 0x1B01,
+};
+
+enum SCHED_BOOST_LVL {
+ SCHED_BOOST_ON = 0x1E01,
+};
+
+enum CPU4_MIN_FREQ_LVL {
+ CPU4_MIN_FREQ_NONTURBO_MAX = 0x1F0A,
+ CPU4_MIN_FREQ_TURBO_MAX = 0x1FFE,
+};
+
+enum CPU5_MIN_FREQ_LVL {
+ CPU5_MIN_FREQ_NONTURBO_MAX = 0x200A,
+ CPU5_MIN_FREQ_TURBO_MAX = 0x20FE,
+};
+
+enum CPU6_MIN_FREQ_LVL {
+ CPU6_MIN_FREQ_NONTURBO_MAX = 0x210A,
+ CPU6_MIN_FREQ_TURBO_MAX = 0x21FE,
+};
+
+enum CPU7_MIN_FREQ_LVL {
+ CPU7_MIN_FREQ_NONTURBO_MAX = 0x220A,
+ CPU7_MIN_FREQ_TURBO_MAX = 0x22FE,
+};
+
+enum CPU4_MAX_FREQ_LVL {
+ CPU4_MAX_FREQ_NONTURBO_MAX = 0x230A,
+};
+
+enum CPU5_MAX_FREQ_LVL {
+ CPU5_MAX_FREQ_NONTURBO_MAX = 0x240A,
+};
+
+enum CPU6_MAX_FREQ_LVL {
+ CPU6_MAX_FREQ_NONTURBO_MAX = 0x250A,
+};
+
+enum CPU7_MAX_FREQ_LVL {
+ CPU7_MAX_FREQ_NONTURBO_MAX = 0x260A,
+};
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/power/power-common.h b/power/power-common.h
new file mode 100644
index 00000000..5ba5e810
--- /dev/null
+++ b/power/power-common.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#define NODE_MAX (64)
+
+#define SCALING_GOVERNOR_PATH "/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor"
+#define DCVS_CPU0_SLACK_MAX_NODE "/sys/module/msm_dcvs/cores/cpu0/slack_time_max_us"
+#define DCVS_CPU0_SLACK_MIN_NODE "/sys/module/msm_dcvs/cores/cpu0/slack_time_min_us"
+#define MPDECISION_SLACK_MAX_NODE "/sys/module/msm_mpdecision/slack_time_max_us"
+#define MPDECISION_SLACK_MIN_NODE "/sys/module/msm_mpdecision/slack_time_min_us"
+#define SCALING_MIN_FREQ "/sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq"
+#define ONDEMAND_GOVERNOR "ondemand"
+#define INTERACTIVE_GOVERNOR "interactive"
+#define MSMDCVS_GOVERNOR "msm-dcvs"
+
+#define HINT_HANDLED (0)
+#define HINT_NONE (-1)
+
+enum CPU_GOV_CHECK {
+ CPU0 = 0,
+ CPU1 = 1,
+ CPU2 = 2,
+ CPU3 = 3
+};
diff --git a/power/powerhintparser.h b/power/powerhintparser.h
new file mode 100644
index 00000000..5f9cbe6f
--- /dev/null
+++ b/power/powerhintparser.h
@@ -0,0 +1,48 @@
+/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __POWERHINTPARSER__
+#define __POWERHINTPARSER__
+
+#define POWERHINT_XML "/vendor/etc/powerhint.xml"
+#define MAX_HINT 6
+#define MAX_PARAM 30
+
+typedef struct perflock_param_t {
+ int type;
+ int numParams;
+ int paramList[MAX_PARAM];//static limit on number of hints - 15
+}perflock_param_t;
+
+static perflock_param_t powerhint[MAX_HINT];
+
+int parsePowerhintXML();
+int *getPowerhint(int, int*);
+
+#endif /* __POWERHINTPARSER__ */
diff --git a/power/utils.h b/power/utils.h
new file mode 100644
index 00000000..4c3dc7fe
--- /dev/null
+++ b/power/utils.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2012-2013,2015-2017, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include
+
+int sysfs_read(char *path, char *s, int num_bytes);
+int sysfs_write(char *path, char *s);
+int get_scaling_governor(char governor[], int size);
+int get_scaling_governor_check_cores(char governor[], int size,int core_num);
+int is_interactive_governor(char*);
+
+void vote_ondemand_io_busy_off();
+void unvote_ondemand_io_busy_off();
+void vote_ondemand_sdf_low();
+void unvote_ondemand_sdf_low();
+void perform_hint_action(int hint_id, int resource_values[],
+ int num_resources);
+void undo_hint_action(int hint_id);
+void release_request(int lock_handle);
+int interaction_with_handle(int lock_handle, int duration, int num_args, int opt_list[]);
+int perf_hint_enable(int hint_id, int duration);
diff --git a/powerhint.json b/powerhint.json
new file mode 100644
index 00000000..1087869e
--- /dev/null
+++ b/powerhint.json
@@ -0,0 +1,650 @@
+{
+ "Nodes": [
+ {
+ "Name": "CPULittleClusterMaxFreq",
+ "Path": "/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq",
+ "Values": [
+ "9999999",
+ "1267200",
+ "1171200",
+ "1113600"
+ ],
+ "DefaultIndex": 0,
+ "ResetOnInit": true
+ },
+ {
+ "Name": "CPULittleClusterMinFreq",
+ "Path": "/sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq",
+ "Values": [
+ "9999999",
+ "1267200",
+ "1171200",
+ "1113600",
+ "300000"
+ ],
+ "ResetOnInit": true
+ },
+ {
+ "Name": "CPUBigClusterMaxFreq",
+ "Path": "/sys/devices/system/cpu/cpu4/cpufreq/scaling_max_freq",
+ "Values": [
+ "9999999",
+ "2016000",
+ "1497600",
+ "1401600"
+ ],
+ "DefaultIndex": 0,
+ "ResetOnInit": true
+ },
+ {
+ "Name": "CPUBigClusterMinFreq",
+ "Path": "/sys/devices/system/cpu/cpu4/cpufreq/scaling_min_freq",
+ "Values": [
+ "9999999",
+ "1497600",
+ "1401600",
+ "1286400",
+ "0"
+ ],
+ "ResetOnInit": true
+ },
+ {
+ "Name": "CPUBigPlusClusterMaxFreq",
+ "Path": "/sys/devices/system/cpu/cpu7/cpufreq/scaling_max_freq",
+ "Values": [
+ "9999999",
+ "2016000",
+ "1497600",
+ "1401600"
+ ],
+ "DefaultIndex": 0,
+ "ResetOnInit": true
+ },
+ {
+ "Name": "CPUBigPlusClusterMinFreq",
+ "Path": "/sys/devices/system/cpu/cpu7/cpufreq/scaling_min_freq",
+ "Values": [
+ "9999999",
+ "1497600",
+ "1401600",
+ "1286400",
+ "0"
+ ],
+ "ResetOnInit": true
+ },
+ {
+ "Name": "GPUMaxFreq",
+ "Path": "/sys/class/kgsl/kgsl-3d0/devfreq/max_freq",
+ "Values": [
+ "600000000",
+ "379650000"
+ ],
+ "DefaultIndex": 0,
+ "ResetOnInit": true
+ },
+ {
+ "Name": "GPUMinFreq",
+ "Path": "/sys/class/kgsl/kgsl-3d0/devfreq/min_freq",
+ "Values": [
+ "553850000",
+ "379650000",
+ "309110000"
+ ],
+ "ResetOnInit": true
+ },
+ {
+ "Name": "GPUBusMinFreq",
+ "Path": "/sys/class/devfreq/soc:qcom,gpubw/min_freq",
+ "Values": [
+ "6881",
+ "5931",
+ "3879",
+ "0"
+ ],
+ "ResetOnInit": true
+ },
+ {
+ "Name": "GPUForceRailOn",
+ "Path": "/sys/class/kgsl/kgsl-3d0/force_rail_on",
+ "Values": [
+ "1",
+ "0"
+ ],
+ "ResetOnInit": true
+ },
+ {
+ "Name": "GPUForceClkOn",
+ "Path": "/sys/class/kgsl/kgsl-3d0/force_clk_on",
+ "Values": [
+ "1",
+ "0"
+ ],
+ "ResetOnInit": true
+ },
+ {
+ "Name": "GPUIdleTimer",
+ "Path": "/sys/class/kgsl/kgsl-3d0/idle_timer",
+ "Values": [
+ "10000",
+ "80"
+ ],
+ "ResetOnInit": true
+ },
+ {
+ "Name": "TASchedtuneBoost",
+ "Path": "/dev/stune/top-app/schedtune.boost",
+ "Values": [
+ "50",
+ "10"
+ ],
+ "ResetOnInit": true
+ },
+ {
+ "Name": "CPUBWHystTriggerCount",
+ "Path": "/sys/class/devfreq/soc:qcom,cpu-cpu-llcc-bw/bw_hwmon/hyst_trigger_count",
+ "Values": [
+ "0",
+ "3"
+ ],
+ "ResetOnInit": true
+ },
+ {
+ "Name": "CPUBWHistMemory",
+ "Path": "/sys/class/devfreq/soc:qcom,cpu-cpu-llcc-bw/bw_hwmon/hist_memory",
+ "Values": [
+ "0",
+ "20"
+ ],
+ "ResetOnInit": true
+ },
+ {
+ "Name": "CPUBWHystLength",
+ "Path": "/sys/class/devfreq/soc:qcom,cpu-cpu-llcc-bw/bw_hwmon/hyst_length",
+ "Values": [
+ "0",
+ "10"
+ ],
+ "ResetOnInit": true
+ },
+ {
+ "Name": "CPUBWSampleMs",
+ "Path": "/sys/class/devfreq/soc:qcom,cpu-cpu-llcc-bw/bw_hwmon/sample_ms",
+ "Values": [
+ "10",
+ "4"
+ ],
+ "ResetOnInit": true
+ },
+ {
+ "Name": "CPUBWIOPercent",
+ "Path": "/sys/class/devfreq/soc:qcom,cpu-cpu-llcc-bw/bw_hwmon/io_percent",
+ "Values": [
+ "80",
+ "34"
+ ],
+ "ResetOnInit": true
+ },
+ {
+ "Name": "CPUBWMinFreq",
+ "Path": "/sys/class/devfreq/soc:qcom,cpu-cpu-llcc-bw/min_freq",
+ "Values": [
+ "11856",
+ "8132",
+ "6149",
+ "2288"
+ ],
+ "ResetOnInit": true
+ },
+ {
+ "Name": "LLCCBWMinFreq",
+ "Path": "/sys/class/devfreq/soc:qcom,cpu-llcc-ddr-bw/min_freq",
+ "Values": [
+ "6881",
+ "2597",
+ "762"
+ ],
+ "ResetOnInit": true
+ },
+ {
+ "Name": "LLCCBWSampleMs",
+ "Path": "/sys/class/devfreq/soc:qcom,cpu-llcc-ddr-bw/bw_hwmon/sample_ms",
+ "Values": [
+ "10",
+ "4"
+ ],
+ "ResetOnInit": true
+ },
+ {
+ "Name": "L3LittleClusterMinFreq",
+ "Path": "/sys/class/devfreq/soc:qcom,cpu0-cpu-l3-lat/min_freq",
+ "Values": [
+ "1440000000",
+ "300000000"
+ ],
+ "ResetOnInit": true
+ },
+ {
+ "Name": "L3BigClusterMinFreq",
+ "Path": "/sys/class/devfreq/soc:qcom,cpu4-cpu-l3-lat/min_freq",
+ "Values": [
+ "1440000000",
+ "300000000"
+ ],
+ "ResetOnInit": true
+ },
+ {
+ "Name": "PMQoSCpuDmaLatency",
+ "Path": "/dev/cpu_dma_latency",
+ "Values": [
+ "44",
+ "100"
+ ],
+ "HoldFd": true
+ },
+ {
+ "Name": "SchedFeatures",
+ "Path": "/sys/kernel/debug/sched_features",
+ "Values": [
+ "NO_ENERGY_AWARE",
+ "ENERGY_AWARE"
+ ],
+ "ResetOnInit": true
+ },
+ {
+ "Name": "PowerHALMainState",
+ "Path": "vendor.powerhal.state",
+ "Values": [
+ "CAMERA_STREAMING",
+ "SUSTAINED_PERFORMANCE",
+ ""
+ ],
+ "Type": "Property"
+ },
+ {
+ "Name": "PowerHALAudioState",
+ "Path": "vendor.powerhal.audio",
+ "Values": [
+ "AUDIO_LOW_LATENCY",
+ ""
+ ],
+ "Type": "Property"
+ },
+ {
+ "Name": "PowerHALRenderingState",
+ "Path": "vendor.powerhal.rendering",
+ "Values": [
+ "EXPENSIVE_RENDERING",
+ ""
+ ],
+ "Type": "Property"
+ }
+ ],
+ "Actions": [
+ {
+ "PowerHint": "SUSTAINED_PERFORMANCE",
+ "Node": "PowerHALMainState",
+ "Duration": 0,
+ "Value": "SUSTAINED_PERFORMANCE"
+ },
+ {
+ "PowerHint": "SUSTAINED_PERFORMANCE",
+ "Node": "CPUBigClusterMaxFreq",
+ "Duration": 0,
+ "Value": "1401600"
+ },
+ {
+ "PowerHint": "SUSTAINED_PERFORMANCE",
+ "Node": "CPUBigPlusClusterMaxFreq",
+ "Duration": 0,
+ "Value": "1401600"
+ },
+ {
+ "PowerHint": "SUSTAINED_PERFORMANCE",
+ "Node": "CPULittleClusterMaxFreq",
+ "Duration": 0,
+ "Value": "1113600"
+ },
+ {
+ "PowerHint": "SUSTAINED_PERFORMANCE",
+ "Node": "GPUMaxFreq",
+ "Duration": 0,
+ "Value": "379650000"
+ },
+ {
+ "PowerHint": "INTERACTION",
+ "Node": "CPUBigPlusClusterMinFreq",
+ "Duration": 0,
+ "Value": "1286400"
+ },
+ {
+ "PowerHint": "INTERACTION",
+ "Node": "CPULittleClusterMinFreq",
+ "Duration": 0,
+ "Value": "1113600"
+ },
+ {
+ "PowerHint": "INTERACTION",
+ "Node": "TASchedtuneBoost",
+ "Duration": 0,
+ "Value": "50"
+ },
+ {
+ "PowerHint": "INTERACTION",
+ "Node": "CPUBWHystTriggerCount",
+ "Duration": 0,
+ "Value": "0"
+ },
+ {
+ "PowerHint": "INTERACTION",
+ "Node": "CPUBWHystLength",
+ "Duration": 0,
+ "Value": "0"
+ },
+ {
+ "PowerHint": "INTERACTION",
+ "Node": "CPUBWHistMemory",
+ "Duration": 0,
+ "Value": "0"
+ },
+ {
+ "PowerHint": "INTERACTION",
+ "Node": "CPUBWMinFreq",
+ "Duration": 0,
+ "Value": "8132"
+ },
+ {
+ "PowerHint": "INTERACTION",
+ "Node": "LLCCBWMinFreq",
+ "Duration": 0,
+ "Value": "2597"
+ },
+ {
+ "PowerHint": "LAUNCH",
+ "Node": "SchedFeatures",
+ "Duration": 5000,
+ "Value": "NO_ENERGY_AWARE"
+ },
+ {
+ "PowerHint": "LAUNCH",
+ "Node": "CPUBigClusterMaxFreq",
+ "Duration": 5000,
+ "Value": "9999999"
+ },
+ {
+ "PowerHint": "LAUNCH",
+ "Node": "CPUBigPlusClusterMaxFreq",
+ "Duration": 5000,
+ "Value": "9999999"
+ },
+ {
+ "PowerHint": "LAUNCH",
+ "Node": "CPUBigClusterMinFreq",
+ "Duration": 5000,
+ "Value": "9999999"
+ },
+ {
+ "PowerHint": "LAUNCH",
+ "Node": "CPUBigPlusClusterMinFreq",
+ "Duration": 5000,
+ "Value": "9999999"
+ },
+ {
+ "PowerHint": "LAUNCH",
+ "Node": "CPULittleClusterMinFreq",
+ "Duration": 5000,
+ "Value": "9999999"
+ },
+ {
+ "PowerHint": "LAUNCH",
+ "Node": "PMQoSCpuDmaLatency",
+ "Duration": 5000,
+ "Value": "44"
+ },
+ {
+ "PowerHint": "LAUNCH",
+ "Node": "CPUBWHystTriggerCount",
+ "Duration": 5000,
+ "Value": "0"
+ },
+ {
+ "PowerHint": "LAUNCH",
+ "Node": "CPUBWHystLength",
+ "Duration": 5000,
+ "Value": "0"
+ },
+ {
+ "PowerHint": "LAUNCH",
+ "Node": "CPUBWHistMemory",
+ "Duration": 5000,
+ "Value": "0"
+ },
+ {
+ "PowerHint": "LAUNCH",
+ "Node": "CPUBWMinFreq",
+ "Duration": 5000,
+ "Value": "11856"
+ },
+ {
+ "PowerHint": "LAUNCH",
+ "Node": "GPUForceClkOn",
+ "Duration": 5000,
+ "Value": "1"
+ },
+ {
+ "PowerHint": "LAUNCH",
+ "Node": "GPUForceRailOn",
+ "Duration": 5000,
+ "Value": "1"
+ },
+ {
+ "PowerHint": "LAUNCH",
+ "Node": "GPUIdleTimer",
+ "Duration": 5000,
+ "Value": "10000"
+ },
+ {
+ "PowerHint": "LAUNCH",
+ "Node": "LLCCBWMinFreq",
+ "Duration": 5000,
+ "Value": "6881"
+ },
+ {
+ "PowerHint": "LAUNCH",
+ "Node": "L3LittleClusterMinFreq",
+ "Duration": 5000,
+ "Value": "1440000000"
+ },
+ {
+ "PowerHint": "LAUNCH",
+ "Node": "L3BigClusterMinFreq",
+ "Duration": 5000,
+ "Value": "1440000000"
+ },
+ {
+ "PowerHint": "CAMERA_LAUNCH",
+ "Node": "SchedFeatures",
+ "Duration": 1000,
+ "Value": "NO_ENERGY_AWARE"
+ },
+ {
+ "PowerHint": "CAMERA_LAUNCH",
+ "Node": "CPUBigClusterMaxFreq",
+ "Duration": 1000,
+ "Value": "9999999"
+ },
+ {
+ "PowerHint": "CAMERA_LAUNCH",
+ "Node": "CPUBigPlusClusterMaxFreq",
+ "Duration": 1000,
+ "Value": "9999999"
+ },
+ {
+ "PowerHint": "CAMERA_LAUNCH",
+ "Node": "CPUBigClusterMinFreq",
+ "Duration": 1000,
+ "Value": "9999999"
+ },
+ {
+ "PowerHint": "CAMERA_LAUNCH",
+ "Node": "CPUBigPlusClusterMinFreq",
+ "Duration": 1000,
+ "Value": "9999999"
+ },
+ {
+ "PowerHint": "CAMERA_LAUNCH",
+ "Node": "CPULittleClusterMaxFreq",
+ "Duration": 1000,
+ "Value": "9999999"
+ },
+ {
+ "PowerHint": "CAMERA_LAUNCH",
+ "Node": "CPULittleClusterMinFreq",
+ "Duration": 1000,
+ "Value": "9999999"
+ },
+ {
+ "PowerHint": "CAMERA_LAUNCH",
+ "Node": "PMQoSCpuDmaLatency",
+ "Duration": 1000,
+ "Value": "44"
+ },
+ {
+ "PowerHint": "CAMERA_STREAMING",
+ "Node": "PowerHALMainState",
+ "Duration": 0,
+ "Value": "CAMERA_STREAMING"
+ },
+ {
+ "PowerHint": "CAMERA_STREAMING",
+ "Node": "CPUBigClusterMaxFreq",
+ "Duration": 0,
+ "Value": "2016000"
+ },
+ {
+ "PowerHint": "CAMERA_STREAMING",
+ "Node": "CPUBigPlusClusterMaxFreq",
+ "Duration": 0,
+ "Value": "2016000"
+ },
+ {
+ "PowerHint": "CAMERA_STREAMING",
+ "Node": "CPUBWSampleMs",
+ "Duration": 0,
+ "Value": "10"
+ },
+ {
+ "PowerHint": "CAMERA_STREAMING",
+ "Node": "CPUBWIOPercent",
+ "Duration": 0,
+ "Value": "80"
+ },
+ {
+ "PowerHint": "CAMERA_STREAMING",
+ "Node": "LLCCBWSampleMs",
+ "Duration": 0,
+ "Value": "10"
+ },
+ {
+ "PowerHint": "CAMERA_SHOT",
+ "Node": "SchedFeatures",
+ "Duration": 1000,
+ "Value": "NO_ENERGY_AWARE"
+ },
+ {
+ "PowerHint": "CAMERA_SHOT",
+ "Node": "CPUBigClusterMaxFreq",
+ "Duration": 1000,
+ "Value": "9999999"
+ },
+ {
+ "PowerHint": "CAMERA_SHOT",
+ "Node": "CPUBigPlusClusterMaxFreq",
+ "Duration": 1000,
+ "Value": "9999999"
+ },
+ {
+ "PowerHint": "CAMERA_SHOT",
+ "Node": "CPUBigClusterMinFreq",
+ "Duration": 1000,
+ "Value": "9999999"
+ },
+ {
+ "PowerHint": "CAMERA_SHOT",
+ "Node": "CPUBigPlusClusterMinFreq",
+ "Duration": 1000,
+ "Value": "9999999"
+ },
+ {
+ "PowerHint": "CAMERA_SHOT",
+ "Node": "CPULittleClusterMaxFreq",
+ "Duration": 1000,
+ "Value": "9999999"
+ },
+ {
+ "PowerHint": "CAMERA_SHOT",
+ "Node": "CPULittleClusterMinFreq",
+ "Duration": 1000,
+ "Value": "9999999"
+ },
+ {
+ "PowerHint": "CAMERA_SHOT",
+ "Node": "PMQoSCpuDmaLatency",
+ "Duration": 1000,
+ "Value": "44"
+ },
+ {
+ "PowerHint": "AUDIO_STREAMING",
+ "Node": "CPUBigClusterMinFreq",
+ "Duration": 2000,
+ "Value": "1497600"
+ },
+ {
+ "PowerHint": "AUDIO_STREAMING",
+ "Node": "CPUBigPlusClusterMinFreq",
+ "Duration": 2000,
+ "Value": "1497600"
+ },
+ {
+ "PowerHint": "AUDIO_STREAMING",
+ "Node": "PMQoSCpuDmaLatency",
+ "Duration": 2000,
+ "Value": "44"
+ },
+ {
+ "PowerHint": "AUDIO_LOW_LATENCY",
+ "Node": "PowerHALAudioState",
+ "Duration": 0,
+ "Value": "AUDIO_LOW_LATENCY"
+ },
+ {
+ "PowerHint": "AUDIO_LOW_LATENCY",
+ "Node": "PMQoSCpuDmaLatency",
+ "Duration": 0,
+ "Value": "44"
+ },
+ {
+ "PowerHint": "EXPENSIVE_RENDERING",
+ "Node": "PowerHALRenderingState",
+ "Duration": 0,
+ "Value": "EXPENSIVE_RENDERING"
+ },
+ {
+ "PowerHint": "EXPENSIVE_RENDERING",
+ "Node": "GPUMinFreq",
+ "Duration": 0,
+ "Value": "553850000"
+ },
+ {
+ "PowerHint": "EXPENSIVE_RENDERING",
+ "Node": "GPUMaxFreq",
+ "Duration": 0,
+ "Value": "600000000"
+ },
+ {
+ "PowerHint": "TPU_BOOST",
+ "Node": "PMQoSCpuDmaLatency",
+ "Duration": 2000,
+ "Value": "44"
+ }
+ ]
+}
diff --git a/powerstats/Android.bp b/powerstats/Android.bp
new file mode 100644
index 00000000..5c4fac6d
--- /dev/null
+++ b/powerstats/Android.bp
@@ -0,0 +1,40 @@
+//
+// Copyright (C) 2018 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.
+cc_binary {
+ name: "android.hardware.power.stats@1.0-service.pixel",
+ relative_install_path: "hw",
+ init_rc: ["android.hardware.power.stats@1.0-service.pixel.rc"],
+ srcs: ["service.cpp"],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+ static_libs: [
+ "libpixelpowerstats",
+ ],
+ shared_libs: [
+ "libbase",
+ "libcutils",
+ "libhidlbase",
+ "libhidltransport",
+ "libfmq",
+ "liblog",
+ "libutils",
+ "android.hardware.power.stats@1.0",
+ "pixelpowerstats_provider_aidl_interface-cpp",
+ "libbinder",
+ ],
+ vendor: true,
+}
diff --git a/powerstats/android.hardware.power.stats@1.0-service.pixel.rc b/powerstats/android.hardware.power.stats@1.0-service.pixel.rc
new file mode 100644
index 00000000..6ba83c28
--- /dev/null
+++ b/powerstats/android.hardware.power.stats@1.0-service.pixel.rc
@@ -0,0 +1,4 @@
+service vendor.power.stats-hal-1-0 /vendor/bin/hw/android.hardware.power.stats@1.0-service.pixel
+ class hal
+ user system
+ group system
diff --git a/powerstats/service.cpp b/powerstats/service.cpp
new file mode 100644
index 00000000..133c9bdf
--- /dev/null
+++ b/powerstats/service.cpp
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2018 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.power.stats@1.0-service.pixel"
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+using android::OK;
+using android::sp;
+using android::status_t;
+
+// libhwbinder:
+using android::hardware::configureRpcThreadpool;
+using android::hardware::joinRpcThreadpool;
+
+// Generated HIDL files
+using android::hardware::power::stats::V1_0::IPowerStats;
+using android::hardware::power::stats::V1_0::PowerEntityInfo;
+using android::hardware::power::stats::V1_0::PowerEntityStateSpace;
+using android::hardware::power::stats::V1_0::PowerEntityType;
+using android::hardware::power::stats::V1_0::implementation::PowerStats;
+
+// Pixel specific
+using android::hardware::google::pixel::powerstats::AidlStateResidencyDataProvider;
+using android::hardware::google::pixel::powerstats::GenericStateResidencyDataProvider;
+using android::hardware::google::pixel::powerstats::PowerEntityConfig;
+using android::hardware::google::pixel::powerstats::StateResidencyConfig;
+using android::hardware::google::pixel::powerstats::WlanStateResidencyDataProvider;
+
+int main(int /* argc */, char ** /* argv */) {
+ ALOGE("power.stats service 1.0 is starting.");
+
+ bool isDebuggable = android::base::GetBoolProperty("ro.debuggable", false);
+
+ PowerStats *service = new PowerStats();
+
+ // Add power entities related to rpmh
+ const uint64_t RPM_CLK = 19200; // RPM runs at 19.2Mhz. Divide by 19200 for msec
+ std::function rpmConvertToMs = [](uint64_t a) { return a / RPM_CLK; };
+ std::vector rpmStateResidencyConfigs = {
+ {.name = "Sleep",
+ .entryCountSupported = true,
+ .entryCountPrefix = "Sleep Count:",
+ .totalTimeSupported = true,
+ .totalTimePrefix = "Sleep Accumulated Duration:",
+ .totalTimeTransform = rpmConvertToMs,
+ .lastEntrySupported = true,
+ .lastEntryPrefix = "Sleep Last Entered At:",
+ .lastEntryTransform = rpmConvertToMs}};
+
+ sp rpmSdp =
+ new GenericStateResidencyDataProvider("/sys/power/rpmh_stats/master_stats");
+
+ uint32_t apssId = service->addPowerEntity("APSS", PowerEntityType::SUBSYSTEM);
+ rpmSdp->addEntity(apssId, PowerEntityConfig("APSS", rpmStateResidencyConfigs));
+
+ uint32_t mpssId = service->addPowerEntity("MPSS", PowerEntityType::SUBSYSTEM);
+ rpmSdp->addEntity(mpssId, PowerEntityConfig("MPSS", rpmStateResidencyConfigs));
+
+ uint32_t adspId = service->addPowerEntity("ADSP", PowerEntityType::SUBSYSTEM);
+ rpmSdp->addEntity(adspId, PowerEntityConfig("ADSP", rpmStateResidencyConfigs));
+
+ uint32_t cdspId = service->addPowerEntity("CDSP", PowerEntityType::SUBSYSTEM);
+ rpmSdp->addEntity(cdspId, PowerEntityConfig("CDSP", rpmStateResidencyConfigs));
+
+ service->addStateResidencyDataProvider(rpmSdp);
+
+ // Add SoC power entity
+ std::vector socStateResidencyConfigs = {
+ {.name = "AOSD",
+ .header = "RPM Mode:aosd",
+ .entryCountSupported = true,
+ .entryCountPrefix = "count:",
+ .totalTimeSupported = true,
+ .totalTimePrefix = "actual last sleep(msec):",
+ .lastEntrySupported = false},
+ {.name = "CXSD",
+ .header = "RPM Mode:cxsd",
+ .entryCountSupported = true,
+ .entryCountPrefix = "count:",
+ .totalTimeSupported = true,
+ .totalTimePrefix = "actual last sleep(msec):",
+ .lastEntrySupported = false}};
+
+ sp socSdp =
+ new GenericStateResidencyDataProvider("/sys/power/system_sleep/stats");
+
+ uint32_t socId = service->addPowerEntity("SoC", PowerEntityType::POWER_DOMAIN);
+ socSdp->addEntity(socId, PowerEntityConfig(socStateResidencyConfigs));
+
+ service->addStateResidencyDataProvider(socSdp);
+
+ if (isDebuggable) {
+ // Add WLAN power entity
+ uint32_t wlanId = service->addPowerEntity("WLAN", PowerEntityType::SUBSYSTEM);
+ sp wlanSdp =
+ new WlanStateResidencyDataProvider(wlanId, "/d/wlan0/power_stats");
+ service->addStateResidencyDataProvider(wlanSdp);
+ }
+
+ // Add Power Entities that require the Aidl data provider
+ sp aidlSdp = new AidlStateResidencyDataProvider();
+ uint32_t citadelId = service->addPowerEntity("Citadel", PowerEntityType::SUBSYSTEM);
+ aidlSdp->addEntity(citadelId, "Citadel", {"Last-Reset", "Active", "Deep-Sleep"});
+
+ auto serviceStatus = android::defaultServiceManager()->addService(
+ android::String16("power.stats-vendor"), aidlSdp);
+ if (serviceStatus != android::OK) {
+ ALOGE("Unable to register power.stats-vendor service %d", serviceStatus);
+ return 1;
+ }
+ sp ps{android::ProcessState::self()}; // Create non-HW binder threadpool
+ ps->startThreadPool();
+
+ service->addStateResidencyDataProvider(aidlSdp);
+
+ // Configure the threadpool
+ configureRpcThreadpool(1, true /*callerWillJoin*/);
+
+ status_t status = service->registerAsService();
+ if (status != OK) {
+ ALOGE("Could not register service for power.stats HAL Iface (%d), exiting.", status);
+ return 1;
+ }
+
+ ALOGI("power.stats service is ready");
+ joinRpcThreadpool();
+
+ // In normal operation, we don't expect the thread pool to exit
+ ALOGE("power.stats service is shutting down");
+ return 1;
+}
diff --git a/product.prop b/product.prop
new file mode 100644
index 00000000..885954a6
--- /dev/null
+++ b/product.prop
@@ -0,0 +1,94 @@
+
+persist.rild.nitz_plmn=
+persist.rild.nitz_long_ons_0=
+persist.rild.nitz_long_ons_1=
+persist.rild.nitz_long_ons_2=
+persist.rild.nitz_long_ons_3=
+persist.rild.nitz_short_ons_0=
+persist.rild.nitz_short_ons_1=
+persist.rild.nitz_short_ons_2=
+persist.rild.nitz_short_ons_3=
+DEVICE_PROVISIONED=1
+
+# Set network mode to Global by default and no DSDS/DSDA
+ro.telephony.default_network=10
+
+debug.sf.hw=1
+debug.gralloc.enable_fb_ubwc=1
+
+# system props for the cne module
+persist.vendor.cne.feature=1
+
+# system props for the MM modules
+media.stagefright.enable-player=true
+media.stagefright.enable-http=true
+media.stagefright.enable-aac=true
+media.stagefright.enable-qcp=true
+media.stagefright.enable-scan=true
+mmp.enable.3g2=true
+media.aac_51_output_enabled=true
+mm.enable.smoothstreaming=true
+#13631487 is decimal sum of supported codecs in AAL
+#codecs:(PARSER_)AAC AC3 AMR_NB AMR_WB ASF AVI DTS FLV 3GP 3G2 MKV MP2PS MP2TS MP3 OGG QCP WAV FLAC AIFF APE DSD
+mm.enable.qcom_parser=13631487
+persist.mm.enable.prefetch=true
+
+# Additional buffers shared between Camera and Video
+vidc.enc.dcvs.extra-buff-count=2
+vidc.enc.disable.pq=1
+
+# system props for the data netmgrd
+persist.data.netmgrd.qos.enable=true
+persist.vendor.data.mode=concurrent
+
+# system props for time-services
+persist.timed.enable=true
+
+# system props for perfetto
+persist.traced.enable=1
+persist.heapprofd.enable=1
+
+# System prop to turn on CdmaLTEPhone always
+telephony.lteOnCdmaDevice=1
+
+# Simulate sdcard on /data/media
+persist.fuse_sdcard=true
+
+# settings to enable Device Orientation Sensors
+ro.qti.sensors.dev_ori=true
+
+# settings to disable sensors not needed
+# all secondary wakeup
+ro.qti.sensors.wu=false
+# unused algorithms
+ro.qti.sdk.sensors.gestures=false
+ro.qti.sensors.amd=false
+ro.qti.sensors.cmc=false
+ro.qti.sensors.facing=false
+ro.qti.sensors.pedometer=false
+ro.qti.sensors.rmd=false
+ro.qti.sensors.scrn_ortn=false
+# use SMGR supplied version
+ro.qti.sensors.step_counter=false
+ro.qti.sensors.step_detector=false
+
+#system prop for RmNet Data
+persist.rmnet.data.enable=true
+persist.data.wda.enable=true
+persist.data.df.dl_mode=5
+persist.data.df.ul_mode=5
+persist.data.df.agg.dl_pkt=10
+persist.data.df.agg.dl_size=4096
+persist.data.df.mux_count=8
+persist.data.df.iwlan_mux=9
+persist.data.df.dev_name=rmnet_usb0
+
+#
+## system props for the data modules
+#
+#ro.use_data_netmgrd=true
+persist.data.netmgrd.qos.enable=true
+persist.data.mode=concurrent
+
+# Disable RescueParty / rescue mode
+persist.sys.disable_rescue=true
diff --git a/recovery.wipe b/recovery.wipe
new file mode 100644
index 00000000..f3b99e0b
--- /dev/null
+++ b/recovery.wipe
@@ -0,0 +1,12 @@
+# All the partitions to be wiped (in order) under recovery.
+/dev/block/bootdevice/by-name/system_a
+/dev/block/bootdevice/by-name/system_b
+/dev/block/bootdevice/by-name/product_a
+/dev/block/bootdevice/by-name/product_b
+/dev/block/bootdevice/by-name/vendor_a
+/dev/block/bootdevice/by-name/vendor_b
+/dev/block/bootdevice/by-name/userdata
+# Wipe the boot partitions last so that all partitions will be wiped
+# correctly even if the wiping process gets interrupted by a force boot.
+/dev/block/bootdevice/by-name/boot_a
+/dev/block/bootdevice/by-name/boot_b
diff --git a/recovery/Android.bp b/recovery/Android.bp
new file mode 100644
index 00000000..e9db8d33
--- /dev/null
+++ b/recovery/Android.bp
@@ -0,0 +1,39 @@
+//
+// Copyright (C) 2018 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.
+//
+
+cc_library_static {
+ name: "librecovery_ui_sunfish",
+ owner: "google",
+ cflags: [
+ "-Wall",
+ "-Wextra",
+ "-Werror",
+ "-pedantic",
+ ],
+ srcs: [
+ "recovery_ui.cpp",
+ ],
+
+ static_libs: [
+ "libbase",
+ "libnos_for_recovery",
+ "libnos_citadel_for_recovery",
+ ],
+
+ shared_libs: [
+ "librecovery_ui",
+ ],
+}
diff --git a/recovery/recovery_ui.cpp b/recovery/recovery_ui.cpp
new file mode 100644
index 00000000..bde386b7
--- /dev/null
+++ b/recovery/recovery_ui.cpp
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2018 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
+#include
+
+#include
+#include
+#include
+
+#include
+#include
+
+namespace android {
+namespace device {
+namespace google {
+namespace sunfish {
+
+namespace {
+
+/** Wipe user data from Titan M. */
+bool WipeTitanM() {
+ // Connect to Titan M
+ ::nos::NuggetClient client;
+ client.Open();
+ if (!client.IsOpen()) {
+ LOG(ERROR) << "Failed to connect to Titan M";
+ return false;
+ }
+
+ // Tell it to wipe user data
+ const uint32_t magicValue = htole32(ERASE_CONFIRMATION);
+ std::vector magic(sizeof(magicValue));
+ memcpy(magic.data(), &magicValue, sizeof(magicValue));
+ const uint32_t status
+ = client.CallApp(APP_ID_NUGGET, NUGGET_PARAM_NUKE_FROM_ORBIT, magic, nullptr);
+ if (status != APP_SUCCESS) {
+ LOG(ERROR) << "Titan M user data wipe failed: " << ::nos::StatusCodeString(status)
+ << " (" << status << ")";
+ return false;
+ }
+
+ LOG(INFO) << "Titan M wipe successful";
+ return true;
+}
+
+} // namespace
+
+class SunfishDevice : public ::Device
+{
+public:
+ SunfishDevice(::ScreenRecoveryUI* const ui) : ::Device(ui) {}
+
+ /** Hook to wipe user data not stored in /data */
+ bool PostWipeData() override {
+ // Try to do everything but report a failure if anything wasn't successful
+ bool totalSuccess = true;
+ ::RecoveryUI* const ui = GetUI();
+
+ ui->Print("Wiping Titan M...\n");
+ if (!WipeTitanM()) {
+ totalSuccess = false;
+ }
+
+ // Extendable to wipe other components
+
+ return totalSuccess;
+ }
+};
+
+} // namespace sunfish
+} // namespace google
+} // namespace device
+} // namespace android
+
+Device *make_device()
+{
+ return new ::android::device::google::sunfish::SunfishDevice(new ::ScreenRecoveryUI);
+}
diff --git a/sec_config b/sec_config
new file mode 100644
index 00000000..9411db20
--- /dev/null
+++ b/sec_config
@@ -0,0 +1,331 @@
+/* IPC Security Config */
+/* :: */
+16:4294967295:1000:1021:1026
+/* :: */
+75:4294967295:1000:1001:3006
+/* :: */
+56:4294967295:1021
+/* Allow SS CTL service to be used by system and net_raw processes */
+43:4294967295:1000:3004
+/* :: */
+71:4294967295:1001
+/* :: */
+50:4294967295:1001
+/* QMI-SLIM service permitted to gps and net_raw */
+55:4294967295:1021
+/* Allow Sensor services to be used by sensor process */
+256:4294967295:1000:1006:1013:1021:1047:3011
+257:4294967295:1000:1006:1013:1021:1047:3011
+258:4294967295:1000:1006:1013:1021:1047:3011
+259:4294967295:1000:1006:1013:1021:1047:3011
+260:4294967295:1000:1006:1013:1021:1047:3011
+261:4294967295:1000:1006:1013:1021:1047:3011
+262:4294967295:1000:1006:1013:1021:1047:3011
+263:4294967295:1000:1006:1013:1021:1047:3011
+264:4294967295:1000:1006:1013:1021:1047:3011
+265:4294967295:1000:1006:1013:1021:1047:3011
+266:4294967295:1000:1006:1013:1021:1047:3011
+267:4294967295:1000:1006:1013:1021:1047:3011
+268:4294967295:1000:1006:1013:1021:1047:3011
+269:4294967295:1000:1006:1013:1021:1047:3011
+270:4294967295:1000:1006:1013:1021:1047:3011
+271:4294967295:1000:1006:1013:1021:1047:3011
+272:4294967295:1000:1006:1013:1021:1047:3011
+273:4294967295:1000:1006:1013:1021:1047:3011
+274:4294967295:1000:1006:1013:1021:1047:3011
+275:4294967295:1000:1006:1013:1021:1047:3011
+276:4294967295:1000:1006:1013:1021:1047:3011
+277:4294967295:1000:1006:1013:1021:1047:3011
+278:4294967295:1000:1006:1013:1021:1047:3011
+279:4294967295:1000:1006:1013:1021:1047:3011
+280:4294967295:1000:1006:1013:1021:1047:3011
+281:4294967295:1000:1006:1013:1021:1047:3011
+282:4294967295:1000:1006:1013:1021:1047:3011
+283:4294967295:1000:1006:1013:1021:1047:3011
+284:4294967295:1000:1006:1013:1021:1047:3011
+285:4294967295:1000:1006:1013:1021:1047:3011
+286:4294967295:1000:1006:1013:1021:1047:3011
+287:4294967295:1000:1006:1013:1021:1047:3011
+288:4294967295:1000:1006:1013:1021:1047:3011
+289:4294967295:1000:1006:1013:1021:1047:3011
+290:4294967295:1000:1006:1013:1021:1047:3011
+291:4294967295:1000:1006:1013:1021:1047:3011
+292:4294967295:1000:1006:1013:1021:1047:3011
+293:4294967295:1000:1006:1013:1021:1047:3011
+294:4294967295:1000:1006:1013:1021:1047:3011
+295:4294967295:1000:1006:1013:1021:1047:3011
+296:4294967295:1000:1006:1013:1021:1047:3011
+297:4294967295:1000:1006:1013:1021:1047:3011
+298:4294967295:1000:1006:1013:1021:1047:3011
+299:4294967295:1000:1006:1013:1021:1047:3011
+300:4294967295:1000:1006:1013:1021:1047:3011
+301:4294967295:1000:1006:1013:1021:1047:3011
+302:4294967295:1000:1006:1013:1021:1047:3011
+303:4294967295:1000:1006:1013:1021:1047:3011
+304:4294967295:1000:1006:1013:1021:1047:3011
+305:4294967295:1000:1006:1013:1021:1047:3011
+306:4294967295:1000:1006:1013:1021:1047:3011
+307:4294967295:1000:1006:1013:1021:1047:3011
+308:4294967295:1000:1006:1013:1021:1047:3011
+309:4294967295:1000:1006:1013:1021:1047:3011
+310:4294967295:1000:1006:1013:1021:1047:3011
+311:4294967295:1000:1006:1013:1021:1047:3011
+312:4294967295:1000:1006:1013:1021:1047:3011
+313:4294967295:1000:1006:1013:1021:1047:3011
+314:4294967295:1000:1006:1013:1021:1047:3011
+315:4294967295:1000:1006:1013:1021:1047:3011
+316:4294967295:1000:1006:1013:1021:1047:3011
+317:4294967295:1000:1006:1013:1021:1047:3011
+318:4294967295:1000:1006:1013:1021:1047:3011
+319:4294967295:1000:1006:1013:1021:1047:3011
+320:4294967295:1000:1006:1013:1021:1047:3011
+321:4294967295:1000:1006:1013:1021:1047:3011
+322:4294967295:1000:1006:1013:1021:1047:3011
+323:4294967295:1000:1006:1013:1021:1047:3011
+324:4294967295:1000:1006:1013:1021:1047:3011
+325:4294967295:1000:1006:1013:1021:1047:3011
+326:4294967295:1000:1006:1013:1021:1047:3011
+327:4294967295:1000:1006:1013:1021:1047:3011
+328:4294967295:1000:1006:1013:1021:1047:3011
+329:4294967295:1000:1006:1013:1021:1047:3011
+330:4294967295:1000:1006:1013:1021:1047:3011
+331:4294967295:1000:1006:1013:1021:1047:3011
+332:4294967295:1000:1006:1013:1021:1047:3011
+333:4294967295:1000:1006:1013:1021:1047:3011
+334:4294967295:1000:1006:1013:1021:1047:3011
+335:4294967295:1000:1006:1013:1021:1047:3011
+336:4294967295:1000:1006:1013:1021:1047:3011
+337:4294967295:1000:1006:1013:1021:1047:3011
+338:4294967295:1000:1006:1013:1021:1047:3011
+339:4294967295:1000:1006:1013:1021:1047:3011
+340:4294967295:1000:1006:1013:1021:1047:3011
+341:4294967295:1000:1006:1013:1021:1047:3011
+342:4294967295:1000:1006:1013:1021:1047:3011
+343:4294967295:1000:1006:1013:1021:1047:3011
+344:4294967295:1000:1006:1013:1021:1047:3011
+345:4294967295:1000:1006:1013:1021:1047:3011
+346:4294967295:1000:1006:1013:1021:1047:3011
+347:4294967295:1000:1006:1013:1021:1047:3011
+348:4294967295:1000:1006:1013:1021:1047:3011
+349:4294967295:1000:1006:1013:1021:1047:3011
+350:4294967295:1000:1006:1013:1021:1047:3011
+351:4294967295:1000:1006:1013:1021:1047:3011
+352:4294967295:1000:1006:1013:1021:1047:3011
+353:4294967295:1000:1006:1013:1021:1047:3011
+354:4294967295:1000:1006:1013:1021:1047:3011
+355:4294967295:1000:1006:1013:1021:1047:3011
+356:4294967295:1000:1006:1013:1021:1047:3011
+357:4294967295:1000:1006:1013:1021:1047:3011
+358:4294967295:1000:1006:1013:1021:1047:3011
+359:4294967295:1000:1006:1013:1021:1047:3011
+360:4294967295:1000:1006:1013:1021:1047:3011
+361:4294967295:1000:1006:1013:1021:1047:3011
+362:4294967295:1000:1006:1013:1021:1047:3011
+363:4294967295:1000:1006:1013:1021:1047:3011
+364:4294967295:1000:1006:1013:1021:1047:3011
+365:4294967295:1000:1006:1013:1021:1047:3011
+366:4294967295:1000:1006:1013:1021:1047:3011
+367:4294967295:1000:1006:1013:1021:1047:3011
+368:4294967295:1000:1006:1013:1021:1047:3011
+369:4294967295:1000:1006:1013:1021:1047:3011
+370:4294967295:1000:1006:1013:1021:1047:3011
+371:4294967295:1000:1006:1013:1021:1047:3011
+372:4294967295:1000:1006:1013:1021:1047:3011
+373:4294967295:1000:1006:1013:1021:1047:3011
+374:4294967295:1000:1006:1013:1021:1047:3011
+375:4294967295:1000:1006:1013:1021:1047:3011
+376:4294967295:1000:1006:1013:1021:1047:3011
+377:4294967295:1000:1006:1013:1021:1047:3011
+378:4294967295:1000:1006:1013:1021:1047:3011
+379:4294967295:1000:1006:1013:1021:1047:3011
+380:4294967295:1000:1006:1013:1021:1047:3011
+381:4294967295:1000:1006:1013:1021:1047:3011
+382:4294967295:1000:1006:1013:1021:1047:3011
+383:4294967295:1000:1006:1013:1021:1047:3011
+384:4294967295:1000:1006:1013:1021:1047:3011
+385:4294967295:1000:1006:1013:1021:1047:3011
+386:4294967295:1000:1006:1013:1021:1047:3011
+387:4294967295:1000:1006:1013:1021:1047:3011
+388:4294967295:1000:1006:1013:1021:1047:3011
+389:4294967295:1000:1006:1013:1021:1047:3011
+390:4294967295:1000:1006:1013:1021:1047:3011
+391:4294967295:1000:1006:1013:1021:1047:3011
+392:4294967295:1000:1006:1013:1021:1047:3011
+393:4294967295:1000:1006:1013:1021:1047:3011
+394:4294967295:1000:1006:1013:1021:1047:3011
+395:4294967295:1000:1006:1013:1021:1047:3011
+396:4294967295:1000:1006:1013:1021:1047:3011
+397:4294967295:1000:1006:1013:1021:1047:3011
+398:4294967295:1000:1006:1013:1021:1047:3011
+399:4294967295:1000:1006:1013:1021:1047:3011
+400:4294967295:1000:1006:1013:1021:1047:3011
+401:4294967295:1000:1006:1013:1021:1047:3011
+402:4294967295:1000:1006:1013:1021:1047:3011
+403:4294967295:1000:1006:1013:1021:1047:3011
+404:4294967295:1000:1006:1013:1021:1047:3011
+405:4294967295:1000:1006:1013:1021:1047:3011
+406:4294967295:1000:1006:1013:1021:1047:3011
+407:4294967295:1000:1006:1013:1021:1047:3011
+408:4294967295:1000:1006:1013:1021:1047:3011
+409:4294967295:1000:1006:1013:1021:1047:3011
+410:4294967295:1000:1006:1013:1021:1047:3011
+411:4294967295:1000:1006:1013:1021:1047:3011
+412:4294967295:1000:1006:1013:1021:1047:3011
+413:4294967295:1000:1006:1013:1021:1047:3011
+414:4294967295:1000:1006:1013:1021:1047:3011
+415:4294967295:1000:1006:1013:1021:1047:3011
+416:4294967295:1000:1006:1013:1021:1047:3011
+417:4294967295:1000:1006:1013:1021:1047:3011
+418:4294967295:1000:1006:1013:1021:1047:3011
+419:4294967295:1000:1006:1013:1021:1047:3011
+420:4294967295:1000:1006:1013:1021:1047:3011
+421:4294967295:1000:1006:1013:1021:1047:3011
+422:4294967295:1000:1006:1013:1021:1047:3011
+423:4294967295:1000:1006:1013:1021:1047:3011
+424:4294967295:1000:1006:1013:1021:1047:3011
+425:4294967295:1000:1006:1013:1021:1047:3011
+426:4294967295:1000:1006:1013:1021:1047:3011
+427:4294967295:1000:1006:1013:1021:1047:3011
+428:4294967295:1000:1006:1013:1021:1047:3011
+429:4294967295:1000:1006:1013:1021:1047:3011
+430:4294967295:1000:1006:1013:1021:1047:3011
+431:4294967295:1000:1006:1013:1021:1047:3011
+432:4294967295:1000:1006:1013:1021:1047:3011
+433:4294967295:1000:1006:1013:1021:1047:3011
+434:4294967295:1000:1006:1013:1021:1047:3011
+435:4294967295:1000:1006:1013:1021:1047:3011
+436:4294967295:1000:1006:1013:1021:1047:3011
+437:4294967295:1000:1006:1013:1021:1047:3011
+438:4294967295:1000:1006:1013:1021:1047:3011
+439:4294967295:1000:1006:1013:1021:1047:3011
+440:4294967295:1000:1006:1013:1021:1047:3011
+441:4294967295:1000:1006:1013:1021:1047:3011
+442:4294967295:1000:1006:1013:1021:1047:3011
+443:4294967295:1000:1006:1013:1021:1047:3011
+444:4294967295:1000:1006:1013:1021:1047:3011
+445:4294967295:1000:1006:1013:1021:1047:3011
+446:4294967295:1000:1006:1013:1021:1047:3011
+447:4294967295:1000:1006:1013:1021:1047:3011
+448:4294967295:1000:1006:1013:1021:1047:3011
+449:4294967295:1000:1006:1013:1021:1047:3011
+450:4294967295:1000:1006:1013:1021:1047:3011
+451:4294967295:1000:1006:1013:1021:1047:3011
+452:4294967295:1000:1006:1013:1021:1047:3011
+453:4294967295:1000:1006:1013:1021:1047:3011
+454:4294967295:1000:1006:1013:1021:1047:3011
+455:4294967295:1000:1006:1013:1021:1047:3011
+456:4294967295:1000:1006:1013:1021:1047:3011
+457:4294967295:1000:1006:1013:1021:1047:3011
+458:4294967295:1000:1006:1013:1021:1047:3011
+459:4294967295:1000:1006:1013:1021:1047:3011
+460:4294967295:1000:1006:1013:1021:1047:3011
+461:4294967295:1000:1006:1013:1021:1047:3011
+462:4294967295:1000:1006:1013:1021:1047:3011
+463:4294967295:1000:1006:1013:1021:1047:3011
+464:4294967295:1000:1006:1013:1021:1047:3011
+465:4294967295:1000:1006:1013:1021:1047:3011
+466:4294967295:1000:1006:1013:1021:1047:3011
+467:4294967295:1000:1006:1013:1021:1047:3011
+468:4294967295:1000:1006:1013:1021:1047:3011
+469:4294967295:1000:1006:1013:1021:1047:3011
+470:4294967295:1000:1006:1013:1021:1047:3011
+471:4294967295:1000:1006:1013:1021:1047:3011
+472:4294967295:1000:1006:1013:1021:1047:3011
+473:4294967295:1000:1006:1013:1021:1047:3011
+474:4294967295:1000:1006:1013:1021:1047:3011
+475:4294967295:1000:1006:1013:1021:1047:3011
+476:4294967295:1000:1006:1013:1021:1047:3011
+477:4294967295:1000:1006:1013:1021:1047:3011
+478:4294967295:1000:1006:1013:1021:1047:3011
+479:4294967295:1000:1006:1013:1021:1047:3011
+480:4294967295:1000:1006:1013:1021:1047:3011
+481:4294967295:1000:1006:1013:1021:1047:3011
+482:4294967295:1000:1006:1013:1021:1047:3011
+483:4294967295:1000:1006:1013:1021:1047:3011
+484:4294967295:1000:1006:1013:1021:1047:3011
+485:4294967295:1000:1006:1013:1021:1047:3011
+486:4294967295:1000:1006:1013:1021:1047:3011
+487:4294967295:1000:1006:1013:1021:1047:3011
+488:4294967295:1000:1006:1013:1021:1047:3011
+489:4294967295:1000:1006:1013:1021:1047:3011
+490:4294967295:1000:1006:1013:1021:1047:3011
+491:4294967295:1000:1006:1013:1021:1047:3011
+492:4294967295:1000:1006:1013:1021:1047:3011
+493:4294967295:1000:1006:1013:1021:1047:3011
+494:4294967295:1000:1006:1013:1021:1047:3011
+495:4294967295:1000:1006:1013:1021:1047:3011
+496:4294967295:1000:1006:1013:1021:1047:3011
+497:4294967295:1000:1006:1013:1021:1047:3011
+498:4294967295:1000:1006:1013:1021:1047:3011
+499:4294967295:1000:1006:1013:1021:1047:3011
+500:4294967295:1000:1006:1013:1021:1047:3011
+501:4294967295:1000:1006:1013:1021:1047:3011
+502:4294967295:1000:1006:1013:1021:1047:3011
+503:4294967295:1000:1006:1013:1021:1047:3011
+504:4294967295:1000:1006:1013:1021:1047:3011
+505:4294967295:1000:1006:1013:1021:1047:3011
+506:4294967295:1000:1006:1013:1021:1047:3011
+507:4294967295:1000:1006:1013:1021:1047:3011
+508:4294967295:1000:1006:1013:1021:1047:3011
+509:4294967295:1000:1006:1013:1021:1047:3011
+510:4294967295:1000:1006:1013:1021:1047:3011
+511:4294967295:1000:1006:1013:1021:1047:3011
+/* Allow RCS service to aquire net_raw permission */
+18:4294967295:1001:3004
+/* Allow RCS service to communicate to IMS QMI Priv Svc*/
+77:4294967295:1001:3003
+/* Allow SSGQMIGD to communicate to SSGCCS service*/
+76:4294967295:1001
+/* Allow cnd to accquire netbind */
+18:4294967295:1000:3003
+/* Allow QMID service to aquire net_raw permission */
+3:4294967295:1001:1021:3004
+2:4294967295:1000:1001:3004
+42:4294967295:1001:3004
+18:4294967295:1001:3004
+9:4294967295:1001:3004
+1:4294967295:1001:3004:1000
+4:4294967295:1001:3004
+7:4294967295:1001:3004
+8:4294967295:1001:3004:1000
+68:4294967295:1001:3004
+/* DPM */
+47:4294967295:1001:3004
+/* Allow communication to some QMI services with radio privileges */
+/* Format is :: */
+/* PBM */
+12:4294967295:1001
+/* WMS */
+5:4294967295:1001
+/* IMS VT */
+32:4294967295:1001
+/* IMSP */
+31:4294967295:1001
+/* PDC */
+36:4294967295:1001
+/* SAR */
+17:4294967295:1001
+/* RFRPE */
+41:4294967295:1001
+/*UIM*/
+11:4294967295:1001
+/*CAT*/
+10:4294967295:1001
+/*IMSA*/
+33:4294967295:1001
+/* CSVT */
+29:4294967295:1001
+/*SERVREG_NOTIF*/
+64:4294967295:1001
+66:4294967295:1001
+73:4294967295:1001
+/*LTE*/
+70:4294967295:1001
+/* Allow Data dpmd to access QMI DFS */
+48:4294967295:1000:3004
+/* DIAG */
+4097:4294967295:2002:2950:3009:2901
+/* :: */
+69:4294967295:1000
+/* :: */
+57:4294967295:1000
diff --git a/seccomp_policy/mediacodec.policy b/seccomp_policy/mediacodec.policy
new file mode 100644
index 00000000..07b7bf70
--- /dev/null
+++ b/seccomp_policy/mediacodec.policy
@@ -0,0 +1,9 @@
+# device specific syscalls
+pselect6: 1
+eventfd2: 1
+sendto: 1
+recvfrom: 1
+_llseek: 1
+sysinfo: 1
+getcwd: 1
+getdents64: 1
diff --git a/sensors.hals.conf b/sensors.hals.conf
new file mode 100644
index 00000000..5f3a14be
--- /dev/null
+++ b/sensors.hals.conf
@@ -0,0 +1 @@
+sensors.ssc.so
diff --git a/sunfish/AndroidBoard.mk b/sunfish/AndroidBoard.mk
new file mode 100644
index 00000000..0099fda6
--- /dev/null
+++ b/sunfish/AndroidBoard.mk
@@ -0,0 +1,56 @@
+LOCAL_PATH := $(call my-dir)
+
+#A/B builds require us to create the mount points at compile time.
+#Just creating it for all cases since it does not hurt.
+FIRMWARE_MOUNT_POINT := $(TARGET_OUT_VENDOR)/firmware_mnt
+ALL_DEFAULT_INSTALLED_MODULES += $(FIRMWARE_MOUNT_POINT)
+
+$(FIRMWARE_MOUNT_POINT):
+ @echo "Creating $(FIRMWARE_MOUNT_POINT)"
+ @mkdir -p $(TARGET_OUT_VENDOR)/firmware_mnt
+
+#----------------------------------------------------------------------
+# Generate persist image (persist.img)
+#----------------------------------------------------------------------
+TARGET_OUT_PERSIST_IMG_PATH := $(PRODUCT_OUT)/persist
+
+INTERNAL_PERSISTIMAGE_FILES := \
+ $(foreach pair,$(PRODUCT_COPY_FILES),\
+ $(if $(filter persist/%,$(call word-colon,2,$(pair))),\
+ $(call word-colon,1,$(pair)):$(PRODUCT_OUT)/$(call word-colon,2,$(pair))))
+
+INSTALLED_PERSISTIMAGE_FILES := $(call copy-many-files,$(INTERNAL_PERSISTIMAGE_FILES))
+INSTALLED_PERSISTIMAGE_TARGET := $(PRODUCT_OUT)/persist.img
+
+$(INSTALLED_PERSISTIMAGE_TARGET): $(MKEXTUSERIMG) $(MAKE_EXT4FS) $(INSTALLED_PERSISTIMAGE_FILES)
+ $(call pretty,"Target persist fs image: $(INSTALLED_PERSISTIMAGE_TARGET)")
+ @mkdir -p $(TARGET_OUT_PERSIST_IMG_PATH)
+ $(hide) PATH=$(HOST_OUT_EXECUTABLES):$${PATH} $(MKEXTUSERIMG) -s $(TARGET_OUT_PERSIST_IMG_PATH) $@ ext4 persist $(BOARD_PERSISTIMAGE_PARTITION_SIZE)
+ $(hide) chmod a+r $@
+ $(hide) $(call assert-max-image-size,$@,$(BOARD_PERSISTIMAGE_PARTITION_SIZE))
+
+ALL_DEFAULT_INSTALLED_MODULES += $(INSTALLED_PERSISTIMAGE_TARGET)
+ALL_MODULES.$(LOCAL_MODULE).INSTALLED += $(INSTALLED_PERSISTIMAGE_TARGET)
+INSTALLED_RADIOIMAGE_TARGET += $(INSTALLED_PERSISTIMAGE_TARGET)
+
+.PHONY: persistimage
+persistimage: $(INSTALLED_PERSISTIMAGE_TARGET)
+
+droidcore: $(INSTALLED_PERSISTIMAGE_TARGET)
+
+
+# copy kernel headers to the build tree
+$(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr: $(wildcard $(PRODUCT_VENDOR_KERNEL_HEADERS)/*)
+ rm -rf $@
+ mkdir -p $@/include
+ cp -a $(PRODUCT_VENDOR_KERNEL_HEADERS)/. $@/include
+
+#----------------------------------------------------------------------
+# build and sign the final stage of bootloader
+#----------------------------------------------------------------------
+.PHONY: aboot
+ifeq ($(USESECIMAGETOOL), true)
+aboot: gensecimage_target gensecimage_install
+else
+aboot: $(INSTALLED_BOOTLOADER_MODULE)
+endif
diff --git a/sunfish/BoardConfig.mk b/sunfish/BoardConfig.mk
new file mode 100644
index 00000000..61c8dc64
--- /dev/null
+++ b/sunfish/BoardConfig.mk
@@ -0,0 +1,21 @@
+#
+# Copyright (C) 2019 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.
+#
+
+TARGET_BOOTLOADER_BOARD_NAME := sunfish
+TARGET_SCREEN_DENSITY := 440
+TARGET_RECOVERY_UI_MARGIN_HEIGHT := 165
+
+include device/google/sunfish/BoardConfig-common.mk
diff --git a/sunfish/init.sunfish.rc b/sunfish/init.sunfish.rc
new file mode 100644
index 00000000..3e7819a2
--- /dev/null
+++ b/sunfish/init.sunfish.rc
@@ -0,0 +1,24 @@
+#
+# 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.
+#
+
+import /vendor/etc/init/hw/init.${ro.boot.hardware.platform}.rc
+
+on property:vendor.all.modules.ready=1
+ chown system system /sys/class/spi_master/spi1/spi1.0/stm_fts_cmd
+
+service vendor.mdm_helper /vendor/bin/mdm_helper
+ class core
+ group system wakelock
diff --git a/sunfish/overlay/frameworks/base/core/res/res/values/config.xml b/sunfish/overlay/frameworks/base/core/res/res/values/config.xml
new file mode 100755
index 00000000..48abfd5c
--- /dev/null
+++ b/sunfish/overlay/frameworks/base/core/res/res/values/config.xml
@@ -0,0 +1,692 @@
+
+
+
+
+
+
+ true
+
+
+ true
+
+
+
+ - "wlan0"
+ - "softap.*"
+
+
+
+ com.android.systemui/com.android.systemui.doze.DozeService
+
+
+ com.google.sensor.single_touch
+
+
+
+ - 1
+ - 2
+ - 3
+ - 4
+ - 8
+ - 12
+ - 20
+ - 33
+ - 55
+ - 90
+ - 148
+ - 245
+ - 403
+ - 665
+ - 1097
+ - 1808
+ - 2981
+ - 5000
+
+
+
+
+ - 10.45935
+ - 29.25559
+ - 34.240692
+ - 37.514347
+ - 40.018696
+ - 46.885098
+ - 51.626434
+ - 58.610405
+ - 66.890915
+ - 77.61644
+ - 90.221886
+ - 105.80314
+ - 126.073845
+ - 154.16931
+ - 191.83717
+ - 240.74442
+ - 294.84857
+ - 348.05453
+ - 399.81
+
+
+
+ 6
+
+
+ 34
+
+
+ true
+
+
+ true
+
+
+ 98
+
+
+
+ 7
+ 6
+ 7
+
+
+ 1
+
+
+ 255
+
+
+
+ - 1
+ - 2
+ - 3
+ - 4
+ - 5
+ - 6
+ - 7
+ - 8
+ - 9
+ - 10
+ - 11
+ - 12
+ - 13
+ - 14
+ - 15
+ - 16
+ - 17
+ - 18
+ - 19
+ - 20
+ - 21
+ - 22
+ - 23
+ - 24
+ - 25
+ - 26
+ - 27
+ - 28
+ - 29
+ - 30
+ - 31
+ - 32
+ - 33
+ - 34
+ - 35
+ - 36
+ - 37
+ - 38
+ - 39
+ - 40
+ - 41
+ - 42
+ - 43
+ - 44
+ - 45
+ - 46
+ - 47
+ - 48
+ - 49
+ - 50
+ - 51
+ - 52
+ - 53
+ - 54
+ - 55
+ - 56
+ - 57
+ - 58
+ - 59
+ - 60
+ - 61
+ - 62
+ - 63
+ - 64
+ - 65
+ - 66
+ - 67
+ - 68
+ - 69
+ - 70
+ - 71
+ - 72
+ - 73
+ - 74
+ - 75
+ - 76
+ - 77
+ - 78
+ - 79
+ - 80
+ - 81
+ - 82
+ - 83
+ - 84
+ - 85
+ - 86
+ - 87
+ - 88
+ - 89
+ - 90
+ - 91
+ - 92
+ - 93
+ - 94
+ - 95
+ - 96
+ - 97
+ - 98
+ - 99
+ - 100
+ - 101
+ - 102
+ - 103
+ - 104
+ - 105
+ - 106
+ - 107
+ - 108
+ - 109
+ - 110
+ - 111
+ - 112
+ - 113
+ - 114
+ - 115
+ - 116
+ - 117
+ - 118
+ - 119
+ - 120
+ - 121
+ - 122
+ - 123
+ - 124
+ - 125
+ - 126
+ - 127
+ - 128
+ - 129
+ - 130
+ - 131
+ - 132
+ - 133
+ - 134
+ - 135
+ - 136
+ - 137
+ - 138
+ - 139
+ - 140
+ - 141
+ - 142
+ - 143
+ - 144
+ - 145
+ - 146
+ - 147
+ - 148
+ - 149
+ - 150
+ - 151
+ - 152
+ - 153
+ - 154
+ - 155
+ - 156
+ - 157
+ - 158
+ - 159
+ - 160
+ - 161
+ - 162
+ - 163
+ - 164
+ - 165
+ - 166
+ - 167
+ - 168
+ - 169
+ - 170
+ - 171
+ - 172
+ - 173
+ - 174
+ - 175
+ - 176
+ - 177
+ - 178
+ - 179
+ - 180
+ - 181
+ - 182
+ - 183
+ - 184
+ - 185
+ - 186
+ - 187
+ - 188
+ - 189
+ - 190
+ - 191
+ - 192
+ - 193
+ - 194
+ - 195
+ - 196
+ - 197
+ - 198
+ - 199
+ - 200
+ - 201
+ - 202
+ - 203
+ - 204
+ - 205
+ - 206
+ - 207
+ - 208
+ - 209
+ - 210
+ - 211
+ - 212
+ - 213
+ - 214
+ - 215
+ - 216
+ - 217
+ - 218
+ - 219
+ - 220
+ - 221
+ - 222
+ - 223
+ - 224
+ - 225
+ - 226
+ - 227
+ - 228
+ - 229
+ - 230
+ - 231
+ - 232
+ - 233
+ - 234
+ - 235
+ - 236
+ - 237
+ - 238
+ - 239
+ - 240
+ - 241
+ - 242
+ - 243
+ - 244
+ - 245
+ - 246
+ - 247
+ - 248
+ - 249
+ - 250
+ - 251
+ - 252
+ - 253
+ - 254
+ - 255
+
+
+
+
+ - 2.0
+ - 3.9
+ - 5.8
+ - 7.6
+ - 9.5
+ - 11.0
+ - 12.5
+ - 14.0
+ - 15.5
+ - 17.0
+ - 18.8
+ - 20.6
+ - 22.4
+ - 24.2
+ - 26.0
+ - 27.6
+ - 29.2
+ - 30.8
+ - 32.4
+ - 34.0
+ - 35.5
+ - 37.0
+ - 38.5
+ - 40.0
+ - 41.5
+ - 43.4
+ - 45.3
+ - 47.2
+ - 49.1
+ - 51.0
+ - 52.5
+ - 53.9
+ - 55.4
+ - 56.8
+ - 58.3
+ - 59.8
+ - 61.3
+ - 62.7
+ - 64.2
+ - 65.7
+ - 67.2
+ - 68.6
+ - 70.1
+ - 71.5
+ - 73.0
+ - 74.5
+ - 75.9
+ - 77.4
+ - 78.8
+ - 80.3
+ - 81.8
+ - 83.3
+ - 84.7
+ - 86.2
+ - 87.7
+ - 89.2
+ - 90.6
+ - 92.1
+ - 93.5
+ - 95.0
+ - 96.7
+ - 98.3
+ - 100.0
+ - 101.6
+ - 103.3
+ - 105.0
+ - 106.6
+ - 108.3
+ - 109.9
+ - 111.6
+ - 113.3
+ - 114.9
+ - 116.6
+ - 118.2
+ - 119.9
+ - 121.6
+ - 123.2
+ - 124.9
+ - 126.5
+ - 128.2
+ - 129.9
+ - 131.6
+ - 133.2
+ - 134.9
+ - 136.6
+ - 138.3
+ - 139.9
+ - 141.6
+ - 143.2
+ - 144.9
+ - 146.6
+ - 148.2
+ - 149.9
+ - 151.5
+ - 153.2
+ - 154.9
+ - 156.5
+ - 158.2
+ - 159.8
+ - 161.5
+ - 162.9
+ - 164.4
+ - 165.8
+ - 167.3
+ - 168.7
+ - 170.1
+ - 171.6
+ - 173.0
+ - 174.5
+ - 175.9
+ - 177.3
+ - 178.8
+ - 180.2
+ - 181.7
+ - 183.1
+ - 184.5
+ - 186.0
+ - 187.4
+ - 188.9
+ - 190.3
+ - 191.7
+ - 193.2
+ - 194.6
+ - 196.1
+ - 197.5
+ - 199.2
+ - 200.9
+ - 202.6
+ - 204.3
+ - 206.0
+ - 207.7
+ - 209.4
+ - 211.1
+ - 212.8
+ - 214.5
+ - 216.2
+ - 217.9
+ - 219.6
+ - 221.3
+ - 223.0
+ - 224.7
+ - 226.4
+ - 228.1
+ - 229.8
+ - 231.5
+ - 233.2
+ - 234.9
+ - 236.6
+ - 238.3
+ - 240.0
+ - 241.6
+ - 243.2
+ - 244.8
+ - 246.4
+ - 248.0
+ - 249.6
+ - 251.2
+ - 252.8
+ - 254.4
+ - 256.0
+ - 257.6
+ - 259.2
+ - 260.8
+ - 262.4
+ - 264.0
+ - 265.6
+ - 267.2
+ - 268.8
+ - 270.4
+ - 272.0
+ - 273.5
+ - 275.1
+ - 276.6
+ - 278.2
+ - 279.7
+ - 281.2
+ - 282.7
+ - 284.3
+ - 285.8
+ - 287.3
+ - 288.8
+ - 290.4
+ - 291.9
+ - 293.5
+ - 295.0
+ - 296.5
+ - 298.0
+ - 299.6
+ - 301.1
+ - 302.6
+ - 304.1
+ - 305.7
+ - 307.2
+ - 308.8
+ - 310.3
+ - 311.8
+ - 313.4
+ - 314.9
+ - 316.5
+ - 318.0
+ - 319.5
+ - 321.0
+ - 322.5
+ - 324.0
+ - 325.5
+ - 327.0
+ - 328.5
+ - 330.0
+ - 331.5
+ - 333.0
+ - 334.5
+ - 336.0
+ - 337.5
+ - 339.0
+ - 340.5
+ - 342.0
+ - 343.5
+ - 345.0
+ - 346.5
+ - 348.0
+ - 349.5
+ - 351.0
+ - 352.5
+ - 354.0
+ - 355.5
+ - 357.0
+ - 358.5
+ - 360.0
+ - 361.5
+ - 363.0
+ - 364.5
+ - 366.0
+ - 367.5
+ - 369.0
+ - 370.5
+ - 372.0
+ - 373.5
+ - 374.9
+ - 376.4
+ - 377.9
+ - 379.4
+ - 380.9
+ - 382.4
+ - 383.9
+ - 385.4
+ - 386.9
+ - 388.4
+ - 389.8
+ - 391.3
+ - 392.8
+ - 394.3
+ - 395.8
+ - 397.3
+ - 398.8
+ - 400.3
+
+
+
+
+ - 0.950352
+ - 1.0
+ - 1.089366
+
+
+
+ 600
+
+
+ true
+
+
+ 140px
+
+
+ 28dp
+
+
diff --git a/sunfish/overlay/frameworks/base/core/res/res/xml/power_profile.xml b/sunfish/overlay/frameworks/base/core/res/res/xml/power_profile.xml
new file mode 100644
index 00000000..bfb9d24b
--- /dev/null
+++ b/sunfish/overlay/frameworks/base/core/res/res/xml/power_profile.xml
@@ -0,0 +1,207 @@
+
+
+
+
+ - 3800
+
+
+
+ 4
+ 3
+ 1
+
+
+
+ - 5.6
+
+ - 5.4
+
+
+ - 8.4
+
+
+ - 2
+
+ - 2.2
+
+ - 2.6
+
+
+
+ 300000
+ 403200
+ 499200
+ 576000
+ 672000
+ 768000
+ 844800
+ 940800
+ 1036800
+ 1113600
+ 1209600
+ 1305600
+ 1382400
+ 1478400
+ 1555200
+ 1632000
+ 1708800
+ 1785600
+
+
+
+ 710400
+ 825600
+ 940800
+ 1056000
+ 1171200
+ 1286400
+ 1401600
+ 1497600
+ 1612800
+ 1708800
+ 1804800
+ 1920000
+ 2016000
+ 2131200
+ 2227200
+ 2323200
+ 2419200
+
+
+
+ 825600
+ 940800
+ 1056000
+ 1171200
+ 1286400
+ 1401600
+ 1497600
+ 1612800
+ 1708800
+ 1804800
+ 1920000
+ 2016000
+ 2131200
+ 2227200
+ 2323200
+ 2419200
+ 2534400
+ 2649600
+ 2745600
+ 2841600
+
+
+
+
+ 39.44
+ 41.34
+ 43.57
+ 45.48
+ 47.20
+ 49.64
+ 51.88
+ 53.34
+ 56.69
+ 58.78
+ 61.41
+ 65.11
+ 67.49
+ 70.61
+ 72.39
+ 75.43
+ 80.21
+ 85.05
+
+
+
+ 50.35
+ 55.12
+ 61.45
+ 69.92
+ 77.48
+ 85.35
+ 95.17
+ 103.26
+ 118.19
+ 132.72
+ 143.83
+ 155.91
+ 190.16
+ 213.11
+ 237.96
+ 266.97
+ 302.04
+
+
+
+ 52.70
+ 55.90
+ 59.73
+ 63.66
+ 67.28
+ 71.66
+ 76.47
+ 80.92
+ 85.81
+ 93.19
+ 98.06
+ 119.08
+ 127.88
+ 129.85
+ 140.37
+ 151.22
+ 160.73
+ 175.50
+ 186.29
+ 223.89
+
+
+
+ - 32
+
+
+ - 98
+
+ - 470
+
+
+ - 240.47
+
+ - 900
+
+
+ - 25
+
+ - 75
+
+
diff --git a/sunfish/overlay/frameworks/base/packages/SystemUI/res/values/config.xml b/sunfish/overlay/frameworks/base/packages/SystemUI/res/values/config.xml
new file mode 100644
index 00000000..d23059ac
--- /dev/null
+++ b/sunfish/overlay/frameworks/base/packages/SystemUI/res/values/config.xml
@@ -0,0 +1,61 @@
+
+
+
+
+
+
+ true
+
+
+ false
+
+
+ com.google.sensor.binned_brightness
+
+
+ true
+
+
+ true
+
+
+
+ - -1
+ - 4
+ - 7
+ - 34
+ - 34
+
+
+
+
+ - -1
+ - 109
+ - 0
+ - 0
+ - 0
+
+
diff --git a/thermal-engine-sunfish.conf b/thermal-engine-sunfish.conf
new file mode 100644
index 00000000..7dfbf68d
--- /dev/null
+++ b/thermal-engine-sunfish.conf
@@ -0,0 +1,58 @@
+[SS-SKIN-HIGH-CPU7]
+algo_type ss
+sampling 2000
+sensor sdm-therm
+device cpu7
+set_point 50000
+set_point_clr 49000
+device_max_limit 2131200
+time_constant 0
+
+[SS-SKIN-MID-CPU7]
+algo_type ss
+sampling 2000
+sensor sdm-therm
+device cpu7
+set_point 52000
+set_point_clr 51000
+device_max_limit 1804800
+time_constant 0
+
+[SS-SKIN-LOW-CPU7]
+algo_type ss
+sampling 2000
+sensor sdm-therm
+device cpu7
+set_point 54000
+set_point_clr 53000
+device_max_limit 1401600
+time_constant 0
+
+[HOT-SKIN-VIRTUAL]
+algo_type virtual
+trip_sensor sdm-therm
+sensors gpuss-0-usr cpuss-0-usr
+list_cnt 2
+weights 1 -1
+set_point 51000
+set_point_clr 49000
+sampling 1000
+math 0
+
+[VIRTUAL-SS-GPU-SKIN]
+algo_type ss
+sensor HOT-SKIN-VIRTUAL
+device gpu
+sampling 1000
+set_point 8000
+set_point_clr 2000
+device_max_limit 427000000
+
+[SKIN-MONITOR]
+algo_type monitor
+sampling 1000
+sensor sdm-therm
+thresholds 56000 58000 100000
+thresholds_clr 54000 56000 99000
+actions cpu0+cpu7+gpu cpu0+cpu7+gpu shutdown
+action_info 940800+1056000+427000000 672000+825600+257000000 1
diff --git a/thermal-engine/thermal_client.h b/thermal-engine/thermal_client.h
new file mode 100644
index 00000000..b41f1394
--- /dev/null
+++ b/thermal-engine/thermal_client.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include
+#ifndef __THERMAL_CLIENT_H__
+#define __THERMAL_CLIENT_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MAX_ACTIONS (32)
+
+/* Enum for supported fields */
+enum supported_fields {
+ UNKNOWN_FIELD = 0x0,
+ DISABLE_FIELD = 0x1,
+ SAMPLING_FIELD = 0x2,
+ THRESHOLDS_FIELD = 0x4,
+ SET_POINT_FIELD = THRESHOLDS_FIELD,
+ THRESHOLDS_CLR_FIELD = 0x8,
+ SET_POINT_CLR_FIELD = THRESHOLDS_CLR_FIELD,
+ ACTION_INFO_FIELD = 0x10,
+ SUPPORTED_FIELD_MAX = 0x20,
+};
+
+enum field_data_type {
+ FIELD_INT = 0,
+ FIELD_STR,
+ FIELD_INT_ARR,
+ FIELD_ARR_STR,
+ FIELD_ARR_INT_ARR,
+ FIELD_MAX
+};
+
+struct action_info_data {
+ int info[MAX_ACTIONS];
+ uint32_t num_actions;
+};
+
+struct field_data {
+ char *field_name;
+ enum field_data_type data_type;
+ uint32_t num_data;
+ void *data;
+};
+
+struct config_instance {
+ char *cfg_desc;
+ char *algo_type;
+ unsigned int fields_mask; /* mask set by client to request to adjust supported fields */
+ uint32_t num_fields;
+ struct field_data *fields;
+};
+
+int thermal_client_config_query(char *algo_type, struct config_instance **configs);
+void thermal_client_config_cleanup(struct config_instance *configs, unsigned int config_size);
+int thermal_client_config_set(struct config_instance *configs, unsigned int config_size);
+
+int thermal_client_register_callback(char *client_name, int (*callback)(int , void *, void *), void *data);
+int thermal_client_request(char *client_name, int req_data);
+void thermal_client_unregister_callback(int client_cb_handle);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __THERMAL_CLIENT_H__ */
diff --git a/thermal_info_config_sunfish.json b/thermal_info_config_sunfish.json
new file mode 100644
index 00000000..59f2d997
--- /dev/null
+++ b/thermal_info_config_sunfish.json
@@ -0,0 +1,346 @@
+{
+ "Sensors":[
+ {
+ "Name":"cpu-0-0-usr",
+ "Type":"CPU",
+ "HotThreshold":[
+ "NAN",
+ "NAN",
+ "NAN",
+ 95.0,
+ "NAN",
+ "NAN",
+ 125.0
+ ],
+ "VrThreshold":"NAN",
+ "Multiplier":0.001
+ },
+ {
+ "Name":"cpu-0-1-usr",
+ "Type":"CPU",
+ "HotThreshold":[
+ "NAN",
+ "NAN",
+ "NAN",
+ 95.0,
+ "NAN",
+ "NAN",
+ 125.0
+ ],
+ "VrThreshold":"NAN",
+ "Multiplier":0.001
+ },
+ {
+ "Name":"cpu-0-2-usr",
+ "Type":"CPU",
+ "HotThreshold":[
+ "NAN",
+ "NAN",
+ "NAN",
+ 95.0,
+ "NAN",
+ "NAN",
+ 125.0
+ ],
+ "VrThreshold":"NAN",
+ "Multiplier":0.001
+ },
+ {
+ "Name":"cpu-0-3-usr",
+ "Type":"CPU",
+ "HotThreshold":[
+ "NAN",
+ "NAN",
+ "NAN",
+ 95.0,
+ "NAN",
+ "NAN",
+ 125.0
+ ],
+ "VrThreshold":"NAN",
+ "Multiplier":0.001
+ },
+ {
+ "Name":"cpu-1-0-usr",
+ "Type":"CPU",
+ "HotThreshold":[
+ "NAN",
+ "NAN",
+ "NAN",
+ 95.0,
+ "NAN",
+ "NAN",
+ 125.0
+ ],
+ "VrThreshold":"NAN",
+ "Multiplier":0.001
+ },
+ {
+ "Name":"cpu-1-1-usr",
+ "Type":"CPU",
+ "HotThreshold":[
+ "NAN",
+ "NAN",
+ "NAN",
+ 95.0,
+ "NAN",
+ "NAN",
+ 125.0
+ ],
+ "VrThreshold":"NAN",
+ "Multiplier":0.001
+ },
+ {
+ "Name":"cpu-1-2-usr",
+ "Type":"CPU",
+ "HotThreshold":[
+ "NAN",
+ "NAN",
+ "NAN",
+ 95.0,
+ "NAN",
+ "NAN",
+ 125.0
+ ],
+ "VrThreshold":"NAN",
+ "Multiplier":0.001
+ },
+ {
+ "Name":"cpu-1-3-usr",
+ "Type":"CPU",
+ "HotThreshold":[
+ "NAN",
+ "NAN",
+ "NAN",
+ 95.0,
+ "NAN",
+ "NAN",
+ 125.0
+ ],
+ "VrThreshold":"NAN",
+ "Multiplier":0.001
+ },
+ {
+ "Name":"gpuss-0-usr",
+ "Type":"GPU",
+ "HotThreshold":[
+ "NAN",
+ "NAN",
+ "NAN",
+ 95.0,
+ "NAN",
+ "NAN",
+ 125.0
+ ],
+ "VrThreshold":"NAN",
+ "Multiplier":0.001
+ },
+ {
+ "Name":"gpuss-1-usr",
+ "Type":"GPU",
+ "HotThreshold":[
+ "NAN",
+ "NAN",
+ "NAN",
+ 95.0,
+ "NAN",
+ "NAN",
+ 125.0
+ ],
+ "VrThreshold":"NAN",
+ "Multiplier":0.001
+ },
+ {
+ "Name":"battery",
+ "Type":"BATTERY",
+ "HotThreshold":[
+ "NAN",
+ "NAN",
+ "NAN",
+ "NAN",
+ "NAN",
+ "NAN",
+ 60.0
+ ],
+ "VrThreshold":"NAN",
+ "Multiplier":0.001
+ },
+ {
+ "Name":"usbc-therm-monitor",
+ "Type":"USB_PORT",
+ "HotThreshold":[
+ "NAN",
+ "NAN",
+ "NAN",
+ "NAN",
+ "NAN",
+ "60.0",
+ "NAN"
+ ],
+ "HotHysteresis":[
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 5.0,
+ 0.0
+ ],
+ "VrThreshold":"NAN",
+ "Multiplier":0.001,
+ "Monitor":true
+ },
+ {
+ "Name":"sdm-therm-monitor",
+ "Type":"SKIN",
+ "HotThreshold":[
+ "NAN",
+ 40.0,
+ 44.0,
+ 46.0,
+ 48.0,
+ 61.0,
+ 95.0
+ ],
+ "HotHysteresis":[
+ 0.0,
+ 1.9,
+ 1.9,
+ 1.9,
+ 1.9,
+ 1.9,
+ 1.9
+ ],
+ "VrThreshold":"NAN",
+ "Multiplier":0.001,
+ "Monitor":true
+ },
+ {
+ "Name":"abh-therm",
+ "Type":"UNKNOWN",
+ "HotThreshold":[
+ "NAN",
+ "NAN",
+ "NAN",
+ "NAN",
+ "NAN",
+ "NAN",
+ "NAN"
+ ],
+ "VrThreshold":"NAN",
+ "Multiplier":0.001
+ },
+ {
+ "Name":"xo-therm",
+ "Type":"UNKNOWN",
+ "HotThreshold":[
+ "NAN",
+ "NAN",
+ "NAN",
+ "NAN",
+ "NAN",
+ "NAN",
+ "NAN"
+ ],
+ "VrThreshold":"NAN",
+ "Multiplier":0.001
+ },
+ {
+ "Name":"rcam-therm",
+ "Type":"UNKNOWN",
+ "HotThreshold":[
+ "NAN",
+ "NAN",
+ "NAN",
+ "NAN",
+ "NAN",
+ "NAN",
+ "NAN"
+ ],
+ "VrThreshold":"NAN",
+ "Multiplier":0.001
+ },
+ {
+ "Name":"btn-therm",
+ "Type":"UNKNOWN",
+ "HotThreshold":[
+ "NAN",
+ "NAN",
+ "NAN",
+ "NAN",
+ "NAN",
+ "NAN",
+ "NAN"
+ ],
+ "VrThreshold":"NAN",
+ "Multiplier":0.001
+ },
+ {
+ "Name":"qtm-left-therm",
+ "Type":"POWER_AMPLIFIER",
+ "HotThreshold":[
+ "NAN",
+ "NAN",
+ "NAN",
+ "NAN",
+ "NAN",
+ "NAN",
+ "NAN"
+ ],
+ "VrThreshold":"NAN",
+ "Multiplier":0.001
+ },
+ {
+ "Name":"chg-therm",
+ "Type":"UNKNOWN",
+ "HotThreshold":[
+ "NAN",
+ "NAN",
+ "NAN",
+ "NAN",
+ "NAN",
+ "NAN",
+ "NAN"
+ ],
+ "VrThreshold":"NAN",
+ "Multiplier":0.001
+ },
+ {
+ "Name":"disp-therm",
+ "Type":"UNKNOWN",
+ "HotThreshold":[
+ "NAN",
+ "NAN",
+ "NAN",
+ "NAN",
+ "NAN",
+ "NAN",
+ "NAN"
+ ],
+ "VrThreshold":"NAN",
+ "Multiplier":0.001
+ }
+ ],
+ "CoolingDevices":[
+ {
+ "Name":"thermal-cpufreq-0",
+ "Type":"CPU"
+ },
+ {
+ "Name":"thermal-cpufreq-4",
+ "Type":"CPU"
+ },
+ {
+ "Name":"thermal-devfreq-0",
+ "Type":"GPU"
+ },
+ {
+ "Name":"cx",
+ "Type":"COMPONENT"
+ },
+ {
+ "Name":"ebi",
+ "Type":"COMPONENT"
+ }
+ ]
+}
diff --git a/ueventd.rc b/ueventd.rc
new file mode 100644
index 00000000..03db70e5
--- /dev/null
+++ b/ueventd.rc
@@ -0,0 +1,135 @@
+#
+# Copyright (C) 2018 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.
+#
+
+# The modem image is mounted at /vendor/firmware_mnt
+firmware_directories /vendor/firmware_mnt/image/
+
+# the DIAG device node is not world writable/readable.
+/dev/diag 0660 system diag
+
+/dev/wlan 0666 system system
+/dev/kgsl-3d0 0666 system system
+/dev/ion 0664 system system
+/dev/rtc0 0660 system system
+/dev/smd7 0660 bluetooth bluetooth
+/dev/ipa 0660 system radio
+/dev/wwan_ioctl 0660 system radio
+/dev/ipaNatTable 0660 system radio
+/dev/rmnet_ctrl 0660 usb usb
+/dev/ipa_odl_ctl 0660 radio radio
+/dev/ipa_adpl 0660 system oem_2905
+
+#permissions for CSVT
+/dev/smd11 0660 radio radio
+
+/dev/smdcntl8 0640 radio radio
+/dev/at_usb0 0640 radio radio
+/dev/at_mdm0 0640 radio radio
+
+/dev/video* 0660 system camera
+/dev/media* 0660 system camera
+/dev/v4l-subdev* 0660 system camera
+
+/dev/qseecom 0660 system drmrpc
+/dev/qsee_ipc_irq_spss 0660 system drmrpc
+/dev/seemplog 0660 system system
+/dev/spcom 0660 system system
+/dev/sp_kernel 0660 system system
+/dev/sp_ssr 0660 system system
+/dev/sp_keymaster 0660 system system
+/dev/sec_nvm_* 0660 system system
+
+/dev/jpeg0 0660 system camera
+/dev/adsprpc-smd 0664 system system
+/dev/adsprpc-smd-secure 0644 system system
+
+/dev/hw_random 0600 root root
+/dev/sdsprpc-smd 0660 system system
+
+/dev/wcd-dsp-glink 0660 system audio
+/dev/wcd_dsp0_control 0660 system audio
+/dev/wcd-spi-ac-client 0660 system audio
+/dev/iaxxx-odsp-celldrv 0660 system audio
+/dev/tunnel0 0660 system audio
+
+/dev/msm_qcelp 0660 system audio
+/dev/msm_evrc 0660 system audio
+/dev/msm_wma 0660 system audio
+/dev/msm_wmapro 0660 system audio
+/dev/msm_alac 0660 system audio
+/dev/msm_ape 0660 system audio
+/dev/msm_amrnb 0660 system audio
+/dev/msm_amrwb 0660 system audio
+/dev/msm_amrwbplus 0660 system audio
+/dev/msm_aac 0660 system audio
+/dev/msm_mp3* 0660 system audio
+/dev/msm_multi_aac 0660 system audio
+/dev/msm_aac_in 0660 system audio
+/dev/msm_qcelp_in 0660 system audio
+/dev/msm_evrc_in 0660 system audio
+/dev/msm_amrnb_in 0640 system audio
+/dev/msm_a2dp_in 0660 system audio
+/dev/msm_ac3 0660 system audio
+/dev/msm_audio_cal 0660 system audio
+/dev/msm_hweffects 0660 system audio
+/dev/msm_rtac 0660 system audio
+/dev/msm_cirrus_playback 0660 system audio
+
+/dev/i2c-5 0660 media media
+/dev/avtimer 0660 system audio
+
+/dev/uio0 0660 system system
+/dev/uio1 0660 system system
+
+# SSR devices
+/dev/subsys_* 0640 system system
+
+# Ramdump devices
+/dev/ramdump_* 0640 system system
+
+# Citadel
+/dev/citadel0 0660 hsm hsm
+
+# Storage: for factory reset protection feature
+/dev/block/platform/soc/1d84000.ufshc/by-name/frp 0660 system system
+
+# fuel gauge history
+/dev/maxfg_history 0644 system system
+
+# BT
+/dev/ttyMSM0 0600 bluetooth bluetooth
+/dev/ttyHS0 0660 bluetooth net_bt
+/dev/btpower 0660 bluetooth net_bt
+
+# NFC
+/dev/st21nfc 0660 nfc nfc
+
+#eSE device
+/dev/st54j_se 0660 secure_element secure_element
+
+# fpc fingerprint
+/sys/devices/platform/soc/soc:fp_fpc* irq 0600 system system
+/sys/devices/platform/soc/soc:fp_fpc* wakeup_enable 0200 system system
+/sys/devices/platform/soc/soc:fp_fpc* hw_reset 0600 system system
+
+# IPU
+/dev/ipu 0666 cameraserver camera
+
+# AB DRAM
+/dev/ab-dram 0666 cameraserver camera
+
+# ABC PCIE DMA
+/dev/abc-pcie-dma 0666 cameraserver camera
diff --git a/uinput-fpc.idc b/uinput-fpc.idc
new file mode 100644
index 00000000..526d0e8c
--- /dev/null
+++ b/uinput-fpc.idc
@@ -0,0 +1,20 @@
+# 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.
+
+#
+# Fingerprint navigation configuration file
+#
+keyboard.orientationAware = 1
+keyboard.builtIn = 1
+
diff --git a/uinput-fpc.kl b/uinput-fpc.kl
new file mode 100644
index 00000000..c8f0acd3
--- /dev/null
+++ b/uinput-fpc.kl
@@ -0,0 +1,4 @@
+key 106 SYSTEM_NAVIGATION_LEFT
+key 108 SYSTEM_NAVIGATION_DOWN
+key 103 SYSTEM_NAVIGATION_UP
+key 105 SYSTEM_NAVIGATION_RIGHT
diff --git a/usb/.clang-format b/usb/.clang-format
new file mode 100644
index 00000000..5d8d909a
--- /dev/null
+++ b/usb/.clang-format
@@ -0,0 +1,14 @@
+BasedOnStyle: Google
+AccessModifierOffset: -2
+AllowShortFunctionsOnASingleLine: Inline
+ColumnLimit: 99
+CommentPragmas: NOLINT:.*
+DerivePointerAlignment: false
+IndentWidth: 4
+PointerAlignment: Right
+TabWidth: 4
+UseTab: Never
+PenaltyExcessCharacter: 32
+AllowShortIfStatementsOnASingleLine: false
+SpacesBeforeTrailingComments: 2
+
diff --git a/usb/Android.bp b/usb/Android.bp
new file mode 100644
index 00000000..01eb6df3
--- /dev/null
+++ b/usb/Android.bp
@@ -0,0 +1,36 @@
+//
+// Copyright (C) 2018 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.
+
+cc_binary {
+ name: "android.hardware.usb@1.2-service.sunfish",
+ relative_install_path: "hw",
+ init_rc: ["android.hardware.usb@1.2-service.sunfish.rc"],
+ srcs: ["service.cpp", "Usb.cpp", "UsbGadget.cpp"],
+ shared_libs: [
+ "android.hardware.usb@1.0",
+ "android.hardware.usb@1.1",
+ "android.hardware.usb@1.2",
+ "android.hardware.usb.gadget@1.0",
+ "libbase",
+ "libcutils",
+ "libhardware",
+ "libhidlbase",
+ "libhidltransport",
+ "liblog",
+ "libutils",
+ ],
+ static_libs: ["libpixelusb"],
+ proprietary: true,
+}
diff --git a/usb/Usb.cpp b/usb/Usb.cpp
new file mode 100644
index 00000000..099e9256
--- /dev/null
+++ b/usb/Usb.cpp
@@ -0,0 +1,785 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "android.hardware.usb@1.2-service.sunfish"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+#include "Usb.h"
+
+namespace android {
+namespace hardware {
+namespace usb {
+namespace V1_2 {
+namespace implementation {
+
+// Set by the signal handler to destroy the thread
+volatile bool destroyThread;
+
+constexpr char kEnabledPath[] = "/sys/class/power_supply/usb/moisture_detection_enabled";
+constexpr char kDetectedPath[] = "/sys/class/power_supply/usb/moisture_detected";
+
+void queryVersionHelper(android::hardware::usb::V1_2::implementation::Usb *usb,
+ hidl_vec *currentPortStatus_1_2);
+
+int32_t readFile(const std::string &filename, std::string *contents) {
+ FILE *fp;
+ ssize_t read = 0;
+ char *line = NULL;
+ size_t len = 0;
+
+ fp = fopen(filename.c_str(), "r");
+ if (fp != NULL) {
+ if ((read = getline(&line, &len, fp)) != -1) {
+ char *pos;
+ if ((pos = strchr(line, '\n')) != NULL)
+ *pos = '\0';
+ *contents = line;
+ }
+ free(line);
+ fclose(fp);
+ return 0;
+ } else {
+ ALOGE("fopen failed");
+ }
+
+ return -1;
+}
+
+int32_t writeFile(const std::string &filename, const std::string &contents) {
+ FILE *fp;
+ std::string written;
+
+ fp = fopen(filename.c_str(), "w");
+ if (fp != NULL) {
+ // FAILURE RETRY
+ int ret = fputs(contents.c_str(), fp);
+ fclose(fp);
+ if ((ret != EOF) && !readFile(filename, &written) && written == contents)
+ return 0;
+ }
+ return -1;
+}
+
+Status queryMoistureDetectionStatus(hidl_vec *currentPortStatus_1_2) {
+ std::string enabled, status;
+
+ (*currentPortStatus_1_2)[0].supportedContaminantProtectionModes = 0;
+ (*currentPortStatus_1_2)[0].supportedContaminantProtectionModes |=
+ ContaminantProtectionMode::FORCE_SINK;
+ (*currentPortStatus_1_2)[0].contaminantProtectionStatus = ContaminantProtectionStatus::NONE;
+ (*currentPortStatus_1_2)[0].contaminantDetectionStatus = ContaminantDetectionStatus::DISABLED;
+ (*currentPortStatus_1_2)[0].supportsEnableContaminantPresenceDetection = true;
+ (*currentPortStatus_1_2)[0].supportsEnableContaminantPresenceProtection = false;
+
+ if (readFile(kEnabledPath, &enabled)) {
+ ALOGE("Failed to open moisture_detection_enabled");
+ return Status::ERROR;
+ }
+
+ if (enabled == "1") {
+ if (readFile(kDetectedPath, &status)) {
+ ALOGE("Failed to open moisture_detected");
+ return Status::ERROR;
+ }
+ if (status == "1") {
+ (*currentPortStatus_1_2)[0].contaminantDetectionStatus =
+ ContaminantDetectionStatus::DETECTED;
+ (*currentPortStatus_1_2)[0].contaminantProtectionStatus =
+ ContaminantProtectionStatus::FORCE_SINK;
+ } else
+ (*currentPortStatus_1_2)[0].contaminantDetectionStatus =
+ ContaminantDetectionStatus::NOT_DETECTED;
+ }
+
+ ALOGI("ContaminantDetectionStatus:%d ContaminantProtectionStatus:%d",
+ (*currentPortStatus_1_2)[0].contaminantDetectionStatus,
+ (*currentPortStatus_1_2)[0].contaminantProtectionStatus);
+
+ return Status::SUCCESS;
+}
+
+Return Usb::enableContaminantPresenceDetection(const hidl_string & /*portName*/,
+ bool enable) {
+ writeFile(kEnabledPath, enable ? "1" : "0");
+ hidl_vec currentPortStatus_1_2;
+
+ queryVersionHelper(this, ¤tPortStatus_1_2);
+ return Void();
+}
+
+Return Usb::enableContaminantPresenceProtection(const hidl_string & /*portName*/,
+ bool /*enable*/) {
+ hidl_vec currentPortStatus_1_2;
+
+ queryVersionHelper(this, ¤tPortStatus_1_2);
+ return Void();
+}
+
+std::string appendRoleNodeHelper(const std::string &portName, PortRoleType type) {
+ std::string node("/sys/class/typec/" + portName);
+
+ switch (type) {
+ case PortRoleType::DATA_ROLE:
+ return node + "/data_role";
+ case PortRoleType::POWER_ROLE:
+ return node + "/power_role";
+ case PortRoleType::MODE:
+ return node + "/port_type";
+ default:
+ return "";
+ }
+}
+
+std::string convertRoletoString(PortRole role) {
+ if (role.type == PortRoleType::POWER_ROLE) {
+ if (role.role == static_cast(PortPowerRole::SOURCE))
+ return "source";
+ else if (role.role == static_cast(PortPowerRole::SINK))
+ return "sink";
+ } else if (role.type == PortRoleType::DATA_ROLE) {
+ if (role.role == static_cast(PortDataRole::HOST))
+ return "host";
+ if (role.role == static_cast(PortDataRole::DEVICE))
+ return "device";
+ } else if (role.type == PortRoleType::MODE) {
+ if (role.role == static_cast(PortMode_1_1::UFP))
+ return "sink";
+ if (role.role == static_cast(PortMode_1_1::DFP))
+ return "source";
+ }
+ return "none";
+}
+
+void extractRole(std::string *roleName) {
+ std::size_t first, last;
+
+ first = roleName->find("[");
+ last = roleName->find("]");
+
+ if (first != std::string::npos && last != std::string::npos) {
+ *roleName = roleName->substr(first + 1, last - first - 1);
+ }
+}
+
+void switchToDrp(const std::string &portName) {
+ std::string filename = appendRoleNodeHelper(std::string(portName.c_str()), PortRoleType::MODE);
+ FILE *fp;
+
+ if (filename != "") {
+ fp = fopen(filename.c_str(), "w");
+ if (fp != NULL) {
+ int ret = fputs("dual", fp);
+ fclose(fp);
+ if (ret == EOF)
+ ALOGE("Fatal: Error while switching back to drp");
+ } else {
+ ALOGE("Fatal: Cannot open file to switch back to drp");
+ }
+ } else {
+ ALOGE("Fatal: invalid node type");
+ }
+}
+
+bool switchMode(const hidl_string &portName, const PortRole &newRole, struct Usb *usb) {
+ std::string filename = appendRoleNodeHelper(std::string(portName.c_str()), newRole.type);
+ std::string written;
+ FILE *fp;
+ bool roleSwitch = false;
+
+ if (filename == "") {
+ ALOGE("Fatal: invalid node type");
+ return false;
+ }
+
+ fp = fopen(filename.c_str(), "w");
+ if (fp != NULL) {
+ // Hold the lock here to prevent loosing connected signals
+ // as once the file is written the partner added signal
+ // can arrive anytime.
+ pthread_mutex_lock(&usb->mPartnerLock);
+ usb->mPartnerUp = false;
+ int ret = fputs(convertRoletoString(newRole).c_str(), fp);
+ fclose(fp);
+
+ if (ret != EOF) {
+ struct timespec to;
+ struct timespec now;
+
+ wait_again:
+ clock_gettime(CLOCK_MONOTONIC, &now);
+ to.tv_sec = now.tv_sec + PORT_TYPE_TIMEOUT;
+ to.tv_nsec = now.tv_nsec;
+
+ int err = pthread_cond_timedwait(&usb->mPartnerCV, &usb->mPartnerLock, &to);
+ // There are no uevent signals which implies role swap timed out.
+ if (err == ETIMEDOUT) {
+ ALOGI("uevents wait timedout");
+ // Sanity check.
+ } else if (!usb->mPartnerUp) {
+ goto wait_again;
+ // Role switch succeeded since usb->mPartnerUp is true.
+ } else {
+ roleSwitch = true;
+ }
+ } else {
+ ALOGI("Role switch failed while wrting to file");
+ }
+ pthread_mutex_unlock(&usb->mPartnerLock);
+ }
+
+ if (!roleSwitch)
+ switchToDrp(std::string(portName.c_str()));
+
+ return roleSwitch;
+}
+
+Usb::Usb()
+ : mLock(PTHREAD_MUTEX_INITIALIZER),
+ mRoleSwitchLock(PTHREAD_MUTEX_INITIALIZER),
+ mPartnerLock(PTHREAD_MUTEX_INITIALIZER),
+ mPartnerUp(false) {
+ pthread_condattr_t attr;
+ if (pthread_condattr_init(&attr)) {
+ ALOGE("pthread_condattr_init failed: %s", strerror(errno));
+ abort();
+ }
+ if (pthread_condattr_setclock(&attr, CLOCK_MONOTONIC)) {
+ ALOGE("pthread_condattr_setclock failed: %s", strerror(errno));
+ abort();
+ }
+ if (pthread_cond_init(&mPartnerCV, &attr)) {
+ ALOGE("pthread_cond_init failed: %s", strerror(errno));
+ abort();
+ }
+ if (pthread_condattr_destroy(&attr)) {
+ ALOGE("pthread_condattr_destroy failed: %s", strerror(errno));
+ abort();
+ }
+}
+
+Return Usb::switchRole(const hidl_string &portName, const V1_0::PortRole &newRole) {
+ std::string filename = appendRoleNodeHelper(std::string(portName.c_str()), newRole.type);
+ std::string written;
+ FILE *fp;
+ bool roleSwitch = false;
+
+ if (filename == "") {
+ ALOGE("Fatal: invalid node type");
+ return Void();
+ }
+
+ pthread_mutex_lock(&mRoleSwitchLock);
+
+ ALOGI("filename write: %s role:%s", filename.c_str(), convertRoletoString(newRole).c_str());
+
+ if (newRole.type == PortRoleType::MODE) {
+ roleSwitch = switchMode(portName, newRole, this);
+ } else {
+ fp = fopen(filename.c_str(), "w");
+ if (fp != NULL) {
+ int ret = fputs(convertRoletoString(newRole).c_str(), fp);
+ fclose(fp);
+ if ((ret != EOF) && !readFile(filename, &written)) {
+ extractRole(&written);
+ ALOGI("written: %s", written.c_str());
+ if (written == convertRoletoString(newRole)) {
+ roleSwitch = true;
+ } else {
+ ALOGE("Role switch failed");
+ }
+ } else {
+ ALOGE("failed to update the new role");
+ }
+ } else {
+ ALOGE("fopen failed");
+ }
+ }
+
+ pthread_mutex_lock(&mLock);
+ if (mCallback_1_0 != NULL) {
+ Return ret = mCallback_1_0->notifyRoleSwitchStatus(
+ portName, newRole, roleSwitch ? Status::SUCCESS : Status::ERROR);
+ if (!ret.isOk())
+ ALOGE("RoleSwitchStatus error %s", ret.description().c_str());
+ } else {
+ ALOGE("Not notifying the userspace. Callback is not set");
+ }
+ pthread_mutex_unlock(&mLock);
+ pthread_mutex_unlock(&mRoleSwitchLock);
+
+ return Void();
+}
+
+Status getAccessoryConnected(const std::string &portName, std::string *accessory) {
+ std::string filename = "/sys/class/typec/" + portName + "-partner/accessory_mode";
+
+ if (readFile(filename, accessory)) {
+ ALOGE("getAccessoryConnected: Failed to open filesystem node: %s", filename.c_str());
+ return Status::ERROR;
+ }
+
+ return Status::SUCCESS;
+}
+
+Status getCurrentRoleHelper(const std::string &portName, bool connected, PortRoleType type,
+ uint32_t *currentRole) {
+ std::string filename;
+ std::string roleName;
+ std::string accessory;
+
+ // Mode
+
+ if (type == PortRoleType::POWER_ROLE) {
+ filename = "/sys/class/typec/" + portName + "/power_role";
+ *currentRole = static_cast(PortPowerRole::NONE);
+ } else if (type == PortRoleType::DATA_ROLE) {
+ filename = "/sys/class/typec/" + portName + "/data_role";
+ *currentRole = static_cast(PortDataRole::NONE);
+ } else if (type == PortRoleType::MODE) {
+ filename = "/sys/class/typec/" + portName + "/data_role";
+ *currentRole = static_cast(PortMode_1_1::NONE);
+ } else {
+ return Status::ERROR;
+ }
+
+ if (!connected)
+ return Status::SUCCESS;
+
+ if (type == PortRoleType::MODE) {
+ if (getAccessoryConnected(portName, &accessory) != Status::SUCCESS) {
+ return Status::ERROR;
+ }
+ if (accessory == "analog_audio") {
+ *currentRole = static_cast(PortMode_1_1::AUDIO_ACCESSORY);
+ return Status::SUCCESS;
+ } else if (accessory == "debug") {
+ *currentRole = static_cast(PortMode_1_1::DEBUG_ACCESSORY);
+ return Status::SUCCESS;
+ }
+ }
+
+ if (readFile(filename, &roleName)) {
+ ALOGE("getCurrentRole: Failed to open filesystem node: %s", filename.c_str());
+ return Status::ERROR;
+ }
+
+ extractRole(&roleName);
+
+ if (roleName == "source") {
+ *currentRole = static_cast(PortPowerRole::SOURCE);
+ } else if (roleName == "sink") {
+ *currentRole = static_cast(PortPowerRole::SINK);
+ } else if (roleName == "host") {
+ if (type == PortRoleType::DATA_ROLE)
+ *currentRole = static_cast(PortDataRole::HOST);
+ else
+ *currentRole = static_cast(PortMode_1_1::DFP);
+ } else if (roleName == "device") {
+ if (type == PortRoleType::DATA_ROLE)
+ *currentRole = static_cast(PortDataRole::DEVICE);
+ else
+ *currentRole = static_cast(PortMode_1_1::UFP);
+ } else if (roleName != "none") {
+ /* case for none has already been addressed.
+ * so we check if the role isnt none.
+ */
+ return Status::UNRECOGNIZED_ROLE;
+ }
+
+ return Status::SUCCESS;
+}
+
+Status getTypeCPortNamesHelper(std::unordered_map *names) {
+ DIR *dp;
+
+ dp = opendir("/sys/class/typec");
+ if (dp != NULL) {
+ struct dirent *ep;
+
+ while ((ep = readdir(dp))) {
+ if (ep->d_type == DT_LNK) {
+ if (std::string::npos == std::string(ep->d_name).find("-partner")) {
+ std::unordered_map::const_iterator portName =
+ names->find(ep->d_name);
+ if (portName == names->end()) {
+ names->insert({ep->d_name, false});
+ }
+ } else {
+ (*names)[std::strtok(ep->d_name, "-")] = true;
+ }
+ }
+ }
+ closedir(dp);
+ return Status::SUCCESS;
+ }
+
+ ALOGE("Failed to open /sys/class/typec");
+ return Status::ERROR;
+}
+
+bool canSwitchRoleHelper(const std::string &portName, PortRoleType /*type*/) {
+ std::string filename = "/sys/class/typec/" + portName + "-partner/supports_usb_power_delivery";
+ std::string supportsPD;
+
+ if (!readFile(filename, &supportsPD)) {
+ if (supportsPD == "yes") {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/*
+ * Reuse the same method for both V1_0 and V1_1 callback objects.
+ * The caller of this method would reconstruct the V1_0::PortStatus
+ * object if required.
+ */
+Status getPortStatusHelper(hidl_vec *currentPortStatus_1_2, HALVersion version) {
+ std::unordered_map names;
+ Status result = getTypeCPortNamesHelper(&names);
+ int i = -1;
+
+ if (result == Status::SUCCESS) {
+ currentPortStatus_1_2->resize(names.size());
+ for (std::pair port : names) {
+ i++;
+ ALOGI("%s", port.first.c_str());
+ (*currentPortStatus_1_2)[i].status_1_1.status.portName = port.first;
+
+ uint32_t currentRole;
+ if (getCurrentRoleHelper(port.first, port.second, PortRoleType::POWER_ROLE,
+ ¤tRole) == Status::SUCCESS) {
+ (*currentPortStatus_1_2)[i].status_1_1.status.currentPowerRole =
+ static_cast(currentRole);
+ } else {
+ ALOGE("Error while retrieving portNames");
+ goto done;
+ }
+
+ if (getCurrentRoleHelper(port.first, port.second, PortRoleType::DATA_ROLE,
+ ¤tRole) == Status::SUCCESS) {
+ (*currentPortStatus_1_2)[i].status_1_1.status.currentDataRole =
+ static_cast(currentRole);
+ } else {
+ ALOGE("Error while retrieving current port role");
+ goto done;
+ }
+
+ if (getCurrentRoleHelper(port.first, port.second, PortRoleType::MODE, ¤tRole) ==
+ Status::SUCCESS) {
+ (*currentPortStatus_1_2)[i].status_1_1.currentMode =
+ static_cast(currentRole);
+ (*currentPortStatus_1_2)[i].status_1_1.status.currentMode =
+ static_cast(currentRole);
+ } else {
+ ALOGE("Error while retrieving current data role");
+ goto done;
+ }
+
+ (*currentPortStatus_1_2)[i].status_1_1.status.canChangeMode = true;
+ (*currentPortStatus_1_2)[i].status_1_1.status.canChangeDataRole =
+ port.second ? canSwitchRoleHelper(port.first, PortRoleType::DATA_ROLE) : false;
+ (*currentPortStatus_1_2)[i].status_1_1.status.canChangePowerRole =
+ port.second ? canSwitchRoleHelper(port.first, PortRoleType::POWER_ROLE) : false;
+
+ if (version == HALVersion::V1_0) {
+ ALOGI("HAL version V1_0");
+ (*currentPortStatus_1_2)[i].status_1_1.status.supportedModes = V1_0::PortMode::DRP;
+ } else {
+ if (version == HALVersion::V1_1)
+ ALOGI("HAL version V1_1");
+ else
+ ALOGI("HAL version V1_2");
+ (*currentPortStatus_1_2)[i].status_1_1.supportedModes = 0 | PortMode_1_1::DRP;
+ (*currentPortStatus_1_2)[i].status_1_1.status.supportedModes = V1_0::PortMode::NONE;
+ (*currentPortStatus_1_2)[i].status_1_1.status.currentMode = V1_0::PortMode::NONE;
+ }
+
+ ALOGI(
+ "%d:%s connected:%d canChangeMode:%d canChagedata:%d canChangePower:%d "
+ "supportedModes:%d",
+ i, port.first.c_str(), port.second,
+ (*currentPortStatus_1_2)[i].status_1_1.status.canChangeMode,
+ (*currentPortStatus_1_2)[i].status_1_1.status.canChangeDataRole,
+ (*currentPortStatus_1_2)[i].status_1_1.status.canChangePowerRole,
+ (*currentPortStatus_1_2)[i].status_1_1.supportedModes);
+ }
+ return Status::SUCCESS;
+ }
+done:
+ return Status::ERROR;
+}
+
+void queryVersionHelper(android::hardware::usb::V1_2::implementation::Usb *usb,
+ hidl_vec *currentPortStatus_1_2) {
+ hidl_vec currentPortStatus_1_1;
+ hidl_vec currentPortStatus;
+ Status status;
+ sp callback_V1_1 = V1_1::IUsbCallback::castFrom(usb->mCallback_1_0);
+ sp callback_V1_2 = IUsbCallback::castFrom(usb->mCallback_1_0);
+
+ pthread_mutex_lock(&usb->mLock);
+ if (usb->mCallback_1_0 != NULL) {
+ if (callback_V1_2 != NULL) {
+ status = getPortStatusHelper(currentPortStatus_1_2, HALVersion::V1_2);
+ queryMoistureDetectionStatus(currentPortStatus_1_2);
+ } else if (callback_V1_1 != NULL) {
+ status = getPortStatusHelper(currentPortStatus_1_2, HALVersion::V1_1);
+ currentPortStatus_1_1.resize(currentPortStatus_1_2->size());
+ for (unsigned long i = 0; i < currentPortStatus_1_2->size(); i++)
+ currentPortStatus_1_1[i] = (*currentPortStatus_1_2)[i].status_1_1;
+ } else {
+ status = getPortStatusHelper(currentPortStatus_1_2, HALVersion::V1_0);
+ currentPortStatus.resize(currentPortStatus_1_2->size());
+ for (unsigned long i = 0; i < currentPortStatus_1_2->size(); i++)
+ currentPortStatus[i] = (*currentPortStatus_1_2)[i].status_1_1.status;
+ }
+
+ Return ret;
+
+ if (callback_V1_2 != NULL)
+ ret = callback_V1_2->notifyPortStatusChange_1_2(*currentPortStatus_1_2, status);
+ else if (callback_V1_1 != NULL)
+ ret = callback_V1_1->notifyPortStatusChange_1_1(currentPortStatus_1_1, status);
+ else
+ ret = usb->mCallback_1_0->notifyPortStatusChange(currentPortStatus, status);
+
+ if (!ret.isOk())
+ ALOGE("queryPortStatus_1_2 error %s", ret.description().c_str());
+ } else {
+ ALOGI("Notifying userspace skipped. Callback is NULL");
+ }
+ pthread_mutex_unlock(&usb->mLock);
+}
+
+Return Usb::queryPortStatus() {
+ hidl_vec currentPortStatus_1_2;
+
+ queryVersionHelper(this, ¤tPortStatus_1_2);
+ return Void();
+}
+
+struct data {
+ int uevent_fd;
+ android::hardware::usb::V1_2::implementation::Usb *usb;
+};
+
+static void uevent_event(uint32_t /*epevents*/, struct data *payload) {
+ char msg[UEVENT_MSG_LEN + 2];
+ char *cp;
+ int n;
+
+ n = uevent_kernel_multicast_recv(payload->uevent_fd, msg, UEVENT_MSG_LEN);
+ if (n <= 0)
+ return;
+ if (n >= UEVENT_MSG_LEN) /* overflow -- discard */
+ return;
+
+ msg[n] = '\0';
+ msg[n + 1] = '\0';
+ cp = msg;
+
+ while (*cp) {
+ if (std::regex_match(cp, std::regex("(add)(.*)(-partner)"))) {
+ ALOGI("partner added");
+ pthread_mutex_lock(&payload->usb->mPartnerLock);
+ payload->usb->mPartnerUp = true;
+ pthread_cond_signal(&payload->usb->mPartnerCV);
+ pthread_mutex_unlock(&payload->usb->mPartnerLock);
+ } else if (!strncmp(cp, "DEVTYPE=typec_", strlen("DEVTYPE=typec_")) ||
+ !strncmp(cp, "POWER_SUPPLY_MOISTURE_DETECTED",
+ strlen("POWER_SUPPLY_MOISTURE_DETECTED"))) {
+ hidl_vec currentPortStatus_1_2;
+ queryVersionHelper(payload->usb, ¤tPortStatus_1_2);
+
+ // Role switch is not in progress and port is in disconnected state
+ if (!pthread_mutex_trylock(&payload->usb->mRoleSwitchLock)) {
+ for (unsigned long i = 0; i < currentPortStatus_1_2.size(); i++) {
+ DIR *dp =
+ opendir(std::string("/sys/class/typec/" +
+ std::string(currentPortStatus_1_2[i]
+ .status_1_1.status.portName.c_str()) +
+ "-partner")
+ .c_str());
+ if (dp == NULL) {
+ // PortRole role = {.role = static_cast(PortMode::UFP)};
+ switchToDrp(currentPortStatus_1_2[i].status_1_1.status.portName);
+ } else {
+ closedir(dp);
+ }
+ }
+ pthread_mutex_unlock(&payload->usb->mRoleSwitchLock);
+ }
+ break;
+ }
+ /* advance to after the next \0 */
+ while (*cp++) {
+ }
+ }
+}
+
+void *work(void *param) {
+ int epoll_fd, uevent_fd;
+ struct epoll_event ev;
+ int nevents = 0;
+ struct data payload;
+
+ ALOGE("creating thread");
+
+ uevent_fd = uevent_open_socket(64 * 1024, true);
+
+ if (uevent_fd < 0) {
+ ALOGE("uevent_init: uevent_open_socket failed\n");
+ return NULL;
+ }
+
+ payload.uevent_fd = uevent_fd;
+ payload.usb = (android::hardware::usb::V1_2::implementation::Usb *)param;
+
+ fcntl(uevent_fd, F_SETFL, O_NONBLOCK);
+
+ ev.events = EPOLLIN;
+ ev.data.ptr = (void *)uevent_event;
+
+ epoll_fd = epoll_create(64);
+ if (epoll_fd == -1) {
+ ALOGE("epoll_create failed; errno=%d", errno);
+ goto error;
+ }
+
+ if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, uevent_fd, &ev) == -1) {
+ ALOGE("epoll_ctl failed; errno=%d", errno);
+ goto error;
+ }
+
+ while (!destroyThread) {
+ struct epoll_event events[64];
+
+ nevents = epoll_wait(epoll_fd, events, 64, -1);
+ if (nevents == -1) {
+ if (errno == EINTR)
+ continue;
+ ALOGE("usb epoll_wait failed; errno=%d", errno);
+ break;
+ }
+
+ for (int n = 0; n < nevents; ++n) {
+ if (events[n].data.ptr)
+ (*(void (*)(int, struct data *payload))events[n].data.ptr)(events[n].events,
+ &payload);
+ }
+ }
+
+ ALOGI("exiting worker thread");
+error:
+ close(uevent_fd);
+
+ if (epoll_fd >= 0)
+ close(epoll_fd);
+
+ return NULL;
+}
+
+void sighandler(int sig) {
+ if (sig == SIGUSR1) {
+ destroyThread = true;
+ ALOGI("destroy set");
+ return;
+ }
+ signal(SIGUSR1, sighandler);
+}
+
+Return Usb::setCallback(const sp