EM/THERMAL: Enabling thermal service.

Enabling Android thermal service feature to control
platform and skin temprature.

Bug: 17154068
BZ: 217020
Change-Id: Ife465076323e126d9cb66653b1313cffc4b963c1
Signed-off-by: shravan <[email protected]>
diff --git a/ituxd/Android.mk b/ituxd/Android.mk
new file mode 100644
index 0000000..68a7de8
--- /dev/null
+++ b/ituxd/Android.mk
@@ -0,0 +1,49 @@
+# Copyright (C) 2014 The Android Open-Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# WARNING: Everything listed here will be built on ALL platforms,
+# including x86, the emulator, and the SDK.  Modules must be uniquely
+# named (liblights.tuna), and must build everywhere, or limit themselves
+# to only building on ARM if they include assembly. Individual makefiles
+# are responsible for having their own logic, for fine-grained control.
+
+ifeq ($(ENABLE_ITUXD),true)
+
+LOCAL_PATH:= $(call my-dir)
+
+# Build
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_JNI_SHARED_LIBRARIES := libthermalJNI
+
+LOCAL_REQUIRED_MODULES += libthermalJNI
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := ituxd
+
+LOCAL_CERTIFICATE := platform
+
+LOCAL_PRIVILEGED_MODULE := true
+
+LOCAL_PROGUARD_ENABLED := disabled
+
+include $(BUILD_PACKAGE)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
+
+endif
diff --git a/ituxd/AndroidManifest.xml b/ituxd/AndroidManifest.xml
new file mode 100644
index 0000000..c725d1e
--- /dev/null
+++ b/ituxd/AndroidManifest.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="com.intel.thermal"
+        android:sharedUserId="android.uid.system"
+>
+
+     <uses-permission android:name="android.permission.WAKE_LOCK" />
+     <uses-permission android:name="android.permission.MANAGE_USB" />
+     <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
+     <uses-permission android:name="android.permission.SHUTDOWN" />
+     <uses-permission android:name="android.permission.REBOOT" />
+
+    <protected-broadcast android:name="com.intel.thermal.action.THERMAL_ZONE_STATE_CHANGED" />
+
+    <application android:name=".ituxdApp" android:persistent="true">
+
+    <service android:enabled="true" android:name=".ThermalService"/>
+    </application>
+</manifest>
diff --git a/ituxd/jni/Android.mk b/ituxd/jni/Android.mk
new file mode 100644
index 0000000..65130f7
--- /dev/null
+++ b/ituxd/jni/Android.mk
@@ -0,0 +1,45 @@
+# Copyright (C) 2014 The Android Open-Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# WARNING: Everything listed here will be built on ALL platforms,
+# including x86, the emulator, and the SDK.  Modules must be uniquely
+# named (liblights.tuna), and must build everywhere, or limit themselves
+# to only building on ARM if they include assembly. Individual makefiles
+# are responsible for having their own logic, for fine-grained control.
+
+ifeq ($(ENABLE_ITUXD),true)
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= thermalJNI.cpp \
+    onload.cpp
+
+
+LOCAL_SHARED_LIBRARIES := \
+    libbinder \
+    libcutils \
+    liblog \
+    libhardware \
+    libhardware_legacy \
+    libnativehelper \
+    libc \
+    libutils
+
+LOCAL_MODULE:= libthermalJNI
+
+include $(BUILD_SHARED_LIBRARY)
+
+endif
diff --git a/ituxd/jni/onload.cpp b/ituxd/jni/onload.cpp
new file mode 100644
index 0000000..f66a169
--- /dev/null
+++ b/ituxd/jni/onload.cpp
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "JNIHelp.h"
+#include "jni.h"
+#include "utils/Log.h"
+#include "utils/misc.h"
+
+namespace android {
+int register_intel_thermal_ituxd(JNIEnv* env);
+};
+
+using namespace android;
+
+extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved)
+{
+    JNIEnv* env = NULL;
+    jint result = -1;
+
+    if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
+        ALOGE("GetEnv failed!");
+        return result;
+    }
+    ALOG_ASSERT(env, "Could not retrieve the env!");
+
+    register_intel_thermal_ituxd(env);
+
+    return JNI_VERSION_1_4;
+}
diff --git a/ituxd/jni/thermalJNI.cpp b/ituxd/jni/thermalJNI.cpp
new file mode 100644
index 0000000..4c92775
--- /dev/null
+++ b/ituxd/jni/thermalJNI.cpp
@@ -0,0 +1,276 @@
+/*
+ * Copyright (C) 2014 Intel Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "ThermalManagerJNI"
+
+#include "JNIHelp.h"
+#include "jni.h"
+#include <utils/Log.h>
+#include <utils/misc.h>
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+namespace android {
+
+#define THERMAL_ZONE_PATH "/sys/class/thermal/thermal_zone"
+#define COOLING_DEV_PATH  "/sys/class/thermal/cooling_device"
+
+static int readFromFile(const char *path, char* buf, size_t size, bool throwError)
+{
+    if (!path)
+        return -1;
+
+    int fd = open(path, O_RDONLY, 0);
+    if (fd < 0) {
+        if (throwError) {
+            ALOGE("Could not open '%s'", path);
+        }
+        return -1;
+    }
+
+    ssize_t count = read(fd, buf, size);
+    if (count > 0) {
+        while (count > 0 && buf[count-1] == '\n')
+            count--;
+        buf[count] = '\0';
+    } else {
+        buf[0] = '\0';
+    }
+
+    close(fd);
+    return count;
+}
+
+static int writeToFile(const char *path, int val)
+{
+    const int SIZE = 20;
+    int ret, fd, len;
+    char value[SIZE];
+
+    if (!path)
+        return -1;
+
+    fd = open(path, O_WRONLY, 0);
+    if (fd < 0) {
+        ALOGE("writeToFile: Could not open '%s' err: %d", path, errno);
+        return -1;
+    }
+
+    len = snprintf(value, SIZE, "%d\n", val);
+    ret = write(fd, value, len);
+
+    close(fd);
+    return (ret == len) ? 0 : -1;
+}
+
+static int lookup(const char *base_path, const char *name)
+{
+    const int SIZE = 128;
+    char buf[SIZE];
+    char full_path[SIZE];
+    int count = 0;
+
+    do {
+        snprintf(full_path, SIZE, "%s%d/type", base_path, count);
+        // Loop through all thermal_zones or cooling_devices until we
+        // find a first match. We call it a match when the given
+        // 'name' of the thermal_zone (or a cooling_device) matches
+        // with the value of 'type' sysfs interface of a thermal_zone
+        // (or cooling_device).
+        if (readFromFile(full_path, buf, SIZE, false) < 0) break;
+
+        if (!strcmp(name, buf)) return count;
+
+        count++;
+    } while(1);
+
+    // lookup failed.
+    return -1;
+}
+
+static int lookup_contains(const char *base_path, const char *name)
+{
+    const int SIZE = 128;
+    char buf[SIZE];
+    char full_path[SIZE];
+    int count = 0;
+
+    do {
+        snprintf(full_path, SIZE, "%s%d/type", base_path, count);
+        if (readFromFile(full_path, buf, SIZE, false) < 0) break;
+        // Check if 'buf' contains 'name'
+        if (strstr(buf, name) != NULL) return count;
+
+        count++;
+    } while(1);
+
+    // lookup failed.
+    return -1;
+}
+
+static jboolean isFileExists(JNIEnv* env, jobject obj, jstring jPath)
+{
+    const char *path = NULL;
+    jboolean ret = true;
+
+    path = jPath ? env->GetStringUTFChars(jPath, NULL) : NULL;
+    if (!path) {
+        return false;
+    }
+
+    int fd = open(path, O_RDONLY, 0);
+
+    if (fd < 0) {
+        ret = false;
+    } else {
+        close(fd);
+    }
+    env->ReleaseStringUTFChars(jPath, path);
+    return ret;
+}
+
+static jint getThermalZoneIndex(JNIEnv* env, jobject obj, jstring jType)
+{
+    int ret;
+    const char *type = NULL;
+
+    type = jType ? env->GetStringUTFChars(jType, NULL) : NULL;
+    if (!type) {
+        jniThrowNullPointerException(env, "Type");
+        return -1;
+    }
+
+    ret = lookup(THERMAL_ZONE_PATH, type);
+    env->ReleaseStringUTFChars(jType, type);
+    return ret;
+}
+
+static jint getThermalZoneIndexContains(JNIEnv* env, jobject obj, jstring jType)
+{
+    int ret;
+    const char *type = NULL;
+
+    type = jType ? env->GetStringUTFChars(jType, NULL) : NULL;
+    if (!type) {
+        jniThrowNullPointerException(env, "Type");
+        return -1;
+    }
+
+    ret = lookup_contains(THERMAL_ZONE_PATH, type);
+    env->ReleaseStringUTFChars(jType, type);
+    return ret;
+}
+
+static jint getCoolingDeviceIndex(JNIEnv* env, jobject obj, jstring jType)
+{
+    int ret;
+    const char *type = NULL;
+
+    type = jType ? env->GetStringUTFChars(jType, NULL) : NULL;
+    if (!type) {
+        jniThrowNullPointerException(env, "Type");
+        return -1;
+    }
+
+    ret = lookup(COOLING_DEV_PATH, type);
+    env->ReleaseStringUTFChars(jType, type);
+    return ret;
+}
+
+static jint getCoolingDeviceIndexContains(JNIEnv* env, jobject obj, jstring jType)
+{
+    int ret;
+    const char *type = NULL;
+
+    type = jType ? env->GetStringUTFChars(jType, NULL) : NULL;
+    if (!type) {
+        jniThrowNullPointerException(env, "Type");
+        return -1;
+    }
+
+    ret = lookup_contains(COOLING_DEV_PATH, type);
+    env->ReleaseStringUTFChars(jType, type);
+    return ret;
+}
+
+static jint writeSysfs(JNIEnv* env, jobject obj, jstring jPath, jint jVal)
+{
+    int ret;
+    const char *path = NULL;
+
+    path = jPath ? env->GetStringUTFChars(jPath, NULL) : NULL;
+    if (!path) {
+        jniThrowNullPointerException(env, "path");
+        return -EINVAL;
+    }
+
+    ret = writeToFile(path, jVal);
+    env->ReleaseStringUTFChars(jPath, path);
+    return ret;
+}
+
+static jstring readSysfs(JNIEnv* env, jobject obj, jstring jPath)
+{
+    const char *path = NULL;
+    const int SIZE = 512;
+    char buf[SIZE];
+
+    path = jPath ? env->GetStringUTFChars(jPath, NULL) : NULL;
+    if (!path) {
+        jniThrowNullPointerException(env, "path");
+        return NULL;
+    }
+
+    if (readFromFile(path, buf, SIZE, true) > 0) {
+        env->ReleaseStringUTFChars(jPath, path);
+        return env->NewStringUTF(buf);
+    } else {
+        env->ReleaseStringUTFChars(jPath, path);
+        return NULL;
+    }
+}
+
+static JNINativeMethod sMethods[] = {
+     /* name, signature, funcPtr */
+        {"native_readSysfs", "(Ljava/lang/String;)Ljava/lang/String;", (void*)readSysfs},
+        {"native_writeSysfs", "(Ljava/lang/String;I)I", (void*)writeSysfs},
+        {"native_getThermalZoneIndex", "(Ljava/lang/String;)I", (void*)getThermalZoneIndex},
+        {"native_getThermalZoneIndexContains", "(Ljava/lang/String;)I",
+                 (void*)getThermalZoneIndexContains},
+        {"native_getCoolingDeviceIndex", "(Ljava/lang/String;)I", (void*)getCoolingDeviceIndex},
+        {"native_getCoolingDeviceIndexContains", "(Ljava/lang/String;)I",
+                 (void*)getCoolingDeviceIndexContains},
+        {"native_isFileExists", "(Ljava/lang/String;)Z", (void*)isFileExists},
+};
+
+int register_intel_thermal_ituxd(JNIEnv* env)
+{
+    jclass clazz = env->FindClass("com/intel/thermal/ThermalUtils");
+    if (clazz == NULL) {
+        ALOGE("Can't find com/intel/thermal/ThermalUtils");
+        return -1;
+    }
+
+    return jniRegisterNativeMethods(env, "com/intel/thermal/ThermalUtils",
+            sMethods, NELEM(sMethods));
+}
+
+} /* namespace android */
diff --git a/ituxd/res/xml/thermal_sensor_config.xml b/ituxd/res/xml/thermal_sensor_config.xml
new file mode 100644
index 0000000..5f44487
--- /dev/null
+++ b/ituxd/res/xml/thermal_sensor_config.xml
@@ -0,0 +1,142 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Thermal Management Configuration File -->
+<!--  Intel Corporation 2011-2012  -->
+<thermalconfig>
+  <!-- Config xml file version should be in sync with iTUX version number-->
+  <ConfigFileVersion>3.0</ConfigFileVersion>
+  <!--Platform Parameters-->
+  <PlatformInfo>
+      <PlatformName>fugu</PlatformName>
+      <!--namely NORMAL, WARNING, ALERT, and CRITICAL.-->
+      <!--in the increasing order of thermal severity-->
+      <!--standard sensor devices register as /sys/class/thermal/thermal_zoneX. Herein
+      referred as 'Path Enumerated at Runtime by Framework in Kernel Thermal' or PERFKT-->
+  </PlatformInfo>
+
+  <Sensor>
+      <SensorName>SYSTHERM1</SensorName>
+<!--
+      <SensorPath>auto</SensorPath>
+      <InputTemp>temp</InputTemp>
+      <HighTemp>auto</HighTemp>
+      <LowTemp>auto</LowTemp>
+-->
+  </Sensor>
+
+  <Sensor>
+      <SensorName>SYSTHERM0</SensorName>
+<!--
+      <SensorPath>auto</SensorPath>
+      <InputTemp>temp</InputTemp>
+      <HighTemp>auto</HighTemp>
+      <LowTemp>auto</LowTemp>
+-->
+  </Sensor>
+
+  <Sensor>
+      <SensorName>SoC_DTS0</SensorName>
+      <SensorPath>auto</SensorPath>
+      <InputTemp>temp</InputTemp>
+      <HighTemp>auto</HighTemp>
+      <LowTemp>auto</LowTemp>
+  </Sensor>
+
+  <Sensor>
+      <SensorName>Core0</SensorName>
+      <SensorPath>/sys/devices/platform/coretemp.0/</SensorPath>
+      <InputTemp>temp2_input</InputTemp>
+      <HighTemp>temp2_threshold2</HighTemp>
+      <LowTemp>temp2_threshold1</LowTemp>
+      <UEventDevPath>DEVPATH=/devices/platform/coretemp.0</UEventDevPath>
+  </Sensor>
+
+<!--
+  <Zone>
+        <ZoneID>1</ZoneID>
+        <ZoneName>BackSkin</ZoneName>
+        <ZoneLogic>VirtualSkin</ZoneLogic>
+        <SupportsUEvent>0</SupportsUEvent>
+        <DebounceInterval>2000</DebounceInterval>
+        <PollDelay>
+               <DelayNormal>30000</DelayNormal>
+               <DelayWarning>30000</DelayWarning>
+               <DelayAlert>30000</DelayAlert>
+        </PollDelay>
+        <ZoneThreshold>
+               <ZoneThresholdNormal>47000</ZoneThresholdNormal>
+               <ZoneThresholdWarning>57000</ZoneThresholdWarning>
+               <ZoneThresholdAlert>72000</ZoneThresholdAlert>
+        </ZoneThreshold>
+       <SensorAttrib>
+           <SensorName>SYSTHERM1</SensorName>
+           <Weight>680</Weight>
+       </SensorAttrib>
+       <Offset>8400</Offset>
+  </Zone>
+
+  <Zone>
+       <ZoneID>2</ZoneID>
+       <ZoneName>FrontSkin</ZoneName>
+       <ZoneLogic>VirtualSkin</ZoneLogic>
+       <SupportsUEvent>0</SupportsUEvent>
+       <DebounceInterval>2000</DebounceInterval>
+       <PollDelay>
+              <DelayNormal>30000</DelayNormal>
+              <DelayWarning>30000</DelayWarning>
+              <DelayAlert>30000</DelayAlert>
+       </PollDelay>
+       <ZoneThreshold>
+              <ZoneThresholdNormal>40000</ZoneThresholdNormal>
+              <ZoneThresholdWarning>50000</ZoneThresholdWarning>
+              <ZoneThresholdAlert>65000</ZoneThresholdAlert>
+       </ZoneThreshold>
+       <SensorAttrib>
+           <SensorName>SYSTHERM0</SensorName>
+           <Weight>710</Weight>
+       </SensorAttrib>
+       <Offset>8100</Offset>
+  </Zone>
+-->
+
+  <Zone>
+       <ZoneID>3</ZoneID>
+       <ZoneName>SoC</ZoneName>
+       <ZoneLogic>Raw</ZoneLogic>
+       <SupportsUEvent>0</SupportsUEvent>
+       <DebounceInterval>2000</DebounceInterval>
+       <PollDelay>
+              <DelayNormal>30000</DelayNormal>
+              <DelayWarning>10000</DelayWarning>
+              <DelayAlert>5000</DelayAlert>
+       </PollDelay>
+       <ZoneThreshold>
+              <ZoneThresholdNormal>80000</ZoneThresholdNormal>
+              <ZoneThresholdWarning>84000</ZoneThresholdWarning>
+              <ZoneThresholdAlert>88000</ZoneThresholdAlert>
+       </ZoneThreshold>
+       <SensorAttrib>
+           <SensorName>SoC_DTS0</SensorName>
+       </SensorAttrib>
+  </Zone>
+
+  <Zone>
+       <ZoneID>4</ZoneID>
+       <ZoneName>CPU</ZoneName>
+       <ZoneLogic>Raw</ZoneLogic>
+       <SupportsUEvent>0</SupportsUEvent>
+       <DebounceInterval>2000</DebounceInterval>
+       <PollDelay>
+              <DelayNormal>30000</DelayNormal>
+              <DelayWarning>10000</DelayWarning>
+              <DelayAlert>5000</DelayAlert>
+       </PollDelay>
+       <ZoneThreshold>
+              <ZoneThresholdNormal>80000</ZoneThresholdNormal>
+              <ZoneThresholdWarning>84000</ZoneThresholdWarning>
+              <ZoneThresholdAlert>88000</ZoneThresholdAlert>
+       </ZoneThreshold>
+       <SensorAttrib>
+           <SensorName>Core0</SensorName>
+       </SensorAttrib>
+  </Zone>
+ </thermalconfig>
diff --git a/ituxd/res/xml/thermal_throttle_config.xml b/ituxd/res/xml/thermal_throttle_config.xml
new file mode 100644
index 0000000..1afb1ff
--- /dev/null
+++ b/ituxd/res/xml/thermal_throttle_config.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Thermal Management Configuration File -->
+<!--  Intel Corporation 2011-2012  -->
+<thermalthrottleconfig>
+  <!-- Config xml file version should be in sync with iTUX version number-->
+  <ConfigFileVersion>3.0</ConfigFileVersion>
+
+  <!--Platform Parameters-->
+  <PlatformInfo>
+      <!--PlatformName reference. In future will be compared against ro.board.platform-->
+      <PlatformName>fugu</PlatformName>
+      <!--standard cooling devices register in /sys/class/thermal/cooling_deviceX/ Herein
+      referred as 'Path Enumerated at Runtime by Framework in Kernel Thermal' or PERFKT-->
+  </PlatformInfo>
+
+  <ContributingDeviceInfo>
+      <CDeviceName>SoC</CDeviceName>
+      <CDeviceID>1</CDeviceID>
+      <CDeviceClassPath>auto</CDeviceClassPath>
+      <CDeviceThrottlePath>auto</CDeviceThrottlePath>
+  </ContributingDeviceInfo>
+<!--
+  <ZoneThrottleInfo>
+    <ZoneID>1</ZoneID>
+    <CriticalShutDown>1</CriticalShutDown>
+    <CoolingDeviceInfo>
+      <CoolingDevId>1</CoolingDevId>
+    </CoolingDeviceInfo>
+  </ZoneThrottleInfo>
+
+  <ZoneThrottleInfo>
+    <ZoneID>2</ZoneID>
+    <CriticalShutDown>1</CriticalShutDown>
+    <CoolingDeviceInfo>
+      <CoolingDevId>1</CoolingDevId>
+    </CoolingDeviceInfo>
+  </ZoneThrottleInfo>
+-->
+  <ZoneThrottleInfo>
+    <ZoneID>3</ZoneID>
+    <CriticalShutDown>0</CriticalShutDown>
+    <CoolingDeviceInfo>
+      <CoolingDevId>1</CoolingDevId>
+    </CoolingDeviceInfo>
+  </ZoneThrottleInfo>
+
+  <ZoneThrottleInfo>
+    <ZoneID>4</ZoneID>
+    <CriticalShutDown>0</CriticalShutDown>
+    <CoolingDeviceInfo>
+      <CoolingDevId>1</CoolingDevId>
+    </CoolingDeviceInfo>
+  </ZoneThrottleInfo>
+
+</thermalthrottleconfig>
diff --git a/ituxd/src/com/intel/thermal/RawThermalZone.java b/ituxd/src/com/intel/thermal/RawThermalZone.java
new file mode 100644
index 0000000..4baba9a
--- /dev/null
+++ b/ituxd/src/com/intel/thermal/RawThermalZone.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2014 Intel Corporation All Rights Reserved.
+ *
+ * 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.
+ */
+
+package com.intel.thermal;
+
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+/**
+ * The RawThermalZone class extends the ThermalZone class, with a default
+ * implementation of the isZoneStateChanged() method. This computes the
+ * zone state by first computing max of all sensor temperature (in polling mode)
+ * and comparing this temperature against zone thresholds. For uevent based
+ * monitoring only the temperature of first sensor is used to compute zone state.
+ *
+ * @hide
+ */
+public class RawThermalZone extends ThermalZone {
+
+    private static final String TAG = "RawThermalZone";
+    private ThermalZoneMonitor mTzm = null;
+
+    public RawThermalZone() {
+        super();
+        // for raw zone emul temp flag is always false
+        mSupportsEmulTemp = false;
+    }
+
+    // irrespective of what flag is set in XML, emul temp flag is false for raw thermal zone
+    // over ride function. so that even if flag is 1 in XML, 0 will be written
+    public void setEmulTempFlag(int flag) {
+        mSupportsEmulTemp = false;
+        if (flag != 0) {
+            Log.i(TAG, "zone:" + getZoneName()
+                    + " is a raw zone, doesnt support emulated temperature");
+        }
+    }
+
+    public void startMonitoring() {
+        mTzm = new ThermalZoneMonitor(this);
+    }
+
+    public void stopMonitoring() {
+        if (mTzm != null) {
+            mTzm.stopMonitor();
+        }
+    }
+
+    // override updateZoneTemp
+    public boolean updateZoneTemp() {
+        int curTemp = ThermalManager.INVALID_TEMP, maxCurTemp = ThermalManager.INVALID_TEMP;
+        if (isUEventSupported()) {
+            ArrayList<ThermalSensor> list = getThermalSensorList();
+            if (list != null) {
+                // for uevent based monitoring only first sensor used
+                ThermalSensor s = list.get(0);
+                if (s != null) {
+                    maxCurTemp = s.getCurrTemp();
+                }
+            }
+        } else {
+            //zone temp is max of all sensor temp
+            for (ThermalSensor ts : getThermalSensorList()) {
+                if (ts != null && ts.getSensorActiveStatus()) {
+                    curTemp = ts.getCurrTemp();
+                    if (curTemp > maxCurTemp) {
+                        maxCurTemp = curTemp;
+                    }
+                }
+            }
+        }
+
+        if (maxCurTemp != ThermalManager.INVALID_TEMP) {
+            setZoneTemp(maxCurTemp);
+            // it is assumed only one sensor will be provided for moving average
+            if (getMovingAverageFlag() && !isUEventSupported()) {
+                // only for polling mode apply moving average on predicted zone temp
+                setZoneTemp(movingAverageTemp());
+            }
+            return true;
+        }
+
+        return false;
+    }
+}
diff --git a/ituxd/src/com/intel/thermal/ThermalCooling.java b/ituxd/src/com/intel/thermal/ThermalCooling.java
new file mode 100644
index 0000000..66c9470
--- /dev/null
+++ b/ituxd/src/com/intel/thermal/ThermalCooling.java
@@ -0,0 +1,785 @@
+/*
+ * Copyright 2014 Intel Corporation All Rights Reserved.
+ *
+ * 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.
+ */
+
+package com.intel.thermal;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlPullParserFactory;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.SystemProperties;
+import android.util.Log;
+
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Hashtable;
+
+/**
+ * The ThermalCooling class parses the thermal_throttle_config.xml. This class
+ * receives Thermal Intents and takes appropriate actions based on the policies
+ * configured in the xml file.
+ *
+ * @hide
+ */
+public class ThermalCooling {
+    private static final String TAG = "ThermalCooling";
+    private static final String THERMAL_SHUTDOWN_NOTIFY_PATH =
+            "/sys/module/intel_mid_osip/parameters/force_shutdown_occured";
+
+    private Context mContext;
+
+    // count to keep track of zones in critical state, waiting for shutdown
+    private int mCriticalZonesCount = 0;
+    private static final Object sCriticalZonesCountLock = new Object();
+
+    private ThermalZoneReceiver mThermalIntentReceiver = new ThermalZoneReceiver();
+    private ProfileChangeReceiver mProfChangeReceiver = new ProfileChangeReceiver();
+    private boolean mProfChangeListenerInitialized = false;
+    /**
+     * This is the parser class which parses the thermal_throttle_config.xml
+     * file.
+     */
+    protected enum MetaTag {
+        ENUM_THROTTLEVALUES,
+        ENUM_THROTTLEMASK,
+        ENUM_DETHROTTLEMASK,
+        ENUM_UNKNOWN
+    }
+
+    public class ThermalParser {
+        private static final String THERMAL_THROTTLE_CONFIG = "thermalthrottleconfig";
+
+        private static final String CDEVINFO = "ContributingDeviceInfo";
+
+        private static final String ZONETHROTINFO = "ZoneThrottleInfo";
+
+        private static final String COOLINGDEVICEINFO = "CoolingDeviceInfo";
+
+        private static final String THROTTLEMASK = "ThrottleDeviceMask";
+
+        private static final String DETHROTTLEMASK = "DethrottleDeviceMask";
+
+        private static final String THROTTLEVALUES = "ThrottleValues";
+
+        private static final String COOLINGDEVICESTATES = "CoolingDeviceStates";
+
+        private static final String PROFILE = "Profile";
+
+        private ArrayList<Integer> mTempMaskList;
+
+        private ArrayList<Integer> mTempThrottleValuesList;;
+
+        private boolean done = false;
+
+        XmlPullParserFactory mFactory;
+
+        XmlPullParser mParser;
+
+        ThermalCoolingDevice mDevice = null;
+
+        /* Hashtable of (ZoneID and ZoneCoolerBindingInfo object) */
+        Hashtable<Integer, ThermalManager.ZoneCoolerBindingInfo> mZoneCoolerBindMap = null;
+        String mCurProfileName = ThermalManager.DEFAULT_PROFILE_NAME;
+        int mNumProfiles = 0;
+
+        ThermalManager.ZoneCoolerBindingInfo mZone = null;
+
+        FileReader mInputStream = null;
+
+        ThermalParser(String fname) {
+            try {
+                mFactory = XmlPullParserFactory.newInstance(
+                        System.getProperty(XmlPullParserFactory.PROPERTY_NAME), null);
+                mFactory.setNamespaceAware(true);
+                mParser = mFactory.newPullParser();
+            } catch (XmlPullParserException xppe) {
+                Log.e(TAG, "mParser NewInstance Exception");
+            }
+
+            try {
+                mInputStream = new FileReader(fname);
+                if (mInputStream == null)
+                    return;
+                if (mParser != null) {
+                    mParser.setInput(mInputStream);
+                }
+                mDevice = null;
+                mZone = null;
+            } catch (XmlPullParserException xppe) {
+                Log.e(TAG, "mParser setInput XmlPullParserException");
+            } catch (FileNotFoundException e) {
+                Log.e(TAG, "mParser setInput FileNotFoundException");
+            }
+
+        }
+
+        ThermalParser() {
+            mParser = mContext.getResources().
+                    getXml(ThermalManager.sThrottleFileXmlId);
+        }
+
+        public boolean parse() {
+            if (ThermalManager.sIsOverlays == false && mInputStream == null) return false;
+            /* if mParser is null, close any open stream before exiting */
+            if (mParser == null) {
+                try {
+                    if (mInputStream != null) {
+                        mInputStream.close();
+                    }
+                } catch (IOException e) {
+                    Log.i(TAG, "IOException caught in parse() function");
+                }
+                return false;
+            }
+
+            boolean ret = true;
+            MetaTag tag = MetaTag.ENUM_UNKNOWN;
+            try {
+                int mEventType = mParser.getEventType();
+                while (mEventType != XmlPullParser.END_DOCUMENT && !done) {
+                    switch (mEventType) {
+                        case XmlPullParser.START_DOCUMENT:
+                            Log.i(TAG, "StartDocument");
+                            break;
+                        case XmlPullParser.START_TAG:
+                            String tagName = mParser.getName();
+                            boolean isMetaTag = false;
+                            if (tagName != null && tagName.equalsIgnoreCase(THROTTLEVALUES)) {
+                                tag = MetaTag.ENUM_THROTTLEVALUES;
+                                isMetaTag = true;
+                            } else if (tagName != null && tagName.equalsIgnoreCase(THROTTLEMASK)) {
+                                tag = MetaTag.ENUM_THROTTLEMASK;
+                                isMetaTag = true;
+                            } else if (tagName != null
+                                    && tagName.equalsIgnoreCase(DETHROTTLEMASK)) {
+                                tag = MetaTag.ENUM_DETHROTTLEMASK;
+                                isMetaTag = true;
+                            }
+                            if (isMetaTag) {
+                                ret = processMetaTag(tagName, tag);
+                            } else {
+                                ret = processStartElement(tagName);
+                            }
+                            if (!ret) {
+                                if (mInputStream != null) mInputStream.close();
+                                return false;
+                            }
+                            break;
+                        case XmlPullParser.END_TAG:
+                            processEndElement(mParser.getName());
+                            break;
+                    }
+                    mEventType = mParser.next();
+                }
+            } catch (XmlPullParserException xppe) {
+                Log.i(TAG, "XmlPullParserException caught in parse():" + xppe.getMessage());
+                ret = false;
+            } catch (IOException e) {
+                Log.i(TAG, "IOException caught in parse():" + e.getMessage());
+                ret = false;
+            } finally {
+                try {
+                    // end of parsing, close the stream
+                    // close is moved here, since if there is an exception
+                    // while parsing doc, input stream needs to be closed
+                    if (mInputStream != null) {
+                        mInputStream.close();
+                    }
+                } catch (IOException e) {
+                    Log.i(TAG, "IOException caught in parse() function");
+                    ret = false;
+                }
+                return ret;
+            }
+        }
+
+        public boolean processMetaTag(String tagName, MetaTag tagId) {
+            if (mParser == null || tagName == null)  return false;
+            ArrayList<Integer> tempList = new ArrayList<Integer>();
+            try {
+                int eventType = mParser.next();
+                while (true) {
+                    if (eventType == XmlPullParser.START_TAG) {
+                        tempList.add(Integer.parseInt(mParser.nextText()));
+                    } else if (eventType == XmlPullParser.END_TAG &&
+                            mParser.getName().equalsIgnoreCase(tagName)) {
+                        break;
+                    }
+                    eventType = mParser.next();
+                }
+            } catch (XmlPullParserException xppe) {
+                Log.e(TAG, "XmlPullParserException:" + xppe.getMessage());
+                return false;
+            } catch (IOException ioe) {
+                Log.e(TAG, "IOException:" + ioe.getMessage());
+                return false;
+            }
+
+            switch(tagId) {
+                case ENUM_THROTTLEVALUES:
+                    if (mDevice == null) {
+                        return false;
+                    } else {
+                        // add throttle value for TCRITICAL (same as last value)
+                        tempList.add(tempList.get(tempList.size() - 1));
+                        mDevice.setThrottleValuesList(tempList);
+                    }
+                    break;
+                case ENUM_THROTTLEMASK:
+                    if (mZone == null || mZone.getLastCoolingDeviceInstance() ==  null) {
+                        return false;
+                    } else {
+                        // Always throttle at CRITICAL state (last state)
+                        tempList.add(1);
+                        mZone.getLastCoolingDeviceInstance().setThrottleMaskList(tempList);
+                    }
+                    break;
+                case ENUM_DETHROTTLEMASK:
+                    if (mZone == null || mZone.getLastCoolingDeviceInstance() ==  null) {
+                        return false;
+                    } else {
+                        // Dethrottling at CRITICAL state (last state) is dontcare condition
+                        tempList.add(0);
+                        mZone.getLastCoolingDeviceInstance().setDeThrottleMaskList(tempList);
+                    }
+                    break;
+                default:
+                    return false;
+            }
+            return true;
+        }
+        boolean processStartElement(String name) {
+            if (name == null)
+                return false;
+            boolean ret = true;
+            try {
+                if (name.equalsIgnoreCase(CDEVINFO)) {
+                    if (mDevice == null)
+                        mDevice = new ThermalCoolingDevice();
+                } else if (name.equalsIgnoreCase(ZONETHROTINFO)) {
+                    if (mZone == null) {
+                        mZone = new ThermalManager.ZoneCoolerBindingInfo();
+                    }
+                    if (mZoneCoolerBindMap == null) {
+                        mZoneCoolerBindMap = new Hashtable<Integer,
+                                ThermalManager.ZoneCoolerBindingInfo>();
+                    }
+                } else if (name.equalsIgnoreCase(PROFILE)) {
+                    mNumProfiles++;
+                    if (mZoneCoolerBindMap == null) {
+                        mZoneCoolerBindMap = new Hashtable<Integer,
+                                ThermalManager.ZoneCoolerBindingInfo>();
+                    }
+                } else if (name.equalsIgnoreCase(COOLINGDEVICEINFO) && mZone != null) {
+                    if (mZone.getCoolingDeviceInfoList() == null) {
+                        mZone.initializeCoolingDeviceInfoList();
+                    }
+                    mZone.createNewCoolingDeviceInstance();
+                } else {
+                    // Retrieve zone and cooling device mapping
+                    if (name.equalsIgnoreCase("ZoneID") && mZone != null) {
+                        mZone.setZoneID(Integer.parseInt(mParser.nextText()));
+                    } else if (name.equalsIgnoreCase("CriticalShutDown") && mZone != null) {
+                        mZone.setCriticalActionShutdown(Integer.parseInt(mParser.nextText()));
+                    } else if (name.equalsIgnoreCase(THROTTLEMASK) && mZone != null) {
+                        mTempMaskList = new ArrayList<Integer>();
+                    } else if (name.equalsIgnoreCase(DETHROTTLEMASK) && mZone != null) {
+                        mTempMaskList = new ArrayList<Integer>();
+                    } else if (name.equalsIgnoreCase("CoolingDevId") && mZone != null) {
+                        mZone.getLastCoolingDeviceInstance().setCoolingDeviceId(
+                                Integer.parseInt(mParser.nextText()));
+                    } else if (name.equalsIgnoreCase(COOLINGDEVICESTATES) && mZone != null) {
+                        // Increase cooling device states by 1, required for CRITICAL state
+                        mZone.getLastCoolingDeviceInstance().setCoolingDeviceStates(
+                                Integer.parseInt(mParser.nextText()) + 1);
+                    }
+                    // Retrieve cooling device information
+                    if (name.equalsIgnoreCase("CDeviceName") && mDevice != null) {
+                        mDevice.setDeviceName(mParser.nextText());
+                    } else if (name.equalsIgnoreCase("CDeviceID") && mDevice != null) {
+                        mDevice.setDeviceId(Integer.parseInt(mParser.nextText()));
+                    } else if (name.equalsIgnoreCase("CDeviceClassPath") && mDevice != null) {
+                        mDevice.setClassPath(mParser.nextText());
+                    } else if (name.equalsIgnoreCase("CDeviceThrottlePath") && mDevice != null) {
+                        mDevice.setThrottlePath(mParser.nextText());
+                    } else if (name.equalsIgnoreCase("Name")) {
+                        mCurProfileName = mParser.nextText();
+                    }
+                }
+            } catch (XmlPullParserException e) {
+                Log.i(TAG, "XmlPullParserException caught in processStartElement()");
+                ret = false;
+            } catch (IOException e) {
+                Log.i(TAG, "IOException caught in processStartElement()");
+                ret = false;
+            } finally {
+                return ret;
+            }
+        }
+
+        void processEndElement(String name) {
+            if (name == null)
+                return;
+            if (name.equalsIgnoreCase(CDEVINFO) && mDevice != null) {
+                // if cooling dev suports less then DEFAULT throttle values donot add to map.
+                if (mDevice.getNumThrottleValues() < ThermalManager.DEFAULT_NUM_THROTTLE_VALUES) {
+                    Log.i(TAG, "cooling dev:" + mDevice.getDeviceName()
+                            + " deactivated! throttle values < "
+                            + ThermalManager.DEFAULT_NUM_THROTTLE_VALUES);
+                    mDevice = null;
+                    return;
+                }
+                if (mDevice.getThrottlePath().equals("auto")) {
+                    mDevice.setThrottlePath("auto");
+                }
+                if (loadCoolingDevice(mDevice)) {
+                    ThermalManager.sCDevMap.put(mDevice.getDeviceId(), mDevice);
+                }
+                mDevice = null;
+            } else if (name.equalsIgnoreCase(ZONETHROTINFO) && mZone != null) {
+                mZone.printAttributes();
+                if (mZoneCoolerBindMap != null) {
+                    mZoneCoolerBindMap.put(mZone.getZoneID(), mZone);
+                }
+                mZone = null;
+            } else if (name.equalsIgnoreCase(PROFILE)) {
+                if (mZoneCoolerBindMap != null) {
+                    ThermalManager.sProfileBindMap.put(mCurProfileName, mZoneCoolerBindMap);
+                    mZoneCoolerBindMap = new Hashtable<Integer,
+                            ThermalManager.ZoneCoolerBindingInfo>();
+                }
+            } else if (name.equalsIgnoreCase(THERMAL_THROTTLE_CONFIG)) {
+                Log.i(TAG, "Parsing Finished..");
+                // This indicates we have not seen any <Profile> tag.
+                // Consider it as if we have only one 'Default' Profile.
+                if (mNumProfiles == 0 && mZoneCoolerBindMap != null) {
+                    ThermalManager.sProfileBindMap.put(mCurProfileName, mZoneCoolerBindMap);
+                }
+                done = true;
+            } else if (name.equalsIgnoreCase(COOLINGDEVICEINFO) && mZone != null) {
+                ThermalManager.ZoneCoolerBindingInfo.CoolingDeviceInfo cDevInfo;
+                cDevInfo = mZone.getLastCoolingDeviceInstance();
+                if (cDevInfo != null) {
+                    ThermalCoolingDevice cDev = ThermalManager.sCDevMap
+                            .get(cDevInfo.getCoolingDeviceId());
+                    if (cDev == null) return;
+                    int cds = cDevInfo.getCoolingDeviceStates();
+                    // check the CDS against the number of throttle values exposed.
+                    // If exceeds, cap it.
+                    if (cds > cDev.getNumThrottleValues()) {
+                        cDevInfo.setCoolingDeviceStates(cDev.getNumThrottleValues());
+                        Log.i(TAG, "capping cdevid: " + cDevInfo.getCoolingDeviceId()
+                                + " to " + cDev.getNumThrottleValues() + " states");
+                    }
+                    if (cDevInfo.checkMaskList(cDev.getNumThrottleValues())) {
+                        // add only active cooling devices to list
+                        mZone.addCoolingDeviceToList(cDevInfo);
+                    }
+                }
+            }
+        }
+    }
+
+    private void configureDynamicTurbo() {
+        // Disable Dynamic Turbo based on the system property
+        int indx = ThermalUtils.getCoolingDeviceIndexContains("SoC");
+        if (indx != -1 && !ThermalManager.sIsDynamicTurboEnabled) {
+            String path = ThermalManager.sCoolingDeviceBasePath + indx
+                    + ThermalManager.sCoolingDeviceState;
+            ThermalUtils.writeSysfs(path, ThermalManager.DISABLE_DYNAMIC_TURBO);
+        }
+    }
+
+    public boolean init(Context context) {
+        Log.i(TAG, "Thermal Cooling manager init() called");
+
+        mContext = context;
+        ThermalParser parser;
+        if (!ThermalManager.sIsOverlays) {
+            parser = new ThermalParser(ThermalManager.sThrottleFilePath);
+        } else {
+            parser = new ThermalParser();
+        }
+
+        if (parser == null || !parser.parse()) {
+            Log.i(TAG, "thermal_throttle_config.xml parsing failed");
+            return false;
+        }
+
+        // Set this sZoneCoolerBindMap to the DefaultProfile Map
+        ThermalManager.setCurBindMap(ThermalManager.DEFAULT_PROFILE_NAME);
+
+        // Register for thermal zone state changed notifications
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(ThermalManager.ACTION_THERMAL_ZONE_STATE_CHANGED);
+        mContext.registerReceiver(mThermalIntentReceiver, filter);
+
+        configureDynamicTurbo();
+        return true;
+    }
+
+    private final class ProfileChangeReceiver extends BroadcastReceiver {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            String action = intent.getAction();
+            if (action.equals(ThermalManager.ACTION_CHANGE_THERMAL_PROFILE)) {
+                String profName = intent.getStringExtra(ThermalManager.EXTRA_PROFILE);
+                if (profName != null) {
+                    ThermalManager.changeThermalProfile(profName);
+                }
+            }
+        }
+    }
+
+    private void incrementCrticalZoneCount() {
+        synchronized(sCriticalZonesCountLock) {
+            mCriticalZonesCount++;
+        }
+    }
+
+    private final class ThermalZoneReceiver extends BroadcastReceiver {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            String zoneName = intent.getStringExtra(ThermalManager.EXTRA_NAME);
+            String profName = intent.getStringExtra(ThermalManager.EXTRA_PROFILE);
+            int thermZone = intent.getIntExtra(ThermalManager.EXTRA_ZONE, -1);
+            int thermState = intent.getIntExtra(ThermalManager.EXTRA_STATE, 0);
+            int thermEvent = intent.getIntExtra(ThermalManager.EXTRA_EVENT, 0);
+            int zoneTemp = intent.getIntExtra(ThermalManager.EXTRA_TEMP, 0);
+
+            // Assume 'Default' profile if there is no profile parameter
+            // as part of the intent.
+            if (profName == null) {
+                profName = ThermalManager.DEFAULT_PROFILE_NAME;
+            }
+
+            Log.i(TAG, "Received THERMAL INTENT:(ProfileName, ZoneName, State, EventType, Temp):"
+                    + "(" + profName + ", " + zoneName + ", " + thermState + ", "
+                    + ThermalZone.getEventTypeAsString(thermEvent) + ", " + zoneTemp + ")");
+
+            Hashtable<Integer, ThermalManager.ZoneCoolerBindingInfo> mBindMap =
+                    ThermalManager.getBindMap(profName);
+            if (mBindMap == null) {
+                Log.i(TAG, "mBindMap null inside ThermalZoneReceiver");
+                return;
+            }
+
+            ThermalManager.ZoneCoolerBindingInfo zoneCoolerBindInfo = mBindMap.get(thermZone);
+            if (zoneCoolerBindInfo == null) {
+                Log.i(TAG, "zoneCoolerBindInfo null for zoneID" + thermZone);
+                return;
+            }
+
+            boolean flag = zoneCoolerBindInfo.getCriticalActionShutdown() == 1;
+            int lastState = zoneCoolerBindInfo.getLastState();
+            if (thermState < lastState) {
+                ThermalManager.updateZoneCriticalPendingMap(thermZone,
+                        ThermalManager.CRITICAL_FALSE);
+            } else if (thermState == lastState && flag) {
+                /* no telephony support, so (!isEmergencyCallOnGoing) is true */
+                if (true) {
+                    doShutdown();
+                } else {
+                    // increment the count of zones in critical state pending on shutdown
+                    ThermalManager.updateZoneCriticalPendingMap(thermZone,
+                            ThermalManager.CRITICAL_TRUE);
+                }
+            }
+
+            /* if THERMALOFF is the zone state, it is guaranteed that the zone has transitioned
+            from a higher state, due to a low event, to THERMALOFF.Hence take de-throttling action
+            corresponding to NORMAL */
+            if (thermState == ThermalManager.THERMAL_STATE_OFF) {
+                thermState = ThermalManager.THERMAL_STATE_NORMAL;
+            }
+            handleThermalEvent(thermZone, thermEvent, thermState, zoneCoolerBindInfo);
+        }
+    }
+
+    private boolean loadCoolingDevice(ThermalCoolingDevice device) {
+        Class cls;
+        Method throttleMethod;
+        String classPath = device.getClassPath();
+
+        if (classPath == null) {
+            Log.i(TAG, "ClassPath not found");
+            return false;
+        }
+
+        if (classPath.equalsIgnoreCase("none") || classPath.equalsIgnoreCase("auto")
+                || classPath.equalsIgnoreCase("AppAgent")) {
+            Log.i(TAG, "ClassPath: none/auto/AppAgent");
+            return true;
+        }
+
+        /* Load the cooling device class */
+        try {
+            cls = Class.forName(classPath);
+            device.setDeviceClass(cls);
+        } catch (Throwable e) {
+            Log.i(TAG, "Unable to load class " + classPath);
+            return false;
+        }
+
+        /* Initialize the cooling device class */
+        try {
+            Class partypes[] = new Class[3];
+            partypes[0] = Context.class;
+            partypes[1] = String.class;
+            partypes[2] = ArrayList.class;
+            Method init = cls.getMethod("init", partypes);
+            Object arglist[] = new Object[3];
+            arglist[0] = mContext;
+            arglist[1] = device.getThrottlePath();
+            arglist[2] = device.getThrottleValuesList();
+            init.invoke(cls, arglist);
+        } catch (NoSuchMethodException e) {
+            Log.i(TAG, "NoSuchMethodException caught in device class init: " + classPath);
+        } catch (SecurityException e) {
+            Log.i(TAG, "SecurityException caught in device class init: " + classPath);
+        } catch (IllegalAccessException e) {
+            Log.i(TAG, "IllegalAccessException caught in device class init: " + classPath);
+        } catch (IllegalArgumentException e) {
+            Log.i(TAG, "IllegalArgumentException caught in device class init: " + classPath);
+        } catch (ExceptionInInitializerError e) {
+            Log.i(TAG, "ExceptionInInitializerError caught in device class init: " + classPath);
+        } catch (InvocationTargetException e) {
+            Log.i(TAG, "InvocationTargetException caught in device class init: " + classPath);
+        }
+
+        /* Get the throttleDevice method from cooling device class */
+        try {
+            Class partypes[] = new Class[1];
+            partypes[0] = Integer.TYPE;
+            throttleMethod = cls.getMethod("throttleDevice", partypes);
+            device.setThrottleMethod(throttleMethod);
+        } catch (NoSuchMethodException e) {
+            Log.i(TAG, "NoSuchMethodException caught initializing throttle function");
+        } catch (SecurityException e) {
+            Log.i(TAG, "SecurityException caught initializing throttle function");
+        }
+
+        return true;
+    }
+
+
+    public void doShutdown() {
+        ThermalUtils.writeSysfs(THERMAL_SHUTDOWN_NOTIFY_PATH, 1);
+        /* We must avoid reboot after shutdown. */
+        SystemProperties.set("sys.property_forcedshutdown", "1");
+        Intent criticalIntent = new Intent(Intent.ACTION_REQUEST_SHUTDOWN);
+        criticalIntent.putExtra(Intent.EXTRA_KEY_CONFIRM, false);
+        criticalIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        Log.i(TAG, "Thermal Service initiating shutdown");
+        mContext.startActivity(criticalIntent);
+    }
+
+    public void registerProfChangeListener() {
+        IntentFilter profChangeIntentFilter = new IntentFilter();
+        profChangeIntentFilter.addAction(ThermalManager.ACTION_CHANGE_THERMAL_PROFILE);
+        // TODO: add some permission (BRICK ??) to protect it from third party apps
+        mContext.registerReceiver(mProfChangeReceiver, profChangeIntentFilter);
+        mProfChangeListenerInitialized = true;
+    }
+
+    /* Method to handle the thermal event based on HIGH or LOW event */
+    private void handleThermalEvent(int zoneId, int eventType, int thermalState,
+            ThermalManager.ZoneCoolerBindingInfo zoneCoolerBindInfo) {
+        ThermalCoolingDevice tDevice;
+        int deviceId;
+        int existingState, targetState;
+        int currThrottleMask, currDethrottleMask;
+        int index = 0;
+
+        if (zoneCoolerBindInfo.getCoolingDeviceInfoList() == null)
+            return;
+
+        for (ThermalManager.ZoneCoolerBindingInfo.CoolingDeviceInfo CdeviceInfo :
+                zoneCoolerBindInfo.getCoolingDeviceInfoList()) {
+            int coolingDeviceState =  thermalState /
+                    zoneCoolerBindInfo.getZoneToCoolDevBucketSizeIndex(index);
+            // cap it
+            coolingDeviceState = (coolingDeviceState > (CdeviceInfo.getCoolingDeviceStates() - 1))
+                    ? CdeviceInfo.getCoolingDeviceStates() - 1 : coolingDeviceState;
+            int finalThrottleState = coolingDeviceState *
+                    zoneCoolerBindInfo.getCoolDevToThrottBucketSizeIndex(index);
+            // cap it
+            finalThrottleState = (finalThrottleState > (CdeviceInfo.getMaxThrottleStates() - 1))
+                    ? CdeviceInfo.getMaxThrottleStates() - 1 : finalThrottleState;
+            index++;
+            if (ThermalManager.THERMAL_HIGH_EVENT == eventType) {
+                ArrayList<Integer> throttleMaskList = CdeviceInfo.getThrottleMaskList();
+                if (throttleMaskList == null) continue;
+                // cap to avoid out of bound exception
+                coolingDeviceState = (coolingDeviceState > throttleMaskList.size() - 1)
+                        ? throttleMaskList.size() - 1 : coolingDeviceState;
+                currThrottleMask = throttleMaskList.get(coolingDeviceState);
+                deviceId = CdeviceInfo.getCoolingDeviceId();
+
+                tDevice = ThermalManager.sCDevMap.get(deviceId);
+                if (tDevice == null)
+                    continue;
+
+                if (currThrottleMask == ThermalManager.THROTTLE_MASK_ENABLE) {
+                    existingState = tDevice.getThermalState();
+                    tDevice.updateZoneState(zoneId, finalThrottleState);
+                    targetState = tDevice.getThermalState();
+
+                    /* Do not throttle if device is already in desired state.
+                     * (We can save Sysfs write)
+                     * */
+                    if (existingState != targetState) throttleDevice(deviceId, targetState);
+
+                } else {
+                     // If throttle mask is not enabled, don't do anything here.
+                }
+            }
+
+            if (ThermalManager.THERMAL_LOW_EVENT == eventType) {
+                ArrayList<Integer> dethrottleMaskList = CdeviceInfo.getDeThrottleMaskList();
+                if (dethrottleMaskList == null) continue;
+                // cap to avoid out of bound exception
+                coolingDeviceState = (coolingDeviceState > dethrottleMaskList.size() - 1)
+                        ? dethrottleMaskList.size() - 1 : coolingDeviceState;
+                currDethrottleMask = dethrottleMaskList.get(coolingDeviceState);
+                deviceId = CdeviceInfo.getCoolingDeviceId();
+
+                tDevice = ThermalManager.sCDevMap.get(deviceId);
+                if (tDevice == null)
+                    continue;
+
+                existingState = tDevice.getThermalState();
+                tDevice.updateZoneState(zoneId, finalThrottleState);
+                targetState = tDevice.getThermalState();
+
+                /* Do not dethrottle if device is already in desired state.
+                 * (We can save Sysfs write) */
+                if ((existingState != targetState) &&
+                        (currDethrottleMask == ThermalManager.DETHROTTLE_MASK_ENABLE)) {
+                    throttleDevice(deviceId, targetState);
+                }
+            }
+        }
+
+    }
+
+    /*
+     * defaultThrottleMethod is called for cooling devices for which an additional
+     * plugin file is not provided. Since the throttle path and the throttle values
+     * are known, we dont need an additional plugin to implement the policy. This info
+     * is provided via thermal_throttle_config file. If for a cooling device,
+     * Assumptions -
+     * 1. If CDeviceClassPath is 'auto' this triggers a call to defaultThrottleMethod().
+     * if a false throttle path is provided, the write fails and function exits gracefully
+     * with a warning message.
+     * 2. If 'auto' mode is used for CDeviceClassPath, and no throttle values are provided,
+     * thermal state will be written.
+     * 3. If CDeviceThrottlePath is 'auto', then throttle path will be constrcuted.
+     * The Cooling device name should contain a subset string that matches the type for
+     * /sys/class/thermal/cooling_deviceX/type inorder to find the right index X
+     * 4. CDeviceThrottlePath is null no write operation will be done
+     **/
+    private void defaultThrottleMethod(ThermalCoolingDevice cdev, int level) {
+        int finalValue;
+        String throttlePath = null;
+
+        if (cdev == null) return;
+
+        if (level < cdev.getNumThrottleValues() - 1) {
+            try {
+                ArrayList<Integer> values = cdev.getThrottleValuesList();
+                if (values == null || values.size() == 0) {
+                    finalValue = level;
+                } else {
+                    finalValue =  values.get(level);
+                }
+
+                throttlePath = cdev.getThrottlePath();
+                if (throttlePath == null) {
+                    Log.w(TAG, "throttle path is null");
+                    return;
+                }
+
+                if (!ThermalUtils.isFileExists(throttlePath)) {
+                    Log.w(TAG, "invalid throttle path for cooling device:" + cdev.getDeviceName());
+                    return;
+                }
+
+                if (ThermalUtils.writeSysfs(throttlePath, finalValue) == -1) {
+                    Log.w(TAG, "write to sysfs failed");
+                }
+            } catch (IndexOutOfBoundsException e) {
+                Log.w(TAG, "IndexOutOfBoundsException caught in defaultThrottleMethod()");
+            }
+        }
+    }
+
+    /* Method to throttle cooling device */
+    private void throttleDevice(int coolingDevId, int throttleLevel) {
+        /* Retrieve the cooling device based on ID */
+        ThermalCoolingDevice dev = ThermalManager.sCDevMap.get(coolingDevId);
+        if (dev != null) {
+            if (dev.getClassPath() != null && dev.getClassPath().equalsIgnoreCase("auto")) {
+                defaultThrottleMethod(dev, throttleLevel);
+            } else {
+                Class c = dev.getDeviceClass();
+                Method throt = dev.getThrottleMethod();
+                if (throt == null)
+                    return;
+                Object arglist[] = new Object[1];
+                arglist[0] = new Integer(throttleLevel);
+
+                // Invoke the throttle method passing the throttle level as parameter
+                try {
+                    throt.invoke(c, arglist);
+                } catch (IllegalAccessException e) {
+                    Log.i(TAG, "IllegalAccessException caught throttleDevice() ");
+                } catch (IllegalArgumentException e) {
+                    Log.i(TAG, "IllegalArgumentException caught throttleDevice() ");
+                } catch (ExceptionInInitializerError e) {
+                    Log.i(TAG, "ExceptionInInitializerError caught throttleDevice() ");
+                } catch (SecurityException e) {
+                    Log.i(TAG, "SecurityException caught throttleDevice() ");
+                } catch (InvocationTargetException e) {
+                    Log.i(TAG, "InvocationTargetException caught throttleDevice() ");
+                }
+            }
+        } else {
+            Log.i(TAG, "throttleDevice: Unable to retrieve cooling device " + coolingDevId);
+        }
+    }
+
+    public void unregisterReceivers() {
+        if (mContext != null) {
+            mContext.unregisterReceiver(mThermalIntentReceiver);
+            // During Thermal Service init, when parsing fails, we
+            // unregister all receivers here. mProfChangeReceiver
+            // might not have been initialized at that time because
+            // we initialize this only after starting the Default profile.
+            if (mProfChangeListenerInitialized) {
+                mContext.unregisterReceiver(mProfChangeReceiver);
+            }
+        }
+    }
+}
diff --git a/ituxd/src/com/intel/thermal/ThermalCoolingDevice.java b/ituxd/src/com/intel/thermal/ThermalCoolingDevice.java
new file mode 100644
index 0000000..4a97eb0
--- /dev/null
+++ b/ituxd/src/com/intel/thermal/ThermalCoolingDevice.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright 2014 Intel Corporation All Rights Reserved.
+ *
+ * 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.
+ */
+
+package com.intel.thermal;
+
+import android.util.Log;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+
+/**
+ * This class contains the cooling device specific information. It also contains
+ * a reference to the actual throttle function.
+ *
+ * @hide
+ */
+public class ThermalCoolingDevice {
+
+    private static final String TAG = "ThermalCoolingDevice";
+
+    private String mDeviceName;
+
+    private String mClassPath;
+
+    private String mThrottlePath;
+
+    private int mCurrentThermalState;
+
+    private int mDeviceId;
+
+    private Class mDeviceClass;
+
+    private Method mThrottleMethod;
+
+    /* Maintains list of zoneid's under which this cooling device falls. */
+    private ArrayList<Integer> mZoneIdList = new ArrayList<Integer>();
+
+    /* Maintains corresponding state of zone present in mZoneidList */
+    private ArrayList<Integer> mZoneStateList = new ArrayList<Integer>();
+
+    /* List of values used to throttle this cooling device */
+    private ArrayList<Integer> mThrottleValues = null;
+
+    private int mNumThrottleValues = ThermalManager.DEFAULT_NUM_THROTTLE_VALUES;
+
+    public ThermalCoolingDevice() {
+        mCurrentThermalState = -1;
+        mThrottlePath = "auto";
+        mClassPath = "auto";
+    }
+
+    public void setNumThrottleValues(int num) {
+        mNumThrottleValues = num;
+    }
+
+    public int getNumThrottleValues() {
+        return mNumThrottleValues;
+    }
+
+    public void setDeviceName(String Name) {
+        mDeviceName = Name;
+    }
+
+    public String getDeviceName() {
+        return mDeviceName;
+    }
+
+    public void setDeviceId(int deviceId) {
+        mDeviceId = deviceId;
+    }
+
+    public int getDeviceId() {
+        return mDeviceId;
+    }
+
+    public String getClassPath() {
+        return mClassPath;
+    }
+
+    public void setClassPath(String Path) {
+        mClassPath = Path;
+    }
+
+    public Class getDeviceClass() {
+        return mDeviceClass;
+    }
+
+    public void setDeviceClass(Class cls) {
+        mDeviceClass = cls;
+    }
+
+    public Method getThrottleMethod() {
+        return mThrottleMethod;
+    }
+
+    public void setThrottleMethod(Method method) {
+        mThrottleMethod = method;
+    }
+
+    public String getThrottlePath() {
+        return mThrottlePath;
+    }
+
+    public void setThrottlePath(String path) {
+        if (path.equalsIgnoreCase("auto") && !mDeviceName.equalsIgnoreCase("battery")) {
+            //construct the throttle path
+            int indx = ThermalUtils.getCoolingDeviceIndexContains(mDeviceName);
+            if (indx != -1) {
+                mThrottlePath = ThermalManager.sCoolingDeviceBasePath + indx +
+                        ThermalManager.sCoolingDeviceState;
+            } else {
+                mThrottlePath = "invalid";
+            }
+        } else {
+            mThrottlePath = path;
+        }
+    }
+
+    public ArrayList<Integer> getZoneIdList() {
+        return mZoneIdList;
+    }
+
+    public ArrayList<Integer> getZoneStateList() {
+        return mZoneStateList;
+    }
+
+    public ArrayList<Integer> getThrottleValuesList() {
+        return mThrottleValues;
+    }
+
+    public void setThrottleValuesList(ArrayList<Integer> list) {
+        mThrottleValues = list;
+        mNumThrottleValues = list.size();
+    }
+    /**
+     * Sets the current thermal state of cooling device which will be maximum of
+     * all states of zones under which this cooling device falls.
+     */
+    private void updateCurrentThermalState() {
+        int state = 0;
+        for (Integer coolingDevState : mZoneStateList) {
+            state = Math.max(state, coolingDevState);
+        }
+        mCurrentThermalState = state;
+    }
+
+    /**
+     * Adds zoneID and its thermal state to mListOfZoneIDs and
+     * mListOfTStatesOfZones array. If zoneId exists then its thermal state is
+     * updated else zoneId and its state will be added to array.
+     */
+    public void updateZoneState(int zoneId, int state) {
+        int index = -1;
+
+        if (!mZoneIdList.isEmpty()) {
+            index = mZoneIdList.indexOf(zoneId);
+        }
+
+        // Entry does not exist
+        if (index == -1) {
+            mZoneIdList.add(zoneId);
+            mZoneStateList.add(state);
+        } else {
+            mZoneStateList.set(index, state);
+        }
+
+        updateCurrentThermalState();
+    }
+
+    public int getThermalState() {
+        return mCurrentThermalState;
+    }
+
+}
diff --git a/ituxd/src/com/intel/thermal/ThermalEvent.java b/ituxd/src/com/intel/thermal/ThermalEvent.java
new file mode 100644
index 0000000..ebc2e79
--- /dev/null
+++ b/ituxd/src/com/intel/thermal/ThermalEvent.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2014 Intel Corporation All Rights Reserved.
+ *
+ * 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.
+ */
+
+package com.intel.thermal;
+
+/**
+ * The ThermalEvent class contains strings and constants used for values
+ * in the ACTION_THERMAL_ZONE_STATE_CHANGED Intent.
+ *
+ * @hide
+ */
+public class ThermalEvent {
+    public int mZoneId, mEventType, mThermalLevel, mZoneTemp;
+    public String mZoneName, mProfName;
+
+    ThermalEvent(int id, int type, int state, int temp, String zoneName, String profName) {
+        mZoneId = id;
+        mEventType = type;
+        mThermalLevel = state;
+        mZoneTemp = temp;
+        mZoneName = zoneName;
+        mProfName = profName;
+    }
+}
diff --git a/ituxd/src/com/intel/thermal/ThermalManager.java b/ituxd/src/com/intel/thermal/ThermalManager.java
new file mode 100644
index 0000000..b68bd3d
--- /dev/null
+++ b/ituxd/src/com/intel/thermal/ThermalManager.java
@@ -0,0 +1,788 @@
+/*
+ * Copyright 2014 Intel Corporation All Rights Reserved.
+ *
+ * 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.
+ */
+
+package com.intel.thermal;
+
+import android.content.Context;
+import android.content.Intent;
+import android.os.SystemProperties;
+import android.os.UserHandle;
+import android.util.Log;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.NumberFormatException;
+import java.lang.StringBuilder;
+import java.util.ArrayList;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingQueue;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.NoSuchElementException;
+/**
+ * The ThermalManager class contains data structures that are common to both
+ * Thermal Sensor/Zone and Cooling device parts.
+ *
+ * @hide
+ */
+public class ThermalManager {
+    private static final String TAG = "ThermalManager";
+    private static Context sContext;
+    private static String sVersion;
+    private static String sCurProfileName;
+    private static String sProfileNameList;
+    private static int sProfileCount;
+    private static final String ITUX_VERSION_PROPERTY = "ro.thermal.ituxversion";
+    /* Parameter needed for reading configuration files */
+    public static final String SENSOR_FILE_NAME = "thermal_sensor_config.xml";
+    public static final String THROTTLE_FILE_NAME = "thermal_throttle_config.xml";
+    public static final String DEFAULT_DIR_PATH = "/system/etc/";
+    public static final String DEBUG_DIR_PATH = "/data/";
+    public static String sSensorFilePath;
+    public static String sThrottleFilePath;
+    /* *XmlId's are assigned if config files are choosen from overlays */
+    public static int sSensorFileXmlId = -1;
+    public static int sThrottleFileXmlId = -1;
+    /* Set to true if config are available in DEFAULT or DEBUG path */
+    public static boolean sIsConfigFiles = false;
+    /* Whether we are using the config files from overlays directory or from /etc/ */
+    public static boolean sIsOverlays = false;
+    /* Parameters required for MaxTrip data */
+    public static final String TJMAX_PATH = "/sys/devices/platform/coretemp.0/temp2_crit";
+    public static final int sDefaultTjMax = 90000;
+    public static int sTjMaxTemp;
+    public static final int sMaxSkinTrip = 150000;
+
+    public static String sUEventDevPath = "DEVPATH=/devices/virtual/thermal/thermal_zone";
+    /**
+     * Thermal Zone State Changed Action: This is broadcast when the state of a
+     * thermal zone changes.
+     */
+    public static final String ACTION_THERMAL_ZONE_STATE_CHANGED =
+            "com.intel.thermal.action.THERMAL_ZONE_STATE_CHANGED";
+
+    public static PlatformInfo sPlatformInfo;
+    public static ThermalCooling sCoolingManager;
+    /* List of Thermal zones for current profile. Access protected by 'sProfileSwitchLock' */
+    private static ArrayList<ThermalZone> sThermalZonesList;
+
+    /* Hashtable of (ProfileName and ListOfZonesUnderThisProfile) */
+    public static Hashtable<String, ArrayList<ThermalZone>> sProfileZoneMap =
+            new Hashtable<String, ArrayList<ThermalZone>>();
+
+    /**
+     * This holds the map for the current profile. Access protected by 'sProfileSwitchLock'.
+     * Should be initialized for every profile change.
+     */
+    private static Hashtable<Integer, ZoneCoolerBindingInfo> sZoneCoolerBindMap =
+            new Hashtable<Integer, ZoneCoolerBindingInfo>();
+
+    /* Hashtable of (ProfileName and Hashtable(zoneID, ZoneCoolerBindingInfo) object */
+    public static Hashtable<String, Hashtable<Integer, ZoneCoolerBindingInfo>> sProfileBindMap =
+            new Hashtable<String, Hashtable<Integer, ZoneCoolerBindingInfo>>();
+
+    /* Hashtable of (Cooling Device ID and ThermalCoolingDevice object) */
+    public static Hashtable<Integer, ThermalCoolingDevice> sCDevMap =
+            new Hashtable<Integer, ThermalCoolingDevice>();
+
+    /* Hashtable of sensor name and sensor object */
+    public static Hashtable<String, ThermalSensor> sSensorMap =
+            new Hashtable<String, ThermalSensor>();
+
+    public static final int CRITICAL_TRUE = 1;
+    public static final int CRITICAL_FALSE = 0;
+    /* sZoneCriticalPendingMap stores info whether a zone is in critical state and platform
+     * shutdown has not yet occured due to some scenario like ongoing emergency call
+     **/
+    public static Hashtable<Integer, Integer> sZoneCriticalPendingMap = null;
+    /* this lock is to access sZoneCriticalPendingMap synchronously */
+    private static final Object sCriticalPendingLock = new Object();
+    /* this count keeps track of number of zones in pending critical state.When
+     * sZoneCriticalPendingMap is updated, the count is either incremented or
+     * decremented depending on whether criical pending flag for a zone is true/
+     * false. By keeping a count we can avoid scanning through the entire map to
+     * see if there is a pending critical shutdown
+     **/
+    private static int sCriticalZonesCount = 0;
+
+    /* Blocking queue to hold thermal events from thermal zones */
+    private static final int EVENT_QUEUE_SIZE = 10;
+
+    public static BlockingQueue<ThermalEvent> sEventQueue = new ArrayBlockingQueue<ThermalEvent>(EVENT_QUEUE_SIZE);
+    /* this lock is to handle uevent callbacks synchronously */
+    private static final Object sLock = new Object();
+
+    /**
+     * Extra for {@link ACTION_THERMAL_ZONE_STATE_CHANGED}:
+     * integer containing the thermal zone.
+     */
+    public static final String EXTRA_ZONE = "zone";
+
+    /**
+     * Extra for {@link ACTION_THERMAL_ZONE_STATE_CHANGED}:
+     * integer containing the thermal state of the zone.
+     */
+    public static final String EXTRA_STATE = "state";
+
+    /**
+     * Extra for {@link ACTION_THERMAL_ZONE_STATE_CHANGED}:
+     * integer containing the thermal event type for the zone.
+     */
+    public static final String EXTRA_EVENT = "event";
+
+    /**
+     * Extra for {@link ACTION_THERMAL_ZONE_STATE_CHANGED}:
+     * integer containing the temperature of the zone.
+     */
+    public static final String EXTRA_TEMP = "temp";
+    public static final String ACTION_CHANGE_THERMAL_PROFILE =
+            "android.intent.action.CHANGE_THERMAL_PROFILE";
+    /**
+     * Extra for {@link ACTION_THERMAL_ZONE_STATE_CHANGED}:
+     * String containing the name of the zone.
+     */
+    public static final String EXTRA_NAME = "name";
+    public static final String EXTRA_PROFILE = "Profile";
+
+    private static Intent sQueryProfileIntent;
+    public static final String ACTION_QUERY_THERMAL_PROFILE =
+            "com.intel.thermal.action.QUERY_THERMAL_PROFILE";
+    public static final String ACTION_KILL = "kill";
+
+    /**
+     * Integer containing the number of thermal profiles.
+     */
+    public static final String EXTRA_NUM_PROFILE = "NumProfiles";
+    /**
+     * Space separated string containing list of thermal profile names.
+     */
+    public static final String EXTRA_PROFILE_LIST = "ProfileList";
+    /**
+     * String containing current thermal profile name.
+     */
+    public static final String EXTRA_CUR_PROFILE = "CurProfile";
+
+    /* values for "STATE" field in the THERMAL_STATE_CHANGED Intent */
+    public static final int THERMAL_STATE_OFF = -1;
+
+    public static final int THERMAL_STATE_NORMAL = 0;
+
+    public static final int THERMAL_STATE_WARNING = 1;
+
+    public static final int THERMAL_STATE_ALERT = 2;
+
+    public static final int THERMAL_STATE_CRITICAL = 3;
+
+    public static final int DEFAULT_NUM_THROTTLE_VALUES = 4;
+
+    // 5 including TOFF and TCRITICAL
+    public static final int DEFAULT_NUM_ZONE_STATES = 5;
+
+    public static final String STATE_NAMES[] = {
+            "OFF", "NORMAL", "WARNING", "ALERT", "CRITICAL"
+    };
+
+    /* values of the "EVENT" field in the THERMAL_STATE_CHANGED intent */
+    /* Indicates type of event */
+    public static final int THERMAL_LOW_EVENT = 0;
+
+    public static final int THERMAL_HIGH_EVENT = 1;
+
+    public static final int THERMAL_EMUL_TEMP_EVENT = 2;
+
+    public static final int INVALID_TEMP = 0xDEADBEEF;
+
+    /* base sysfs path for sensors */
+    public static final String sSysfsSensorBasePath = "/sys/class/thermal/thermal_zone";
+
+    public static final String sSysfsSensorHighTempPath = "trip_point_1_temp";
+
+    public static final String sSysfsSensorLowTempPath = "trip_point_0_temp";
+
+    public static final String sCoolingDeviceBasePath = "/sys/class/thermal/cooling_device";
+
+    public static final String sCoolingDeviceState = "/cur_state";
+
+    public static final int THROTTLE_MASK_ENABLE = 1;
+
+    public static final int DETHROTTLE_MASK_ENABLE = 1;
+
+    /**
+     * Magic number (agreed upon between the Thermal driver and the Thermal Service)
+     * symbolising Dynamic Turbo OFF
+     */
+    public static final int DISABLE_DYNAMIC_TURBO = 0xB0FF;
+
+    public static boolean sIsDynamicTurboEnabled = false;
+
+    /* thermal notifier system properties for shutdown action */
+    public static boolean sShutdownTone = false;
+
+    public static boolean sShutdownToast = false;
+
+    public static boolean sShutdownVibra = false;
+
+    /* Name of default Thermal Profile */
+    public static final String DEFAULT_PROFILE_NAME = "Default";
+
+    /* Lock protecting profile-switch */
+    private static final Object sProfileSwitchLock = new Object();
+
+    /**
+     * This class stores the zone throttle info. It contains the zoneID,
+     * CriticalShutdown flag and CoolingDeviceInfo arraylist.
+     */
+    public static class ZoneCoolerBindingInfo {
+        private int mZoneID;
+        // max states includes TOFF also.
+        // if user provides k threshold values in XML.
+        // mMaxStates = k + 1(for critical) + 1(for TOFF)
+        // this is same as the max states stored in corresponding zone object
+        protected int mMaxStates;
+        private int mIsCriticalActionShutdown;
+
+        /* cooler ID mask, 1 - throttle device, 0- no action, -1- dont care */
+        private ArrayList<CoolingDeviceInfo> mCoolingDeviceInfoList = null;
+
+        // ManyToOneMapping: ZoneStates >= CoolingDeviceStates
+        private ArrayList<Integer> mZoneToCoolDevBucketSize = null;
+
+        // OneToOneMapping: CoolingDeviceStates >= ThrottleValues
+        private ArrayList<Integer> mCoolDevToThrottBucketSize = null;
+
+        private CoolingDeviceInfo lastCoolingDevInfoInstance = null;
+
+        public ZoneCoolerBindingInfo() {
+            mZoneToCoolDevBucketSize = new ArrayList<Integer>();
+            mCoolDevToThrottBucketSize = new ArrayList<Integer>();
+        }
+
+        public int getLastState() {
+            // mMaxStates = k + 1(for critical) + 1(for TOFF)
+            return mMaxStates - 2;
+        }
+
+        public void setMaxStates(int state) {
+            mMaxStates = state;
+        }
+
+        public int getMaxStates() {
+            return mMaxStates;
+        }
+
+        public void setZoneToCoolDevBucketSize() {
+            int size = 1;
+            int zoneStates = getMaxStates();
+            for (CoolingDeviceInfo coolDev : mCoolingDeviceInfoList) {
+                size = (zoneStates - 1) / coolDev.getCoolingDeviceStates();
+                mZoneToCoolDevBucketSize.add(size == 0 ? 1 : size);
+            }
+        }
+
+        public int getZoneToCoolDevBucketSizeIndex(int index) {
+            if (mZoneToCoolDevBucketSize.size() > index)
+                return mZoneToCoolDevBucketSize.get(index);
+
+            return 1;
+        }
+
+        public int getCoolDevToThrottBucketSizeIndex(int index) {
+            if (mZoneToCoolDevBucketSize.size() > index)
+                return mCoolDevToThrottBucketSize.get(index);
+
+            return 1;
+        }
+
+        public void setCoolDevToThrottBucketSize() {
+            int size = 1;
+            for (CoolingDeviceInfo coolDev : mCoolingDeviceInfoList) {
+                size = coolDev.getMaxThrottleStates() / coolDev.getCoolingDeviceStates();
+                mCoolDevToThrottBucketSize.add(size == 0 ? 1 : size);
+            }
+        }
+
+        public void printAttributes() {
+            if (mCoolingDeviceInfoList == null) return;
+            StringBuilder s = new StringBuilder();
+            for (CoolingDeviceInfo c : mCoolingDeviceInfoList) {
+                if (c != null) {
+                    s.append(c.getCoolingDeviceId());
+                    s.append(",");
+                }
+            }
+            Log.i(TAG, "zone id:" + mZoneID + " coolingDevID  mapped:" + s.toString());
+        }
+
+        public void printMappedAttributes() {
+            if (mZoneToCoolDevBucketSize == null || mCoolDevToThrottBucketSize == null) return;
+            StringBuilder s = new StringBuilder();
+            for (int bs : mZoneToCoolDevBucketSize) {
+                s.append(bs);
+                s.append(",");
+            }
+            Log.i(TAG, "zone id:" + mZoneID + " ZoneToCoolDevBucketSize:" + s.toString());
+            // clear the string
+            s.delete(0,s.length());
+            for (int bs : mCoolDevToThrottBucketSize) {
+                s.append(bs);
+                s.append(",");
+            }
+            Log.i(TAG, "zone id:" + mZoneID + " CoolDevToThrottBucketSize:" + s.toString());
+        }
+
+        public class CoolingDeviceInfo {
+            private int mCDeviceID;
+
+            // mCoolingDeviceState is number of device states exposed under a zone.
+            // this must be less than or equal to its total number of throttle values
+            private int mCoolingDeviceStates = DEFAULT_NUM_THROTTLE_VALUES;
+
+            // store a copy here for fast lookup during throttling/dethrottling
+            private int mMaxThrottleStates = 0;
+            private ArrayList<Integer> mDeviceThrottleMask = null;
+
+            private ArrayList<Integer> mDeviceDethrottleMask = null;
+
+            public CoolingDeviceInfo() {
+            }
+
+            public int getMaxThrottleStates() {
+                return mMaxThrottleStates;
+            }
+
+            public boolean checkMaskList(int throttleStates) {
+                boolean ret = true;
+                // if the list is empty this mean, THROTTLE MASK and/or
+                // DETHTOTTLE mask was not provided. Initialize default mask.
+                if (mDeviceThrottleMask ==  null) {
+                    mDeviceThrottleMask = new ArrayList<Integer>();
+                    for (int i = 0; i < mCoolingDeviceStates; i++) {
+                        mDeviceThrottleMask.add(THROTTLE_MASK_ENABLE);
+                    }
+                } else if (mDeviceThrottleMask.size() != mCoolingDeviceStates) {
+                    Log.i(TAG, "cdevid:" + mCDeviceID
+                            + " has mismatch in Cooling device state and mask array!deactivate!");
+                    ret = false;
+                }
+
+                if (mDeviceDethrottleMask ==  null) {
+                    mDeviceDethrottleMask = new ArrayList<Integer>();
+                    for (int i = 0; i < mCoolingDeviceStates; i++) {
+                        mDeviceDethrottleMask.add(DETHROTTLE_MASK_ENABLE);
+                    }
+                } else if (mDeviceDethrottleMask.size() != mCoolingDeviceStates) {
+                    Log.i(TAG, "cdevid:" + mCDeviceID
+                            + " has mismatch in Cooling device state and mask array!deactivate!");
+                    ret = false;
+                }
+                if (ret) {
+                    mMaxThrottleStates = throttleStates;
+                }
+                return ret;
+            }
+
+            public int getCoolingDeviceId() {
+                return mCDeviceID;
+            }
+
+            public void setCoolingDeviceId(int deviceID) {
+                mCDeviceID = deviceID;
+            }
+
+            public int getCoolingDeviceStates() {
+                return mCoolingDeviceStates;
+            }
+
+            public void setCoolingDeviceStates(int num) {
+                mCoolingDeviceStates = num;
+            }
+
+            public ArrayList<Integer> getThrottleMaskList() {
+                return mDeviceThrottleMask;
+            }
+
+            public ArrayList<Integer> getDeThrottleMaskList() {
+                return mDeviceDethrottleMask;
+            }
+
+            public void setThrottleMaskList(ArrayList<Integer> list) {
+                this.mDeviceThrottleMask = list;
+            }
+
+            public void setDeThrottleMaskList(ArrayList<Integer> list) {
+                this.mDeviceDethrottleMask = list;
+            }
+
+        }
+
+        public ArrayList<CoolingDeviceInfo> getCoolingDeviceInfoList() {
+            return mCoolingDeviceInfoList;
+        }
+
+        public void createNewCoolingDeviceInstance() {
+            lastCoolingDevInfoInstance = new CoolingDeviceInfo();
+        }
+
+        public CoolingDeviceInfo getLastCoolingDeviceInstance() {
+            return lastCoolingDevInfoInstance;
+        }
+
+        public void setZoneID(int zoneID) {
+            mZoneID = zoneID;
+        }
+
+        public int getZoneID() {
+            return mZoneID;
+        }
+
+        public void setCriticalActionShutdown(int val) {
+            mIsCriticalActionShutdown = val;
+        }
+
+        public int getCriticalActionShutdown() {
+            return mIsCriticalActionShutdown;
+        }
+
+        public void setCoolingDeviceInfoList(ArrayList<CoolingDeviceInfo> devinfoList) {
+            mCoolingDeviceInfoList = devinfoList;
+        }
+
+        public void initializeCoolingDeviceInfoList() {
+            mCoolingDeviceInfoList = new ArrayList<CoolingDeviceInfo>();
+        }
+
+        public void addCoolingDeviceToList(CoolingDeviceInfo CdeviceInfo) {
+            mCoolingDeviceInfoList.add(CdeviceInfo);
+        }
+    }
+
+    /* platform information */
+    public static class PlatformInfo {
+       public int mMaxThermalStates;
+
+       public int getMaxThermalStates() {
+            return mMaxThermalStates;
+       }
+
+       public void printAttrs() {
+           Log.i(TAG, Integer.toString(mMaxThermalStates));
+       }
+       public PlatformInfo() {}
+    }
+
+    /* methods */
+    public ThermalManager() {
+        // empty constructor
+    }
+
+    public static void setContext(Context context) {
+        sContext = context;
+    }
+
+    public static String getVersion() {
+        return sVersion;
+    }
+
+    public static void loadiTUXVersion() {
+        sVersion = SystemProperties.get(ITUX_VERSION_PROPERTY, "none");
+        if (sVersion.equalsIgnoreCase("none")) {
+            Log.i(TAG, "iTUX Version not found!");
+        } else {
+            Log.i(TAG, "iTUX Version:" + sVersion);
+        }
+    }
+
+    public static void addThermalEvent(ThermalEvent event) {
+        try {
+            ThermalManager.sEventQueue.put(event);
+        } catch (InterruptedException ex) {
+            Log.i(TAG, "caught InterruptedException in posting to event queue");
+        }
+    }
+
+    public static void setCurBindMap(String profName) {
+        synchronized (sProfileSwitchLock) {
+            sZoneCoolerBindMap = sProfileBindMap.get(profName);
+        }
+    }
+
+    public static Hashtable<Integer, ZoneCoolerBindingInfo> getCurBindMap() {
+        synchronized (sProfileSwitchLock) {
+            return sZoneCoolerBindMap;
+        }
+    }
+
+    public static Hashtable<Integer, ZoneCoolerBindingInfo> getBindMap(String profName) {
+        return sProfileBindMap.get(profName);
+    }
+
+    private static void setCurProfileName(String profName) {
+        sCurProfileName = profName;
+    }
+
+    public static String getCurProfileName() {
+        return sCurProfileName;
+    }
+
+    private static boolean isProfileExists(String profName) {
+        if (sProfileZoneMap.get(profName) == null || sProfileBindMap.get(profName) == null) {
+            return false;
+        }
+        return true;
+    }
+
+    private static void startNewProfile(String profName) {
+        sThermalZonesList = sProfileZoneMap.get(profName);
+        sZoneCoolerBindMap = sProfileBindMap.get(profName);
+        if (sThermalZonesList == null || sZoneCoolerBindMap == null) {
+            Log.i(TAG, "Couldn't shift to profile:" + profName);
+            return;
+        }
+        initializeZoneCriticalPendingMap();
+        setCurProfileName(profName);
+        int activeZones = startMonitoringZones();
+        Log.i(TAG, activeZones + " zones found active in profile " + profName);
+        // broadcast a sticky intent for the clients
+        sendQueryProfileIntent();
+    }
+
+    public static void stopCurrentProfile() {
+        for (ThermalZone zone : sThermalZonesList) {
+            // Stop Polling threads
+            zone.stopMonitoring();
+            // Unregister UEvent/EmulTemp observers
+            zone.unregisterReceiver();
+            // Reset Parameters:
+            // Zone State: Normal, Event Type: LOW, Temperature: Normal Threshold
+            zone.setZoneState(0);
+            zone.setEventType(ThermalManager.THERMAL_LOW_EVENT);
+            zone.setZoneTemp(zone.getZoneTempThreshold(0));
+            // Send ThermalIntent with above parameters
+            // This will release all throttle controls this zone had.
+            // Since we are in the middle of a profile switch(stop),
+            // set the override parameter as true, so that this
+            // event is actually queued for processing.
+            // TODO: Find a way to take care of zones that are not
+            // present in thermal_sensor_config.xml but present in
+            // thermal_throttle_config.xml (usually from other components)
+            zone.sendThermalEvent();
+            // Reprogram the sensor thresholds if this zone supported interrupts
+            // TODO: We are reprogramming the calibrated thresholds in case the
+            // the sensor was using 'weights' and 'offset'. Hope this is fine.
+            if (zone.isUEventSupported()) {
+                zone.programThresholds((zone.getThermalSensorList()).get(0));
+            }
+        }
+    }
+
+    public static void startDefaultProfile() {
+        if (isProfileExists(DEFAULT_PROFILE_NAME)) {
+            startNewProfile(DEFAULT_PROFILE_NAME);
+        }
+        // register for Thermal Profile Change Intent only after
+        // we have started the default profile
+        sCoolingManager.registerProfChangeListener();
+    }
+
+    public static void changeThermalProfile(String newProfName) {
+        synchronized (sProfileSwitchLock) {
+            if (newProfName.equalsIgnoreCase(sCurProfileName)) {
+                Log.i(TAG, "New Profile same as current profile. Profile change request Ignored");
+                return;
+            }
+            if (!isProfileExists(newProfName)) {
+                Log.i(TAG, "New Profile does not exist in xml. Profile change request Ignored");
+                return;
+            }
+            Log.i(TAG, "ACTION_CHANGE_THERMAL_PROFILE received. New Profile: " + newProfName);
+
+            stopCurrentProfile();
+            startNewProfile(newProfName);
+        }
+    }
+
+    public static void setBucketSizeForProfiles() {
+        Iterator it = ThermalManager.sProfileZoneMap.entrySet().iterator();
+        while (it.hasNext()) {
+            Map.Entry entryProfZone = (Map.Entry) it.next();
+            String keyProfile = (String) entryProfZone.getKey();
+            sThermalZonesList = (ArrayList<ThermalZone>) entryProfZone.getValue();
+            setCurBindMap(keyProfile);
+            for (ThermalZone zone : sThermalZonesList) {
+                if (sZoneCoolerBindMap == null) {
+                    Log.e(TAG, "ZoneCoolerBindMap null while setBucketSizeForProfiles");
+                    return;
+                }
+                ZoneCoolerBindingInfo bindInfo = sZoneCoolerBindMap.get(zone.getZoneId());
+                if (bindInfo == null) {
+                    Log.e(TAG, "CoolerBindingInfo for zoneid:" + zone.getZoneId() + "not mapped");
+                    return;
+                }
+                bindInfo.setMaxStates(zone.getMaxStates());
+                bindInfo.setZoneToCoolDevBucketSize();
+                bindInfo.setCoolDevToThrottBucketSize();
+                if (zone.isUEventSupported()) {
+                    // calibration of thresholds based on weight, order
+                    if (!zone.isMaxThreshExceed())
+                        zone.calibrateThresholds();
+                }
+            }
+        }
+    }
+
+    public static int startMonitoringZones() {
+        int activeZonesCount = 0;
+        for (ThermalZone zone : sThermalZonesList) {
+            zone.computeZoneActiveStatus();
+            if (zone.getZoneActiveStatus() == false) {
+                Log.i(TAG, "deactivating inactive zone:" + zone.getZoneName());
+                continue;
+            }
+
+            ZoneCoolerBindingInfo bindInfo = sZoneCoolerBindMap.get(zone.getZoneId());
+            if (bindInfo != null) {
+                // TODO: To be conditioned under debug
+                bindInfo.printMappedAttributes();
+            }
+            if (zone.isUEventSupported()) {
+                zone.registerUevent();
+            } else {
+                // start polling thread for each zone
+                zone.startMonitoring();
+            }
+            zone.startEmulTempObserver();
+            activeZonesCount++;
+        }
+        return activeZonesCount;
+    }
+
+    public static void readShutdownNotiferProperties() {
+        try {
+            if ("1".equals(SystemProperties.get("persist.thermal.shutdown.msg", "0"))) {
+                sShutdownToast = true;
+            }
+            if ("1".equals(SystemProperties.get("persist.thermal.shutdown.tone", "0"))) {
+                sShutdownTone = true;
+            }
+            if ("1".equals(SystemProperties.get("persist.thermal.shutdown.vibra", "0"))) {
+                sShutdownVibra = true;
+            }
+        } catch (java.lang.IllegalArgumentException e) {
+            Log.e(TAG, "exception caught in reading thermal system properties");
+        }
+    }
+
+    private static void initializeZoneCriticalPendingMap() {
+        sZoneCriticalPendingMap = new Hashtable<Integer, Integer>();
+        if (sZoneCriticalPendingMap == null) return;
+        Enumeration en;
+        try {
+            // look up for zone list is performed from sZoneCoolerBindMap instead of
+            // sThermalZonesList since some non thermal zones may not have entry in
+            // sThermalZonesList. This is because such zones only have entry in throttle
+            // config file and not in sensor config files.
+            // 'sZoneCoolerBindMap' is protected by caller here.
+            en = sZoneCoolerBindMap.keys();
+            while (en.hasMoreElements()) {
+                int zone = (Integer) en.nextElement();
+                sZoneCriticalPendingMap.put(zone, CRITICAL_FALSE);
+            }
+        } catch (NoSuchElementException e) {
+            Log.i(TAG, "NoSuchElementException in InitializeZoneCriticalPendingMap()");
+        }
+    }
+
+    /*
+     * updateZoneCriticalPendingMap updates sZoneCriticalPendingMap synchronously.
+     * sCriticalZonesCount is incremented iff old value in the map for the zone is
+     * FALSE (ensures count is incremented only once for a zone) and decremented
+     * iff oldval is TRUE (ensures no negative value for count)
+     **/
+    public static boolean updateZoneCriticalPendingMap(int zoneid, int flag) {
+        synchronized (sCriticalPendingLock) {
+            if (sZoneCriticalPendingMap == null) return false;
+                Integer oldVal = sZoneCriticalPendingMap.get(zoneid);
+                if (oldVal == null) return false;
+                sZoneCriticalPendingMap.put(zoneid, flag);
+                if (oldVal == CRITICAL_FALSE && flag == CRITICAL_TRUE) {
+                   sCriticalZonesCount++;
+                } else if (oldVal == CRITICAL_TRUE && flag == CRITICAL_FALSE) {
+                   sCriticalZonesCount--;
+                }
+                return true;
+        }
+    }
+
+    public static boolean checkShutdownCondition() {
+        synchronized (sCriticalPendingLock) {
+           return sCriticalZonesCount > 0;
+        }
+    }
+
+    public static ThermalSensor getSensor(String sensorName) {
+        if (sensorName == null || sSensorMap == null) return null;
+        return sSensorMap.get(sensorName);
+    }
+
+    public static void buildProfileNameList() {
+        int count = 0;
+        StringBuilder s = new StringBuilder();
+        Iterator it = sProfileZoneMap.entrySet().iterator();
+        while (it.hasNext()) {
+            Map.Entry entry = (Map.Entry) it.next();
+            String key = (String) entry.getKey();
+            // create list of only valid profiles
+            if (isProfileExists(key)) {
+                // build a space seperate list of string
+                s.append(key);
+                s.append(" ");
+                count++;
+            }
+        }
+
+        sProfileNameList = s.toString();
+        sProfileCount = count;
+        Log.i(TAG, "profile name list:" + sProfileNameList);
+        Log.i(TAG, "profile count:" + sProfileCount);
+    }
+
+    public static void initializeStickyIntent() {
+        sQueryProfileIntent = new Intent();
+        sQueryProfileIntent.setAction(ACTION_QUERY_THERMAL_PROFILE);
+    }
+
+    private static void sendQueryProfileIntent() {
+        if (sQueryProfileIntent != null && sContext != null) {
+            sQueryProfileIntent.putExtra(ThermalManager.EXTRA_NUM_PROFILE, sProfileCount);
+            sQueryProfileIntent.putExtra(ThermalManager.EXTRA_PROFILE_LIST, sProfileNameList);
+            sQueryProfileIntent.putExtra(ThermalManager.EXTRA_CUR_PROFILE, sCurProfileName);
+            sContext.sendStickyBroadcastAsUser(sQueryProfileIntent, UserHandle.ALL);
+        }
+    }
+
+    public static void clearData() {
+        sThermalZonesList.clear();
+        // clearing hastables
+        sProfileZoneMap.clear();
+        sZoneCoolerBindMap.clear();
+        sProfileBindMap.clear();
+        sCDevMap.clear();
+        sSensorMap.clear();
+        sZoneCriticalPendingMap.clear();
+    }
+}
diff --git a/ituxd/src/com/intel/thermal/ThermalSensor.java b/ituxd/src/com/intel/thermal/ThermalSensor.java
new file mode 100644
index 0000000..78c7739
--- /dev/null
+++ b/ituxd/src/com/intel/thermal/ThermalSensor.java
@@ -0,0 +1,282 @@
+/*
+ * Copyright 2014 Intel Corporation All Rights Reserved.
+ *
+ * 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.
+ */
+
+package com.intel.thermal;
+
+import com.intel.thermal.ThermalManager;
+
+import android.util.Log;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+/**
+ * The ThermalSensor class describes the attributes of a Thermal Sensor. This
+ * class implements methods that retrieve temperature sensor information from
+ * the kernel through the native interface.
+ *
+ * @hide
+ */
+public class ThermalSensor {
+
+    private static final String TAG = "ThermalSensor";
+    private String mSensorPath;     /* sys path to read temp from */
+    private String mSensorName;     /* name of the sensor */
+    private String mInputTempPath;  /* sys path to read the current temp */
+    private String mHighTempPath;   /* sys path to set the intermediate upper threshold */
+    private String mLowTempPath;    /* sys path to set the intermediate lower threshold */
+    private String mUEventDevPath;  /* sys path for uevent listener */
+    private int mErrorCorrectionTemp; /* Temperature difference in mC */
+    private int mSensorID = -1;
+    private int mSensorState;       /* Thermal state of the sensor */
+    private int mCurrTemp;          /* Holds the latest temperature of the sensor */
+    private int mSensorSysfsIndx; /* Index of this sensor in the sysfs */
+    private boolean mIsSensorActive = false; /* Whether this sensor is active */
+
+    public void printAttrs() {
+        Log.i(TAG, "mSensorName: " + mSensorName);
+        Log.i(TAG, "mSensorPath: " + mSensorPath);
+        Log.i(TAG, "mInputTempPath: " + mInputTempPath);
+        Log.i(TAG, "mHighTempPath: " + mHighTempPath);
+        Log.i(TAG, "mLowTempPath: " + mLowTempPath);
+        Log.i(TAG, "mUEventDevPath: " + mUEventDevPath);
+        Log.i(TAG, "mErrorCorrection: " + mErrorCorrectionTemp);
+    }
+
+    private void setSensorSysfsPath() {
+        int indx = ThermalUtils.getThermalZoneIndex(mSensorName);
+        // The battery subsystem exposes sensors under different names.
+        // The only commonality among them is that all of them contain
+        // the string "battery".
+        if (indx == -1 && mSensorName.contains("battery")) {
+            indx = ThermalUtils.getThermalZoneIndexContains("battery");
+        }
+
+        if (indx != -1) {
+            mSensorPath = ThermalManager.sSysfsSensorBasePath + indx + "/";
+        }
+
+        mSensorSysfsIndx = indx;
+    }
+
+    public boolean getSensorActiveStatus() {
+        return mIsSensorActive;
+    }
+
+    public String getSensorSysfsPath() {
+        return mSensorPath;
+    }
+
+    public ThermalSensor() {
+        mSensorState = ThermalManager.THERMAL_STATE_OFF;
+        mCurrTemp = ThermalManager.INVALID_TEMP;
+        mSensorPath = "auto";
+        mInputTempPath = "auto";
+        mHighTempPath = "auto";
+        mLowTempPath = "auto";
+        mUEventDevPath = "auto";
+
+        // Set default value of 'correction temperature' to 1000mC
+        mErrorCorrectionTemp = 1000;
+    }
+
+    public int getSensorID() {
+        return mSensorID;
+    }
+
+    public int getSensorSysfsIndx() {
+        return mSensorSysfsIndx;
+    }
+
+    public String getSensorPath() {
+        return mSensorPath;
+    }
+
+    /**
+     * This function sets the sensor path to the given String value. If the
+     * String is "auto" it loops through the standard sysfs path, to obtain the
+     * 'mSensorPath'. The standard sysfs path is /sys/class/
+     * thermal/thermal_zoneX and the look up is based on 'mSensorName'.
+     * If sensor path is "none", sensor temp is not read via any sysfs
+     */
+    public void setSensorPath(String path) {
+        if (path.equalsIgnoreCase("auto")) {
+            setSensorSysfsPath();
+        } else {
+            mSensorPath = path;
+        }
+    }
+
+    private boolean isSensorSysfsValid(String path) {
+        return ThermalUtils.isFileExists(path);
+    }
+
+    public String getSensorName() {
+        return mSensorName;
+    }
+
+    public void setSensorName(String name) {
+        mSensorName = name;
+    }
+
+    public void setUEventDevPath(String devPath) {
+        mUEventDevPath = devPath;
+    }
+
+    public String getUEventDevPath() {
+        return mUEventDevPath;
+    }
+
+    public void setErrorCorrectionTemp(int temp) {
+        mErrorCorrectionTemp = temp;
+    }
+
+    public int getErrorCorrectionTemp() {
+        return mErrorCorrectionTemp;
+    }
+
+
+    public void setInputTempPath(String name) {
+        // sensor path is none, it means sensor temperature reporting is
+        // not sysfs based. So turn sensor active by default.
+        // If the sensor path does not exist, deactivate the sensor.
+        if (mSensorPath != null && mSensorPath.equalsIgnoreCase("none")) {
+            mIsSensorActive = true;
+        } else {
+            if (name != null && name.equalsIgnoreCase("auto")) {
+                name = "temp";
+            }
+            mInputTempPath = mSensorPath + name;
+            if (!isSensorSysfsValid(mInputTempPath)) {
+                mIsSensorActive = false;
+                Log.i(TAG, "Sensor:" + mSensorName + " path:" + mInputTempPath
+                        + " is invalid...deactivaing Sensor");
+            } else {
+                mIsSensorActive = true;
+            }
+        }
+    }
+
+    public String getSensorInputTempPath() {
+        return mInputTempPath;
+    }
+
+    public void setHighTempPath(String name) {
+        if (name != null && name.equalsIgnoreCase("auto")) {
+            mHighTempPath = mSensorPath + ThermalManager.sSysfsSensorHighTempPath;
+        } else {
+            if (mSensorPath != null && mSensorPath.equalsIgnoreCase("none")) {
+                mHighTempPath = "invalid";
+            } else {
+                mHighTempPath = mSensorPath + name;
+            }
+        }
+    }
+
+    public String getSensorHighTempPath() {
+        return mHighTempPath;
+    }
+
+    public void setLowTempPath(String name) {
+        if (name != null && name.equalsIgnoreCase("auto")) {
+            mLowTempPath = mSensorPath + ThermalManager.sSysfsSensorLowTempPath;
+        } else {
+            if (mSensorPath != null && mSensorPath.equalsIgnoreCase("none")) {
+                mLowTempPath = "invalid";
+            } else {
+                mLowTempPath = mSensorPath + name;
+            }
+        }
+    }
+
+    public String getSensorLowTempPath() {
+        return mLowTempPath;
+    }
+
+    public void setCurrTemp(int temp) {
+        mCurrTemp = temp;
+    }
+
+    public int getCurrTemp() {
+        return mCurrTemp;
+    }
+
+    /**
+     * Method that actually does a Sysfs read.
+     */
+    public int readSensorTemp() {
+        int val = ThermalManager.INVALID_TEMP;
+        try {
+            String tempStr = ThermalUtils.readSysfs(mInputTempPath);
+            if (tempStr != null) {
+                val = Integer.parseInt(tempStr.trim());
+            }
+        } catch (NumberFormatException e) {
+            Log.i(TAG, "NumberFormatException in readSensorTemp():" + mInputTempPath);
+        }
+        return val;
+    }
+
+    /**
+     * Method to read the current temperature from sensor. This method should be
+     * used only when we want to obtain the latest temperature from sensors.
+     * Otherwise, the getCurrTemp method should be used, which returns the
+     * previously read value.
+     */
+    public void updateSensorTemp() {
+        int val = readSensorTemp();
+        if (val != ThermalManager.INVALID_TEMP) {
+            setCurrTemp(val);
+        }
+    }
+
+    public int getSensorThermalState() {
+        return mSensorState;
+    }
+
+    public void setSensorThermalState(int state) {
+        mSensorState = state;
+    }
+
+    public void setAutoValues() {
+        if (mSensorPath.equalsIgnoreCase("auto")) {
+            setSensorPath(mSensorPath);
+        }
+        if (mInputTempPath.equalsIgnoreCase("auto")) {
+            setInputTempPath(mInputTempPath);
+        }
+        if (mHighTempPath.equalsIgnoreCase("auto")) {
+            setHighTempPath(mHighTempPath);
+        }
+        if (mLowTempPath.equalsIgnoreCase("auto")) {
+            setLowTempPath(mLowTempPath);
+        }
+        if (mUEventDevPath.equalsIgnoreCase("auto")) {
+            // build the sensor UEvent listener path
+            if (mSensorSysfsIndx == -1) {
+                mUEventDevPath = "invalid";
+                Log.i(TAG, "Cannot build UEvent path for sensor:" + mSensorName);
+                return;
+            } else {
+                mUEventDevPath = ThermalManager.sUEventDevPath + mSensorSysfsIndx;
+            }
+        } else if (!mUEventDevPath.contains("DEVPATH=")) {
+            mUEventDevPath = "DEVPATH=" + mUEventDevPath;
+        }
+    }
+
+}
diff --git a/ituxd/src/com/intel/thermal/ThermalSensorAttrib.java b/ituxd/src/com/intel/thermal/ThermalSensorAttrib.java
new file mode 100644
index 0000000..37fbc81
--- /dev/null
+++ b/ituxd/src/com/intel/thermal/ThermalSensorAttrib.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2014 Intel Corporation All Rights Reserved.
+ *
+ * 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.
+ */
+
+package com.intel.thermal;
+
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+/**
+ * The ThermalSensorAttrib class describes the attributes of a Thermal Sensor that are
+ * zone specific.
+ * @hide
+ */
+public class ThermalSensorAttrib {
+
+    private static final String TAG = "ThermalSensorAttrib";
+    private String mSensorName;
+    private Integer mWeights[];
+    private Integer mOrder[];
+
+    public String getSensorName() {
+        return mSensorName;
+    }
+
+    public void setSensorName(String name) {
+        mSensorName = name;
+    }
+
+    public Integer[] getWeights() {
+        return mWeights;
+    }
+
+    public void setWeights(ArrayList<Integer> list) {
+        if (list != null) {
+            mWeights = new Integer[list.size()];
+            if (mWeights != null) {
+                mWeights = list.toArray(mWeights);
+            }
+        }
+    }
+
+    public Integer[] getOrder() {
+        return mOrder;
+    }
+
+    public void setOrder(ArrayList<Integer> list) {
+        if (list != null) {
+            mOrder = new Integer[list.size()];
+            if (mOrder != null) {
+                mOrder = list.toArray(mOrder);
+            }
+        }
+    }
+
+    public void printAttrs() {
+        Log.i(TAG, "SensorAttrib: " + mSensorName);
+        Log.i(TAG, "mWeights[]: " + Arrays.toString(mWeights));
+        Log.i(TAG, "mOrder[]: " + Arrays.toString(mOrder));
+        if (mWeights != null && mOrder != null && mWeights.length != mOrder.length) {
+            Log.i(TAG, "mismatch in weights and order array, raw sensor temp will be used");
+        }
+    }
+}
diff --git a/ituxd/src/com/intel/thermal/ThermalService.java b/ituxd/src/com/intel/thermal/ThermalService.java
new file mode 100644
index 0000000..0751885
--- /dev/null
+++ b/ituxd/src/com/intel/thermal/ThermalService.java
@@ -0,0 +1,602 @@
+/*
+ * Copyright 2014 Intel Corporation All Rights Reserved.
+ *
+ * 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.
+ */
+
+package com.intel.thermal;
+
+import android.app.ActivityManagerNative;
+import android.app.IntentService;
+import android.app.Service;
+import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.Process;
+import android.os.SystemProperties;
+import android.os.UserHandle;
+import android.util.Log;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.lang.ClassLoader;
+import java.lang.NullPointerException;
+import java.lang.reflect.Array;
+import java.lang.SecurityException;
+import java.util.ArrayList;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlPullParserFactory;
+
+/**
+ * The ThermalService monitors the Thermal zones on the platform.
+ * The number of thermal zones and sensors associated with the zones are
+ * obtained from the thermal_sensor_config.xml file. When any thermal zone
+ * crosses the thresholds configured in the xml, a Thermal Intent is sent.
+ * ACTION_THERMAL_ZONE_STATE_CHANGED
+ * The Thermal Cooling Manager acts upon this intent and throttles
+ * the corresponding cooling device.
+ *
+ * @hide
+ */
+public class ThermalService extends Service {
+    private static final String TAG = ThermalService.class.getSimpleName();
+    private static Context mContext;
+    private Handler mHandler = new Handler();
+    static {
+        System.loadLibrary("thermalJNI");
+    }
+    protected enum MetaTag {
+            ENUM_UNKNOWN,
+            ENUM_ZONETHRESHOLD,
+            ENUM_POLLDELAY,
+            ENUM_MOVINGAVGWINDOW
+    }
+
+    public class ThermalParser {
+        // Names of the XML Tags
+        private static final String PINFO = "PlatformInfo";
+        private static final String SENSOR_ATTRIB = "SensorAttrib";
+        private static final String SENSOR = "Sensor";
+        private static final String ZONE = "Zone";
+        private static final String THERMAL_CONFIG = "thermalconfig";
+        private static final String THRESHOLD = "Threshold";
+        private static final String POLLDELAY = "PollDelay";
+        private static final String MOVINGAVGWINDOW = "MovingAverageWindow";
+        private static final String ZONELOGIC = "ZoneLogic";
+        private static final String WEIGHT = "Weight";
+        private static final String ORDER = "Order";
+        private static final String OFFSET = "Offset";
+        private static final String ZONETHRESHOLD = "ZoneThreshold";
+        private static final String PROFILE = "Profile";
+
+        private boolean mDone = false;
+        private ThermalManager.PlatformInfo mPlatformInfo = null;
+        private ThermalSensor mCurrSensor = null;
+        private ThermalZone mCurrZone = null;
+        private ArrayList<ThermalSensorAttrib> mCurrSensorAttribList = null;
+        private ThermalSensorAttrib mCurrSensorAttrib = null;
+        private ArrayList<ThermalZone> mThermalZones = null;
+        private ArrayList<Integer> mPollDelayList = null;
+        private ArrayList<Integer> mMovingAvgWindowList = null;
+        private ArrayList<Integer> mWeightList = null;
+        private ArrayList<Integer> mOrderList = null;
+        private ArrayList<Integer> mZoneThresholdList = null;
+        private String mSensorName = null;
+        XmlPullParserFactory mFactory = null;
+        XmlPullParser mParser = null;
+        int mTempZoneId = -1;
+        int mNumProfiles = 0;
+        String mTempZoneName = null;
+        String mCurProfileName = ThermalManager.DEFAULT_PROFILE_NAME;
+        FileReader mInputStream = null;
+
+        ThermalParser(String fname) {
+            try {
+                mFactory = XmlPullParserFactory.newInstance(System.
+                        getProperty(XmlPullParserFactory.PROPERTY_NAME), null);
+                mFactory.setNamespaceAware(true);
+                mParser = mFactory.newPullParser();
+            } catch (SecurityException e) {
+                Log.e(TAG, "SecurityException caught in ThermalParser");
+            } catch (IllegalArgumentException e) {
+                Log.e(TAG, "IllegalArgumentException caught in ThermalParser");
+            } catch (XmlPullParserException xppe) {
+                Log.e(TAG, "XmlPullParserException caught in ThermalParser");
+            }
+
+            try {
+                mInputStream = new FileReader(fname);
+                mPlatformInfo = null;
+                mCurrSensor = null;
+                mCurrZone = null;
+                mThermalZones = null;
+                if (mInputStream == null) return;
+                if (mParser != null) {
+                    mParser.setInput(mInputStream);
+                }
+            } catch (FileNotFoundException e) {
+                Log.e(TAG, "FileNotFoundException Exception in ThermalParser()");
+            } catch (XmlPullParserException e) {
+                Log.e(TAG, "XmlPullParserException Exception in ThermalParser()");
+            }
+        }
+
+        ThermalParser() {
+            mParser = mContext.getResources().
+                    getXml(ThermalManager.sSensorFileXmlId);
+        }
+
+        public ThermalManager.PlatformInfo getPlatformInfo() {
+            return mPlatformInfo;
+        }
+
+        public boolean parse() {
+            if (ThermalManager.sIsOverlays == false && mInputStream == null) return false;
+            /* if mParser is null, close any open stream before exiting */
+            if (mParser == null) {
+                try {
+                    if (mInputStream != null) {
+                        mInputStream.close();
+                    }
+                } catch (IOException e) {
+                    Log.i(TAG, "IOException caught in parse() function");
+                }
+                return false;
+            }
+
+            boolean ret = true;
+            MetaTag tag = MetaTag.ENUM_UNKNOWN;
+            try {
+                int mEventType = mParser.getEventType();
+                while (mEventType != XmlPullParser.END_DOCUMENT && !mDone) {
+                    switch (mEventType) {
+                        case XmlPullParser.START_DOCUMENT:
+                            Log.i(TAG, "StartDocument");
+                            break;
+                        case XmlPullParser.START_TAG:
+                            String tagName = mParser.getName();
+                            boolean isMetaTag = false;
+                            if (tagName != null && tagName.equalsIgnoreCase(ZONETHRESHOLD)) {
+                                tag = MetaTag.ENUM_ZONETHRESHOLD;
+                                isMetaTag = true;
+                            } else if (tagName != null && tagName.equalsIgnoreCase(POLLDELAY)) {
+                                tag = MetaTag.ENUM_POLLDELAY;
+                                isMetaTag = true;
+                            } else if (tagName != null
+                                    && tagName.equalsIgnoreCase(MOVINGAVGWINDOW)) {
+                                tag = MetaTag.ENUM_MOVINGAVGWINDOW;
+                                isMetaTag = true;
+                            }
+                            if (isMetaTag) {
+                                ret = processMetaTag(tagName, tag);
+                            } else {
+                                ret = processStartElement(tagName);
+                            }
+                            if (!ret) {
+                                if (mInputStream != null) mInputStream.close();
+                                return false;
+                            }
+                            break;
+                        case XmlPullParser.END_TAG:
+                            processEndElement(mParser.getName());
+                            break;
+                    }
+                    mEventType = mParser.next();
+                }
+            } catch (XmlPullParserException xppe) {
+                Log.i(TAG, "XmlPullParserException caught in parse():" + xppe.getMessage());
+                ret = false;
+            } catch (IOException e) {
+                Log.i(TAG, "IOException caught in parse():" + e.getMessage());
+                ret = false;
+            } finally {
+                try {
+                    // end of parsing, close the stream
+                    // close is moved here, since if there is an exception
+                    // while parsing doc, input stream needs to be closed
+                    if (mInputStream != null) mInputStream.close();
+                } catch (IOException e) {
+                    Log.i(TAG, "IOException caught in parse() function");
+                    ret = false;
+                }
+                return ret;
+            }
+        }
+
+        boolean processMetaTag(String tagName, MetaTag tagId) {
+            if (mParser == null || tagName == null || mCurrZone == null)  return false;
+            ArrayList<Integer> tempList;
+            tempList = new ArrayList<Integer>();
+            // add the dummy value for TOFF now. update it once meta tag parsed
+            tempList.add(0);
+            try {
+                int eventType = mParser.next();
+                while (true) {
+                    if (eventType == XmlPullParser.START_TAG) {
+                        tempList.add(Integer.parseInt(mParser.nextText()));
+                    } else if (eventType == XmlPullParser.END_TAG &&
+                            mParser.getName().equalsIgnoreCase(tagName)) {
+                        break;
+                    }
+                    eventType = mParser.next();
+                }
+            } catch (XmlPullParserException xppe) {
+                Log.e(TAG, "XmlPullParserException:" + xppe.getMessage());
+                return false;
+            } catch (IOException ioe) {
+                Log.e(TAG, "IOException:" + ioe.getMessage());
+                return false;
+            }
+            // now that all state values are parse, copy the value corresponding to <normal>
+            // state to TOFF and last state to CRITICAL state.
+            // now we have reached end of meta tag add this temp list to appropriate list
+            switch(tagId) {
+                case ENUM_POLLDELAY:
+                    // add TOFF
+                    tempList.set(0, tempList.get(1));
+                    // add TCRITICAL
+                    tempList.add(tempList.get(tempList.size() - 1));
+                    mCurrZone.setPollDelay(tempList);
+                    break;
+                case ENUM_ZONETHRESHOLD:
+                    // add TCRITICAL
+                    tempList.add(tempList.get(tempList.size() - 1));
+                    mCurrZone.updateMaxStates(tempList.size());
+                    mCurrZone.setZoneTempThreshold(tempList);
+                    break;
+                case ENUM_MOVINGAVGWINDOW:
+                    // add TOFF
+                    tempList.set(0, tempList.get(1));
+                    // add TCRITICAL
+                    tempList.add(tempList.get(tempList.size() - 1));
+                    mCurrZone.setMovingAvgWindow(tempList);
+                    break;
+                case ENUM_UNKNOWN:
+                default:
+                    break;
+            }
+            tempList = null;
+            return true;
+        }
+
+        boolean processStartElement(String name) {
+            if (name == null)
+                return false;
+            String zoneName;
+            boolean ret = true;
+            try {
+                if (name.equalsIgnoreCase(PINFO)) {
+                    mPlatformInfo = new ThermalManager.PlatformInfo();
+                    // Default Thermal States
+                    mPlatformInfo.mMaxThermalStates = 5;
+                } else if (name.equalsIgnoreCase(PROFILE)) {
+                    mNumProfiles++;
+                } else if (name.equalsIgnoreCase(SENSOR)) {
+                    if (mCurrSensor == null) {
+                        mCurrSensor = new ThermalSensor();
+                    }
+                } else if (name.equalsIgnoreCase(SENSOR_ATTRIB)) {
+                    if (mCurrSensorAttribList == null) {
+                        mCurrSensorAttribList = new ArrayList<ThermalSensorAttrib>();
+                    }
+                    mCurrSensorAttrib = new ThermalSensorAttrib();
+                } else if (name.equalsIgnoreCase(ZONE)) {
+                    if (mThermalZones == null)
+                        mThermalZones = new ArrayList<ThermalZone>();
+                } else {
+                    // Retrieve Platform Information
+                    if (mPlatformInfo != null && name.equalsIgnoreCase("PlatformThermalStates")) {
+                        mPlatformInfo.mMaxThermalStates = Integer.parseInt(mParser.nextText());
+                        // Retrieve Zone Information
+                    } else if (name.equalsIgnoreCase("ZoneName") && mTempZoneId != -1) {
+                        mTempZoneName = mParser.nextText();
+                    } else if (name.equalsIgnoreCase("Name")) {
+                        mCurProfileName = mParser.nextText();
+                    } else if (name.equalsIgnoreCase(ZONELOGIC) && mTempZoneId != -1
+                            && mTempZoneName != null) {
+                        String zoneLogic = mParser.nextText();
+                        if (zoneLogic.equalsIgnoreCase("VirtualSkin")) {
+                            mCurrZone = new VirtualThermalZone();
+                        } else {
+                            // default zone raw
+                            mCurrZone = new RawThermalZone();
+                        }
+                        if (mCurrZone != null) {
+                            mCurrZone.setZoneName(mTempZoneName);
+                            mCurrZone.setZoneId(mTempZoneId);
+                            mCurrZone.setZoneLogic(zoneLogic);
+                        }
+                    } else if (name.equalsIgnoreCase("ZoneID")) {
+                        mTempZoneId = Integer.parseInt(mParser.nextText());
+                    } else if (name.equalsIgnoreCase("SupportsUEvent") && mCurrZone != null)
+                        mCurrZone.setSupportsUEvent(Integer.parseInt(mParser.nextText()));
+                    else if (name.equalsIgnoreCase("SupportsEmulTemp") && mCurrZone != null)
+                        mCurrZone.setEmulTempFlag(Integer.parseInt(mParser.nextText()));
+                    else if (name.equalsIgnoreCase("DebounceInterval") && mCurrZone != null)
+                        mCurrZone.setDBInterval(Integer.parseInt(mParser.nextText()));
+                    else if (name.equalsIgnoreCase(POLLDELAY) && mCurrZone != null) {
+                        mPollDelayList = new ArrayList<Integer>();
+                    } else if (name.equalsIgnoreCase(OFFSET) && mCurrZone != null) {
+                        mCurrZone.setOffset(Integer.parseInt(mParser.nextText()));
+                    }
+
+                    // Retrieve Sensor Information
+                    else if (name.equalsIgnoreCase("SensorName")) {
+                        if (mCurrSensorAttrib != null) {
+                            mCurrSensorAttrib.setSensorName(mParser.nextText());
+                        } else if (mCurrSensor != null) {
+                            mCurrSensor.setSensorName(mParser.nextText());
+                        }
+                    } else if (name.equalsIgnoreCase("SensorPath") && mCurrSensor != null)
+                        mCurrSensor.setSensorPath(mParser.nextText());
+                    else if (name.equalsIgnoreCase("InputTemp") && mCurrSensor != null)
+                        mCurrSensor.setInputTempPath(mParser.nextText());
+                    else if (name.equalsIgnoreCase("HighTemp") && mCurrSensor != null)
+                        mCurrSensor.setHighTempPath(mParser.nextText());
+                    else if (name.equalsIgnoreCase("LowTemp") && mCurrSensor != null)
+                        mCurrSensor.setLowTempPath(mParser.nextText());
+                    else if (name.equalsIgnoreCase("UEventDevPath") && mCurrSensor != null)
+                        mCurrSensor.setUEventDevPath(mParser.nextText());
+                    else if (name.equalsIgnoreCase("ErrorCorrection") && mCurrSensor != null)
+                        mCurrSensor.setErrorCorrectionTemp(Integer.parseInt(mParser.nextText()));
+                    else if (name.equalsIgnoreCase(WEIGHT) && mCurrSensorAttrib != null) {
+                        if (mWeightList == null) {
+                            mWeightList = new ArrayList<Integer>();
+                        }
+                        if (mWeightList != null) {
+                            mWeightList.add(Integer.parseInt(mParser.nextText()));
+                        }
+                    } else if (name.equalsIgnoreCase(ORDER) && mCurrSensorAttrib != null) {
+                        if (mOrderList == null) {
+                            mOrderList = new ArrayList<Integer>();
+                        }
+                        if (mOrderList != null) {
+                            mOrderList.add(Integer.parseInt(mParser.nextText()));
+                        }
+                    }
+                }
+            } catch (XmlPullParserException e) {
+                Log.i(TAG, "XmlPullParserException caught in processStartElement()");
+                ret = false;
+            } catch (IOException e) {
+                Log.i(TAG, "IOException caught in processStartElement()");
+                ret = false;
+            } finally {
+                return ret;
+            }
+        }
+
+        void processEndElement(String name) {
+            if (name.equalsIgnoreCase(SENSOR)) {
+                // insert in map, only if no sensor with same name already in map
+                if (mCurrSensor == null) return;
+                mCurrSensor.setAutoValues();
+                if (ThermalManager.getSensor(mCurrSensor.getSensorName()) == null) {
+                    ThermalManager.sSensorMap.put(mCurrSensor.getSensorName(), mCurrSensor);
+                } else {
+                    Log.i(TAG, "sensor:" + mCurrSensor.getSensorName() + " already present");
+                }
+                mCurrSensor = null;
+            } else if (name.equalsIgnoreCase(SENSOR_ATTRIB) && mCurrSensorAttribList != null) {
+                if (mCurrSensorAttrib != null) {
+                    mCurrSensorAttrib.setWeights(mWeightList);
+                    mCurrSensorAttrib.setOrder(mOrderList);
+                }
+                mWeightList = null;
+                mOrderList = null;
+                if (mCurrSensorAttrib != null
+                        && ThermalManager.getSensor(mCurrSensorAttrib.getSensorName()) != null) {
+                    // this is valid sensor, so now update the zone sensorattrib list
+                    // and sensor list.This check is needed to avoid a scenario where
+                    // a invalid sensor name might be included in sensorattrib list.
+                    // This check filters out all invalid sensor attrib.
+                    mCurrSensorAttribList.add(mCurrSensorAttrib);
+                }
+            } else if (name.equalsIgnoreCase(ZONE) && mCurrZone != null
+                    && mThermalZones != null) {
+                mCurrZone.setSensorList(mCurrSensorAttribList);
+                mThermalZones.add(mCurrZone);
+                mCurrZone = null;
+                mTempZoneId = -1;
+                mTempZoneName = null;
+                mCurrSensorAttribList = null;
+            } else if (name.equalsIgnoreCase(POLLDELAY) && mCurrZone != null) {
+                mCurrZone.setPollDelay(mPollDelayList);
+                mPollDelayList = null;
+            } else if (name.equalsIgnoreCase(MOVINGAVGWINDOW) && mCurrZone != null) {
+                mCurrZone.setMovingAvgWindow(mMovingAvgWindowList);
+                mMovingAvgWindowList = null;
+            } else if (name.equalsIgnoreCase(THERMAL_CONFIG)) {
+                // This indicates we have not seen any <Profile> tag.
+                // Consider it as if we have only one 'Default' Profile.
+                if (mNumProfiles == 0) {
+                    ThermalManager.sProfileZoneMap.put(mCurProfileName, mThermalZones);
+                }
+                mDone = true;
+            } else if (name.equalsIgnoreCase(PROFILE)) {
+                ThermalManager.sProfileZoneMap.put(mCurProfileName, mThermalZones);
+                mThermalZones = null;
+            } else if (name.equalsIgnoreCase(ZONETHRESHOLD) && mCurrZone != null) {
+                mCurrZone.setZoneTempThreshold(mZoneThresholdList);
+                mZoneThresholdList = null;
+            }
+        }
+    }
+
+    /* Class to notifying thermal events */
+    public class Notify implements Runnable {
+        private final BlockingQueue cQueue;
+        Notify (BlockingQueue q) {
+            cQueue = q;
+        }
+
+        public void run () {
+            try {
+                while (true) { consume((ThermalEvent) cQueue.take()); }
+            } catch (InterruptedException ex) {
+                Log.i(TAG, "caught InterruptedException in run()");
+            }
+        }
+
+        /* Method to consume thermal event */
+        public void consume (ThermalEvent event) {
+            Intent statusIntent = new Intent();
+            statusIntent.setAction(ThermalManager.ACTION_THERMAL_ZONE_STATE_CHANGED);
+
+            statusIntent.putExtra(ThermalManager.EXTRA_NAME, event.mZoneName);
+            statusIntent.putExtra(ThermalManager.EXTRA_PROFILE, event.mProfName);
+            statusIntent.putExtra(ThermalManager.EXTRA_ZONE, event.mZoneId);
+            statusIntent.putExtra(ThermalManager.EXTRA_EVENT, event.mEventType);
+            statusIntent.putExtra(ThermalManager.EXTRA_STATE, event.mThermalLevel);
+            statusIntent.putExtra(ThermalManager.EXTRA_TEMP, event.mZoneTemp);
+
+            /* Send the Thermal Intent */
+            mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL);
+        }
+    }
+
+    /* Register for boot complete Intent */
+    public ThermalService() {
+        super();
+    }
+
+    private void configureTurboProperties() {
+        String prop = SystemProperties.get("persist.thermal.turbo.dynamic");
+
+        if (prop.equals("0")) {
+            ThermalManager.sIsDynamicTurboEnabled = false;
+            Log.i(TAG, "Dynamic Turbo disabled through persist.thermal.turbo.dynamic");
+        } else if (prop.equals("1")) {
+            ThermalManager.sIsDynamicTurboEnabled = true;
+            Log.i(TAG, "Dynamic Turbo enabled through persist.thermal.turbo.dynamic");
+        } else {
+            // Set it to true so that we don't write ThermalManager.DISABLE_DYNAMIC_TURBO
+            // into any cooling device based on this.
+            ThermalManager.sIsDynamicTurboEnabled = true;
+            Log.i(TAG, "property persist.thermal.turbo.dynamic not present");
+        }
+    }
+
+    @Override
+    public void onDestroy() {
+        // stop all thread
+        ThermalManager.stopCurrentProfile();
+        ThermalManager.sCoolingManager.unregisterReceivers();
+        // clear all static data
+        ThermalManager.clearData();
+        Log.w(TAG, "ituxd destroyed");
+    }
+
+    @Override
+    public void onCreate() {
+        mContext = getApplicationContext();
+        ThermalManager.setContext(mContext);
+    }
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        return(null);
+    }
+
+    @Override
+    public int onStartCommand(Intent intent, int flags, int startid)
+    {
+        boolean ret;
+        ThermalManager.loadiTUXVersion();
+        /* Check for exitence of config files */
+        ThermalUtils.initialiseConfigFiles(mContext);
+        if (!ThermalManager.sIsConfigFiles && !ThermalManager.sIsOverlays) {
+            Log.i(TAG, "Thermal config files do not exist. Exiting ThermalService");
+            return START_NOT_STICKY;
+        }
+
+        /* Set Dynamic Turbo status based on the property */
+        configureTurboProperties();
+
+        /* Intiliaze DTS TjMax temperature */
+        ThermalUtils.getTjMax();
+
+        /* Initialize the Thermal Cooling Manager */
+        ThermalManager.sCoolingManager = new ThermalCooling();
+        if (ThermalManager.sCoolingManager != null) {
+            ret = ThermalManager.sCoolingManager.init(mContext);
+            if (!ret) {
+                Log.i(TAG, "CoolingManager is null. Exiting ThermalService");
+                return START_NOT_STICKY;
+            }
+        }
+
+        /* Parse the thermal configuration file to determine zone/sensor information */
+        ThermalParser mThermalParser;
+        if (ThermalManager.sIsConfigFiles) {
+            mThermalParser = new ThermalParser(ThermalManager.sSensorFilePath);
+        } else {
+            mThermalParser = new ThermalParser();
+        }
+
+        if (mThermalParser != null) {
+            ret = mThermalParser.parse();
+            if (!ret) {
+                ThermalManager.sCoolingManager.unregisterReceivers();
+                Log.i(TAG, "thermal_sensor_config.xml parsing Failed. Exiting ThermalService");
+                return START_NOT_STICKY;
+            }
+        }
+
+        /* Retrieve the platform information after parsing */
+        ThermalManager.sPlatformInfo = mThermalParser.getPlatformInfo();
+
+        /* Print thermal_sensor_config.xml information */
+        Iterator it = ThermalManager.sProfileZoneMap.entrySet().iterator();
+        while (it.hasNext()) {
+            Map.Entry entry = (Map.Entry) it.next();
+            String key = (String) entry.getKey();
+            ArrayList<ThermalZone> tzList = (ArrayList<ThermalZone>) entry.getValue();
+            Log.i(TAG, "Zones under Profile: " + key);
+            for (ThermalZone tz : tzList) tz.printAttrs();
+        }
+
+        /* read persistent system properties for shutdown notification */
+        ThermalManager.readShutdownNotiferProperties();
+        /* initialize the thermal notifier thread */
+        Notify notifier = new Notify(ThermalManager.sEventQueue);
+        new Thread(notifier, "ThermalNotifier").start();
+
+        ThermalManager.buildProfileNameList();
+        ThermalManager.initializeStickyIntent();
+
+        /* Building bucket size for all profiles */
+        ThermalManager.setBucketSizeForProfiles();
+
+        /* Start monitoring the zones in Default Thermal Profile */
+        ThermalManager.startDefaultProfile();
+
+        return START_STICKY;
+    }
+}
diff --git a/ituxd/src/com/intel/thermal/ThermalUtils.java b/ituxd/src/com/intel/thermal/ThermalUtils.java
new file mode 100644
index 0000000..7126f9b
--- /dev/null
+++ b/ituxd/src/com/intel/thermal/ThermalUtils.java
@@ -0,0 +1,195 @@
+/*
+ * Copyright 2014 Intel Corporation All Rights Reserved.
+ *
+ * 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.
+ */
+
+package com.intel.thermal;
+
+import android.content.Context;
+import android.os.SystemProperties;
+import android.util.Log;
+
+import java.io.IOException;
+import java.io.File;
+
+/* importing static variables */
+import static com.intel.thermal.ThermalManager.*;
+
+/**
+ * The ThermalUtils class contains all common utility functionality
+ * implementations
+ *
+ * @hide
+ */
+public class ThermalUtils {
+    private static final String TAG = "ThermalUtils";
+
+    /* Native methods to access Sysfs Interfaces */
+    private native static String native_readSysfs(String path);
+    private native static int native_writeSysfs(String path, int val);
+    private native static int native_getThermalZoneIndex(String name);
+    private native static int native_getThermalZoneIndexContains(String name);
+    private native static int native_getCoolingDeviceIndex(String name);
+    private native static int native_getCoolingDeviceIndexContains(String name);
+    private native static boolean native_isFileExists(String name);
+
+    // native methods to access kernel sysfs layer
+    public static String readSysfs(String path) {
+        try {
+            return native_readSysfs(path);
+        } catch (UnsatisfiedLinkError e) {
+            Log.w(TAG, "caught UnsatisfiedLinkError in readSysfs");
+            return null;
+        }
+    }
+
+    public static int writeSysfs(String path, int val) {
+        try {
+            return native_writeSysfs(path, val);
+        } catch (UnsatisfiedLinkError e) {
+            Log.w(TAG, "caught UnsatisfiedLinkError in writeSysfs");
+            return -1;
+        }
+    }
+
+    public static int getThermalZoneIndex(String name) {
+        try {
+            return native_getThermalZoneIndex(name);
+        } catch (UnsatisfiedLinkError e) {
+            Log.w(TAG, "caught UnsatisfiedLinkError in getThermalZoneIndex");
+            return -1;
+        }
+    }
+
+    public static int getThermalZoneIndexContains(String name) {
+        try {
+            return native_getThermalZoneIndexContains(name);
+        } catch (UnsatisfiedLinkError e) {
+            Log.w(TAG, "caught UnsatisfiedLinkError in getThermalZoneIndexContains");
+            return -1;
+        }
+    }
+
+    public static int getCoolingDeviceIndex(String name) {
+        try {
+            return native_getCoolingDeviceIndex(name);
+        } catch (UnsatisfiedLinkError e) {
+            Log.w(TAG, "caught UnsatisfiedLinkError in getCoolingDeviceIndex");
+            return -1;
+        }
+    }
+
+    public static int getCoolingDeviceIndexContains(String name) {
+        try {
+            return native_getCoolingDeviceIndexContains(name);
+        } catch (UnsatisfiedLinkError e) {
+            Log.w(TAG, "caught UnsatisfiedLinkError in getCoolingDeviceIndexContains");
+            return -1;
+        }
+    }
+
+    public static boolean isFileExists(String path) {
+        try {
+            return native_isFileExists(path);
+        } catch (UnsatisfiedLinkError e) {
+            Log.w(TAG, "caught UnsatisfiedLinkError in isFileExists");
+            return false;
+        }
+    }
+
+
+    public static int calculateThermalState(int temp, Integer thresholds[]) {
+        if (thresholds == null) return THERMAL_STATE_OFF;
+        // Return OFF state if temperature less than starting of thresholds
+        if (temp < thresholds[0])
+            return THERMAL_STATE_OFF;
+
+        if (temp >= thresholds[thresholds.length - 2])
+            return (thresholds.length - 2);
+
+        for (int i = 0; i < thresholds.length - 1; i++) {
+            if (temp >= thresholds[i] && temp < thresholds[i + 1]) {
+                return i;
+            }
+        }
+
+        // should never come here
+        return THERMAL_STATE_OFF;
+    }
+
+    public static int getLowerThresholdTemp(int index, Integer thresholds[]) {
+        if (thresholds == null) return INVALID_TEMP;
+        if (index < 0 || index >= thresholds.length)
+            return INVALID_TEMP;
+        return thresholds[index];
+    }
+
+    public static int getUpperThresholdTemp(int index, Integer thresholds[]) {
+        if (thresholds == null) return INVALID_TEMP;
+        if (index < 0 || index >= thresholds.length)
+            return INVALID_TEMP;
+        return thresholds[index + 1];
+    }
+
+    public static void getTjMax() {
+        String temp_tjmax;
+
+        temp_tjmax = readSysfs(ThermalManager.TJMAX_PATH);
+        if (temp_tjmax != null) {
+            try {
+                ThermalManager.sTjMaxTemp = Integer.parseInt(temp_tjmax);
+                Log.i(TAG, "TjMax temp = " + ThermalManager.sTjMaxTemp);
+            } catch (NumberFormatException e) {
+                ThermalManager.sTjMaxTemp = ThermalManager.sDefaultTjMax;
+                Log.i(TAG, "TjMax value invalid, Default TjMax value =" +
+                        ThermalManager.sTjMaxTemp);
+            }
+        } else {
+            ThermalManager.sTjMaxTemp = ThermalManager.sDefaultTjMax;
+            Log.i(TAG, "TjMax temp read failed, Default TjMax value =" +
+                    ThermalManager.sTjMaxTemp);
+        }
+    }
+
+    public static void initialiseConfigFiles(Context context) {
+        if ("1".equals(SystemProperties.get("persist.thermal.debug.xml", "0"))) {
+            if (isFileExists(DEBUG_DIR_PATH + SENSOR_FILE_NAME) &&
+                    isFileExists(DEBUG_DIR_PATH + THROTTLE_FILE_NAME)) {
+                sSensorFilePath = DEBUG_DIR_PATH + SENSOR_FILE_NAME;
+                sThrottleFilePath = DEBUG_DIR_PATH + THROTTLE_FILE_NAME;
+                Log.i(TAG, "Reading thermal config files from /data/");
+                sIsConfigFiles = true;
+            } else {
+                Log.i(TAG, "systemProperty set to read config files from /data/, but files absent");
+            }
+        } else if (isFileExists(DEFAULT_DIR_PATH + SENSOR_FILE_NAME) &&
+                isFileExists(DEFAULT_DIR_PATH + THROTTLE_FILE_NAME)) {
+            sSensorFilePath = DEFAULT_DIR_PATH + SENSOR_FILE_NAME;
+            sThrottleFilePath = DEFAULT_DIR_PATH + THROTTLE_FILE_NAME;
+            Log.i(TAG, "Reading thermal config files from /system/etc/");
+            sIsConfigFiles = true;
+        } else {
+            sSensorFileXmlId = context.getResources().
+                getIdentifier("thermal_sensor_config", "xml", "com.intel.thermal");
+            sThrottleFileXmlId = context.getResources().
+                getIdentifier("thermal_throttle_config", "xml", "com.intel.thermal");
+            if (sSensorFileXmlId != 0 && sThrottleFileXmlId != 0) {
+                Log.i(TAG, "Reading thermal config files from overlays");
+                sIsOverlays = true;
+            } else {
+                Log.i(TAG, "Unable to retrieve config files from overlays");
+            }
+        }
+    }
+}
diff --git a/ituxd/src/com/intel/thermal/ThermalZone.java b/ituxd/src/com/intel/thermal/ThermalZone.java
new file mode 100644
index 0000000..a3af5af
--- /dev/null
+++ b/ituxd/src/com/intel/thermal/ThermalZone.java
@@ -0,0 +1,633 @@
+/*
+ * Copyright 2014 Intel Corporation All Rights Reserved.
+ *
+ * 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.
+ */
+
+package com.intel.thermal;
+
+import android.os.UEventObserver;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Hashtable;
+import java.util.Iterator;
+
+/**
+ * The ThermalZone class contains attributes of a Thermal zone. A Thermal zone
+ * can have one or more sensors associated with it. Whenever the temperature of a
+ * thermal zone crosses the thresholds configured, actions are taken.
+ */
+public class ThermalZone {
+
+    private static final String TAG = "ThermalZone";
+
+    protected int mZoneID;               /* ID of the Thermal zone */
+    protected int mCurrThermalState;     /* Current thermal state of the zone */
+    protected int mCurrEventType;        /* specifies thermal event type, HIGH or LOW */
+    protected String mZoneName;          /* Name of the Thermal zone */
+    protected int mMaxStates;
+    /* List of sensors under this thermal zone */
+    protected ArrayList<ThermalSensor> mThermalSensors = null;
+    // sensor name - sensorAttrib object hash to improve lookup performace
+    // during runtime thermal monitoring like re-programming sensor thresholds
+    // calculating weighted zone temp.
+    protected Hashtable<String, ThermalSensorAttrib> mThermalSensorsAttribMap = null;
+    protected int mZoneTemp;             /* Temperature of the Thermal Zone */
+    protected boolean mSupportsEmulTemp = true;
+    private int mDebounceInterval;    /* Debounce value to avoid thrashing of throttling actions */
+    private Integer mPollDelay[];     /* Delay between sucessive polls in milli seconds */
+    protected boolean mSupportsUEvent;  /* Determines if Sensor supports Uevents */
+    private String mZoneLogic;      /* Logic to be used to determine thermal state of zone */
+    private boolean mIsZoneActive = false;
+    private boolean mMaxThreshExceeded = false;
+    private int mTripMax;
+    private int mOffset = 0;
+    protected Integer mZoneTempThresholds[];  /* Array containing temperature thresholds */
+    // mZoneTempThresholdsRaw contains the Raw thresholds (as specified in xml).
+    // mZoneTempThresholds contsins the calibrated thresholds that are used
+    // to detect zone state change at runtime.
+    protected Integer mZoneTempThresholdsRaw[];
+
+    /* MovingAverage related declarations */
+    private int mRecordedValuesHead = -1; /* Index pointing to the head of past values of sensor */
+    private int mRecordedValues[];        /* Recorded values of sensor */
+    private int mNumberOfInstances[];     /* Number of recorded instances to be considered */
+    private ArrayList<Integer> mWindowList = null;
+    private boolean mIsMovingAverage = false; /* By default false */
+
+    // override this method in ModemZone to limit num states to default
+    public void setMaxStates(int state) {
+        mMaxStates = state;
+    }
+
+    public void updateMaxStates(int state) {
+        setMaxStates(state);
+    }
+
+    public int getMaxStates() {
+        return mMaxStates;
+    }
+
+    public boolean getMovingAverageFlag() {
+        return mIsMovingAverage;
+    }
+
+    public void setMovingAvgWindow(ArrayList<Integer> windowList) {
+        int maxValue = Integer.MIN_VALUE; // -2^31
+
+        if (windowList == null || mPollDelay == null) {
+            Log.i(TAG, "setMovingAvgWindow input is null");
+            mIsMovingAverage = false;
+            return;
+        }
+        mNumberOfInstances = new int[windowList.size()];
+        if (mNumberOfInstances == null) {
+            Log.i(TAG, "failed to create poll windowlist");
+            mIsMovingAverage = false;
+            return;
+        }
+        mIsMovingAverage = true;
+        for (int i = 0; i < windowList.size(); i++) {
+            if (mPollDelay[i] == 0) {
+                mIsMovingAverage = false;
+                Log.i(TAG, "Polling delay is zero, WMA disabled\n");
+                return;
+            }
+            mNumberOfInstances[i] = windowList.get(i) / mPollDelay[i];
+            if (mNumberOfInstances[i] <= 0) {
+                mIsMovingAverage = false;
+                Log.i(TAG, "Polling delay greater than moving average window, WMA disabled\n");
+                return;
+            }
+            maxValue = Math.max(mNumberOfInstances[i], maxValue);
+        }
+        mRecordedValues = new int[maxValue];
+    }
+
+    public int movingAverageTemp() {
+        int index, calIndex;
+        int predictedTemp = 0;
+
+        mRecordedValuesHead = (mRecordedValuesHead + 1) % mRecordedValues.length;
+        mRecordedValues[mRecordedValuesHead] = mZoneTemp;
+
+        // Sensor State starts with -1, InstancesList starts with 0
+        for (index = 0; index < mNumberOfInstances[mCurrThermalState + 1]; index++) {
+            calIndex = mRecordedValuesHead - index;
+            if (calIndex < 0) {
+                calIndex = mRecordedValues.length + calIndex;
+            }
+            predictedTemp += mRecordedValues[calIndex];
+        }
+        return predictedTemp / index;
+    }
+
+    public void printAttrs() {
+        Log.i(TAG, "mZoneID:" + Integer.toString(mZoneID));
+        Log.i(TAG, "mDBInterval: " + Integer.toString(mDebounceInterval));
+        Log.i(TAG, "mZoneName:" + mZoneName);
+        Log.i(TAG, "mSupportsUEvent:" + Boolean.toString(mSupportsUEvent));
+        Log.i(TAG, "mZoneLogic:" + mZoneLogic);
+        Log.i(TAG, "mOffset:" + mOffset);
+        Log.i(TAG, "mPollDelay[]:" + Arrays.toString(mPollDelay));
+        Log.i(TAG, "mZoneTempThresholds[]: " + Arrays.toString(mZoneTempThresholds));
+        Log.i(TAG, "mNumberOfInstances[]: " + Arrays.toString(mNumberOfInstances));
+        Log.i(TAG, "mEmulTempFlag:" + mSupportsEmulTemp);
+        Log.i(TAG, "MaxStates:" + getMaxStates());
+        printStateThresholdMap();
+        printSensors();
+        printSensorAttribList();
+    }
+
+    public void printStateThresholdMap() {
+        if (mZoneTempThresholds == null
+                || mZoneTempThresholds.length < ThermalManager.DEFAULT_NUM_ZONE_STATES) return;
+        StringBuilder s = new StringBuilder();
+        s.append("[" + "State0" + "<" + mZoneTempThresholds[1] + "];");
+        for (int index = 2; index < getMaxStates(); index++) {
+            int curstate = index - 1;
+            s.append("[" + mZoneTempThresholds[index - 1] + "<=" + "State"
+                    + curstate + "<" + mZoneTempThresholds[index] + "];");
+        }
+        Log.i(TAG, "states-threshold map:" + s.toString());
+    }
+
+    private void printSensors() {
+        if (mThermalSensors == null) return;
+        StringBuilder s =  new StringBuilder();
+        for (ThermalSensor ts : mThermalSensors) {
+            if (ts != null) {
+                s.append(ts.getSensorName());
+                s.append(",");
+            }
+        }
+        Log.i(TAG, "zoneID: " + mZoneID + " sensors mapped:" + s.toString());
+    }
+
+    private void printSensorAttribList() {
+        if (mThermalSensorsAttribMap == null) return;
+        Iterator it = (Iterator) mThermalSensorsAttribMap.keySet().iterator();
+        if (it == null) return;
+        ThermalSensorAttrib sensorAttrib = null;
+        while (it.hasNext()) {
+            sensorAttrib = mThermalSensorsAttribMap.get((String) it.next());
+            if (sensorAttrib != null) sensorAttrib.printAttrs();
+        }
+    }
+
+    public ThermalZone() {
+        mCurrThermalState = ThermalManager.THERMAL_STATE_OFF;
+        mZoneTemp = ThermalManager.INVALID_TEMP;
+    }
+
+    public static String getStateAsString(int index) {
+        if (index < -1 || index > 3)
+            return "Invalid";
+        return ThermalManager.STATE_NAMES[index + 1];
+    }
+
+    public static String getEventTypeAsString(int type) {
+        return type == 0 ? "LOW" : "HIGH";
+    }
+
+    public void setSensorList(ArrayList<ThermalSensorAttrib> sensorAtribList) {
+        if (sensorAtribList == null || ThermalManager.sSensorMap == null) return;
+        for (ThermalSensorAttrib sa : sensorAtribList) {
+            // since each object of sensor attrib list is already validated during
+            // parsing it is gauranteed that 'sa != null' and a valid sensor object 's'
+            // will be returned. Hence skipping null check..
+            if (mThermalSensors == null) {
+                // first time allocation
+                mThermalSensors = new ArrayList<ThermalSensor>();
+                if (mThermalSensors == null) {
+                    // allocation failure. return
+                    return;
+                }
+            }
+            if (mThermalSensorsAttribMap == null) {
+                // first time allocation
+                mThermalSensorsAttribMap = new Hashtable<String, ThermalSensorAttrib>();
+                if (mThermalSensorsAttribMap == null) return;
+            }
+            mThermalSensors.add(ThermalManager.getSensor(sa.getSensorName()));
+            mThermalSensorsAttribMap.put(sa.getSensorName(), sa);
+        }
+    }
+
+    public ArrayList<ThermalSensor> getThermalSensorList() {
+        return mThermalSensors;
+    }
+
+    public int getZoneState() {
+        return mCurrThermalState;
+    }
+
+    public void setZoneState(int state) {
+        mCurrThermalState = state;
+    }
+
+    public int getEventType() {
+        return mCurrEventType;
+    }
+
+    public void setEventType(int type) {
+        mCurrEventType = type;
+    }
+
+    public void setZoneTemp(int temp) {
+        mZoneTemp = temp;
+    }
+
+    public int getZoneTemp() {
+        return mZoneTemp;
+    }
+
+    public void setZoneId(int id) {
+        mZoneID = id;
+    }
+
+    public int getZoneId() {
+        return mZoneID;
+    }
+
+    public void setZoneName(String name) {
+        mZoneName = name;
+    }
+
+    public String getZoneName() {
+        return mZoneName;
+    }
+
+    public void setSupportsUEvent(int flag) {
+        mSupportsUEvent = (flag == 1);
+    }
+
+    public boolean isUEventSupported() {
+        return mSupportsUEvent;
+    }
+
+    public boolean isMaxThreshExceed() {
+        return mMaxThreshExceeded;
+    }
+
+    public void setZoneLogic(String type) {
+        mZoneLogic = type;
+    }
+
+    public String getZoneLogic() {
+        return mZoneLogic;
+    }
+
+    public void setDBInterval(int interval) {
+        mDebounceInterval = interval;
+    }
+
+    public int getDBInterval() {
+        return mDebounceInterval;
+    }
+
+    public int getOffset() {
+        return mOffset;
+    }
+
+    public void setOffset(int offset) {
+        mOffset  = offset;
+    }
+
+    public void setPollDelay(ArrayList<Integer> delayList) {
+        if (delayList != null) {
+            mPollDelay = new Integer[delayList.size()];
+            if (mPollDelay != null) {
+                mPollDelay = delayList.toArray(mPollDelay);
+            }
+        }
+    }
+
+    public Integer[] getPollDelay() {
+        return mPollDelay;
+    }
+
+    /**
+     * In polldelay array, index of TOFF = 0, Normal = 1, Warning = 2, Alert =
+     * 3, Critical = 4. Whereas a ThermalZone states are enumerated as TOFF =
+     * -1, Normal = 0, Warning = 1, Alert = 2, Critical = 3. Hence we add 1
+     * while querying poll delay
+     */
+    public int getPollDelay(int index) {
+        index++;
+
+        // If poll delay is requested for an invalid state, return the delay
+        // corresponding to normal state
+        if (index < 0 || index >= mPollDelay.length)
+            index = 1;
+
+        return mPollDelay[index];
+    }
+
+    public void setZoneTempThreshold(ArrayList<Integer> thresholdList) {
+        if (mZoneName.contains("CPU") || mZoneName.contains("SoC"))
+            mTripMax = ThermalManager.sTjMaxTemp;
+        else
+            mTripMax = ThermalManager.sMaxSkinTrip;
+
+        if (thresholdList != null ) {
+            // In Uevent mode, if any threshold specified for a particular
+            // zone exceeds the max threshold temp, we de-activate that zone.
+            if (mSupportsUEvent) {
+                for (int i = 0; i < thresholdList.size(); i++) {
+                    if (thresholdList.get(i) <= mTripMax)
+                        continue;
+                    else
+                        mMaxThreshExceeded = true;
+                }
+            }
+            if (mMaxThreshExceeded == false) {
+                mZoneTempThresholds = new Integer[thresholdList.size()];
+                mZoneTempThresholdsRaw = new Integer[thresholdList.size()];
+                if (mZoneTempThresholds != null) {
+                    mZoneTempThresholds = thresholdList.toArray(mZoneTempThresholds);
+                }
+                if (mZoneTempThresholdsRaw != null) {
+                    mZoneTempThresholdsRaw = thresholdList.toArray(mZoneTempThresholdsRaw);
+                }
+            }
+        }
+    }
+
+    public int getZoneTempThreshold(int index) {
+        if (index < 0 || index >= mZoneTempThresholds.length)
+            return -1;
+        return mZoneTempThresholds[index];
+    }
+
+    public Integer[] getZoneTempThreshold() {
+        return mZoneTempThresholds;
+    }
+
+    public boolean getZoneActiveStatus() {
+        return mIsZoneActive;
+    }
+
+    public void computeZoneActiveStatus() {
+        // init again. needed because of a profile change
+        mIsZoneActive = false;
+        if (mSupportsUEvent) {
+            // Zone de-activated when any threshold for that zone is
+            // above the allowed Max threshold.
+            if (mMaxThreshExceeded == true) {
+                Log.i(TAG, "deactivate zone:" + mZoneName +
+                        ". Zone Threshold exceeds max trip temp:" + mTripMax);
+                mIsZoneActive = false;
+                return;
+            }
+        }
+        if (mZoneTempThresholds == null) {
+            Log.i(TAG, "deactivate zone:" + getZoneName() + " threshold list is NULL! ");
+            mIsZoneActive = false;
+            return;
+        }
+        // 1. minimum number of states supported must be DEFAULT NUM STATES
+        // 2. if sensor list null disable zone
+        if (mMaxStates < ThermalManager.DEFAULT_NUM_ZONE_STATES) {
+            // substract by 1 since TOFF is transparent to USER
+            int minStateSupport = ThermalManager.DEFAULT_NUM_ZONE_STATES - 1;
+            Log.i(TAG, "deactivate zone:" + getZoneName() + " supports < "
+                    + minStateSupport + " states");
+            mIsZoneActive = false;
+            return;
+        }
+        if (mThermalSensors == null) {
+            Log.i(TAG, "deactivate zone:" + getZoneName() + " sensor list null! ");
+            mIsZoneActive = false;
+            return;
+        }
+
+        if (mSupportsUEvent) {
+            // if uevent just check the first sensor
+            ThermalSensor s = mThermalSensors.get(0);
+            if (s != null && s.getSensorActiveStatus()) {
+                mIsZoneActive = true;
+                return;
+            }
+        } else {
+            if (mPollDelay == null) {
+                Log.i(TAG, "deactivate zone:" + getZoneName()
+                        + " polldelay list null in poll mode! ");
+                mIsZoneActive = false;
+                return;
+            }
+            if (mZoneTempThresholds.length != mPollDelay.length) {
+                Log.i(TAG, "deactivate zone:" + getZoneName()
+                        + " mismatch of polldelay and threshold list in polling mode!");
+                mIsZoneActive = false;
+                return;
+            }
+            for (ThermalSensor ts : mThermalSensors) {
+                if (ts != null && ts.getSensorActiveStatus()) {
+                    mIsZoneActive = true;
+                    return;
+                }
+            }
+        }
+    }
+
+    public void setEmulTempFlag(int flag) {
+        mSupportsEmulTemp = (flag == 1);
+    }
+
+    public boolean getEmulTempFlag() {
+        return mSupportsEmulTemp;
+    }
+
+    // override in Specific zone class which inherit ThermalZone
+    public void startMonitoring() {
+    }
+
+    // override in Specific zone class which inherit ThermalZone
+    public void stopMonitoring() {
+    }
+
+    // override in ModemZone to unregister Modem specific intents
+    // override in VirtualThermalZone to stop UEvent observers
+    public void unregisterReceiver() {
+        if (isUEventSupported()) {
+            mUEventObserver.stopObserving();
+        }
+    }
+
+    // override in VirtualThermalZone class
+    public void startEmulTempObserver() {
+    }
+
+    // override in VirtualThermalZone class
+    public void calibrateThresholds() {
+    }
+
+    /**
+     * Function that calculates the state of the Thermal Zone after reading
+     * temperatures of all sensors in the zone. This function is used when a
+     * zone operates in polling mode.
+     */
+    public boolean isZoneStateChanged() {
+        for (ThermalSensor ts : mThermalSensors) {
+            if (ts.getSensorActiveStatus()) {
+                ts.updateSensorTemp();
+            }
+        }
+        return updateZoneParams();
+    }
+
+    /**
+     * Function that calculates the state of the Thermal Zone after reading
+     * temperatures of all sensors in the zone. This is an overloaded function
+     * used when a zone supports UEvent notifications from kernel. When a
+     * sensor sends an UEvent, it also sends its current temperature as a
+     * parameter of the UEvent.
+     */
+    public boolean isZoneStateChanged(ThermalSensor s, int temp) {
+        if (s == null) return false;
+        s.setCurrTemp(temp);
+        setZoneTemp(temp);
+        return updateZoneParams();
+    }
+
+    /**
+     * Method to update Zone Temperature and Zone Thermal State
+     */
+    public boolean updateZoneParams() {
+        int newZoneState;
+        int prevZoneState = mCurrThermalState;
+
+        if (!updateZoneTemp()) {
+            return false;
+        }
+
+        newZoneState = ThermalUtils.calculateThermalState(mZoneTemp, mZoneTempThresholds);
+        if (newZoneState == prevZoneState) {
+            return false;
+        }
+
+        if (newZoneState == ThermalManager.THERMAL_STATE_OFF) {
+            setZoneState(newZoneState);
+            return true;
+        }
+
+        int threshold = ThermalUtils.getLowerThresholdTemp(prevZoneState, mZoneTempThresholds);
+        // For Interrupt based zones, HW (should) takes care of the debounce.
+        if (!isUEventSupported()) {
+            if (newZoneState < prevZoneState && getZoneTemp() > (threshold - getDBInterval())) {
+                Log.i(TAG, " THERMAL_LOW_EVENT for zone:" + getZoneName()
+                        + " rejected due to debounce interval");
+                return false;
+            }
+        }
+
+        setZoneState(newZoneState);
+        setEventType(newZoneState > prevZoneState
+                ? ThermalManager.THERMAL_HIGH_EVENT
+                : ThermalManager.THERMAL_LOW_EVENT);
+        return true;
+    }
+
+    public boolean updateZoneTemp() {
+        return false;
+    }
+
+    public void registerUevent() {
+        int indx;
+
+        if (mThermalSensors == null) return;
+        if (mThermalSensors.size() > 1) {
+            Log.i(TAG, "for zone:" + getZoneName() + " in uevent mode only first sensor used!");
+        }
+        ThermalSensor sensor = mThermalSensors.get(0);
+        if (sensor == null) return;
+        String path = sensor.getUEventDevPath();
+        if (path.equalsIgnoreCase("invalid")) return;
+        // first time update of sensor temp and zone temp
+        sensor.updateSensorTemp();
+        setZoneTemp(sensor.getCurrTemp());
+        if (updateZoneParams()) {
+            // first intent after initialization
+            sendThermalEvent();
+        }
+        mUEventObserver.startObserving(path);
+        programThresholds(sensor);
+    }
+
+    public UEventObserver mUEventObserver = new UEventObserver() {
+        @Override
+        public void onUEvent(UEventObserver.UEvent event) {
+            String sensorName;
+            int sensorTemp, errorVal, eventType = -1;
+            ThermalZone zone;
+            if (mThermalSensors ==  null) return;
+
+            // Name of the sensor and current temperature are mandatory parameters of an UEvent
+            sensorName = event.get("NAME");
+            sensorTemp = Integer.parseInt(event.get("TEMP"));
+
+            // eventType is an optional parameter. so, check for null case
+            if (event.get("EVENT") != null)
+                eventType = Integer.parseInt(event.get("EVENT"));
+
+            if (sensorName != null) {
+                Log.i(TAG, "UEvent received for sensor:" + sensorName + " temp:" + sensorTemp);
+                // check the name against the first sensor
+                ThermalSensor sensor = mThermalSensors.get(0);
+                if (sensor != null && sensor.getSensorName() != null
+                        && sensor.getSensorName().equalsIgnoreCase(sensorName)) {
+                    // Adjust the sensor temperature based on the 'error correction' temperature.
+                    // For 'LOW' event, debounce interval will take care of this.
+                    errorVal = sensor.getErrorCorrectionTemp();
+                    if (eventType == ThermalManager.THERMAL_HIGH_EVENT)
+                        sensorTemp += errorVal;
+
+                    if (isZoneStateChanged(sensor, sensorTemp)) {
+                        sendThermalEvent();
+                        // reprogram threshold
+                        programThresholds(sensor);
+                    }
+                }
+            }
+        }
+    };
+
+    public void programThresholds(ThermalSensor s) {
+        if (s == null) return;
+        int zoneState = getZoneState();
+        if (zoneState == ThermalManager.THERMAL_STATE_OFF) return;
+        int lowerTripPoint = ThermalUtils.getLowerThresholdTemp(zoneState, getZoneTempThreshold());
+        int upperTripPoint = ThermalUtils.getUpperThresholdTemp(zoneState, getZoneTempThreshold());
+        if (lowerTripPoint != ThermalManager.INVALID_TEMP
+                && upperTripPoint != ThermalManager.INVALID_TEMP) {
+            if (ThermalUtils.writeSysfs(s.getSensorLowTempPath(), lowerTripPoint) == -1) {
+                Log.i(TAG, "error while programming lower trip point:" + lowerTripPoint
+                        + "for sensor:" + s.getSensorName());
+            }
+            if (ThermalUtils.writeSysfs(s.getSensorHighTempPath(), upperTripPoint) == -1) {
+                Log.i(TAG, "error while programming upper trip point:" + upperTripPoint
+                        + "for sensor:" + s.getSensorName());
+            }
+        }
+    }
+
+    public void sendThermalEvent() {
+        ThermalEvent event = new ThermalEvent(mZoneID, mCurrEventType,
+                mCurrThermalState, mZoneTemp, mZoneName,
+                ThermalManager.getCurProfileName());
+        ThermalManager.addThermalEvent(event);
+    }
+}
diff --git a/ituxd/src/com/intel/thermal/ThermalZoneMonitor.java b/ituxd/src/com/intel/thermal/ThermalZoneMonitor.java
new file mode 100644
index 0000000..5c38b43
--- /dev/null
+++ b/ituxd/src/com/intel/thermal/ThermalZoneMonitor.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2014 Intel Corporation All Rights Reserved.
+ *
+ * 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.
+ */
+
+package com.intel.thermal;
+
+import android.util.Log;
+
+/**
+ * The ThermalZoneMonitor class runs a thread for each zone
+ * with which it is instantiated.
+ *
+ * @hide
+ */
+public class ThermalZoneMonitor implements Runnable {
+    private static final String TAG = "ThermalZoneMonitor";
+    private Thread t;
+    private ThermalZone zone;
+    private String mThreadName;
+    private boolean stop = false;
+
+    public ThermalZoneMonitor(ThermalZone tz) {
+        zone = tz;
+        mThreadName = "ThermalZone" + zone.getZoneId();
+        t = new Thread(this, mThreadName);
+        t.start();
+    }
+
+    public void stopMonitor() {
+        stop = true;
+        t.interrupt();
+    }
+
+    public void run() {
+        try {
+            while (!stop && !t.isInterrupted()) {
+                if (zone.isZoneStateChanged()) {
+                    zone.sendThermalEvent();
+                }
+                // stop value can be changed before going to sleep
+                if (!stop) {
+                    Thread.sleep(zone.getPollDelay(zone.getZoneState()));
+                }
+            }
+        } catch (InterruptedException iex) {
+            Log.i(TAG, "Stopping thread " + mThreadName + " [InterruptedException]");
+        }
+    }
+}
diff --git a/ituxd/src/com/intel/thermal/VirtualThermalZone.java b/ituxd/src/com/intel/thermal/VirtualThermalZone.java
new file mode 100644
index 0000000..1f4fd4d
--- /dev/null
+++ b/ituxd/src/com/intel/thermal/VirtualThermalZone.java
@@ -0,0 +1,241 @@
+/*
+ * Copyright 2014 Intel Corporation All Rights Reserved.
+ *
+ * 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.
+ */
+
+package com.intel.thermal;
+
+import android.os.UEventObserver;
+import android.util.Log;
+
+import java.lang.Math;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+/**
+ * The VirtualThermalZone class extends the ThermalZone class, with a default
+ * implementation of the isZoneStateChanged() method. This computes the
+ * zone state by computing the equation, which can be linear / higher order implementation
+ * @hide
+ */
+public class VirtualThermalZone extends ThermalZone {
+
+    private static final String TAG = "VirtualThermalZone";
+    private String mEmulTempPath;
+    private ThermalZoneMonitor mTzm = null;
+
+    public void setEmulTempPath(String path) {
+        mEmulTempPath = path;
+    }
+
+    public String getEmulTempPath() {
+        return mEmulTempPath;
+    }
+
+    public VirtualThermalZone() {
+        super();
+    }
+
+    // overridden to start UEvent observer only for Virtual zone
+    public void startEmulTempObserver() {
+        if (!getEmulTempFlag()) {
+            return;
+        }
+        int indx = ThermalUtils.getThermalZoneIndex(getZoneName());
+        if (indx == -1) {
+            Log.i(TAG, "Could not obtain emul_temp sysfs node for " + getZoneName());
+            return;
+        }
+        String uEventDevPath = ThermalManager.sUEventDevPath + indx;
+        setEmulTempPath(ThermalManager.sSysfsSensorBasePath + indx + "/emul_temp");
+        mEmulTempObserver.startObserving(uEventDevPath);
+    }
+
+    public void unregisterReceiver() {
+        super.unregisterReceiver();
+        if (getEmulTempFlag()) {
+            mEmulTempObserver.stopObserving();
+        }
+    }
+
+    public void startMonitoring() {
+        mTzm = new ThermalZoneMonitor(this);
+    }
+
+    public void stopMonitoring() {
+        if (mTzm != null) {
+            mTzm.stopMonitor();
+        }
+    }
+
+    // override fucntion
+    public void calibrateThresholds() {
+        ThermalSensor ts = getThermalSensorList().get(0);
+        ThermalSensorAttrib sa = mThermalSensorsAttribMap.get(ts.getSensorName());
+        if (sa == null) {
+            return;
+        }
+        Integer weights[] = sa.getWeights();
+        int m = weights[0];
+        int c = getOffset();
+
+        if (m == 0) return;
+        for (int i = 0; i < mZoneTempThresholdsRaw.length; i++) {
+            // We do not want to convert '0'. Let it represent 0 C.
+            if (mZoneTempThresholdsRaw[i] == 0) continue;
+            // Get raw systherm temperature: y=mx+c <--> x=(y-c)/m
+            mZoneTempThresholds[i] = ((mZoneTempThresholdsRaw[i] - c) * 1000) / m;
+        }
+        Log.i(TAG, "calibrateThresholds[]: " + Arrays.toString(mZoneTempThresholds));
+    }
+
+    private int calculateZoneTemp() {
+        int curZoneTemp = 0;
+        int weightedTemp;
+        ArrayList<ThermalSensor> list = getThermalSensorList();
+
+        // Check if the SensorList is sane and usable
+        if (list == null || list.get(0) == null) {
+            return ThermalManager.INVALID_TEMP;
+        }
+
+        if (isUEventSupported()) {
+            // for uevent based monitoring only first sensor used
+            ThermalSensor ts = list.get(0);
+            weightedTemp = getWeightedTemp(ts, ts.readSensorTemp());
+            return weightedTemp == ThermalManager.INVALID_TEMP
+                    ? ThermalManager.INVALID_TEMP : weightedTemp + getOffset();
+        }
+
+        // Polling mode
+        for (ThermalSensor ts : list) {
+            if (ts != null && ts.getSensorActiveStatus()) {
+                weightedTemp = getWeightedTemp(ts, ts.readSensorTemp());
+                if (weightedTemp == ThermalManager.INVALID_TEMP) {
+                    return ThermalManager.INVALID_TEMP;
+                }
+                curZoneTemp += weightedTemp;
+            }
+        }
+        return curZoneTemp + getOffset();
+    }
+
+    private UEventObserver mEmulTempObserver = new UEventObserver() {
+        @Override
+        public void onUEvent(UEventObserver.UEvent event) {
+            String type = event.get("EVENT");
+            if (type == null || Integer.parseInt(type) != ThermalManager.THERMAL_EMUL_TEMP_EVENT) {
+                Log.i(TAG, "EventType does not match");
+                return;
+            }
+
+            if (!getZoneName().equals(event.get("NAME"))) {
+                Log.i(TAG, "ZoneName does not match");
+                return;
+            }
+
+            int temp = calculateZoneTemp();
+            if (temp == ThermalManager.INVALID_TEMP) {
+                Log.i(TAG, "Obtained INVALID_TEMP[0xDEADBEEF]");
+                return;
+            }
+
+            String path = getEmulTempPath();
+            if (path == null) {
+                Log.i(TAG, "EmulTempPath is null");
+                return;
+            }
+
+            int ret = ThermalUtils.writeSysfs(path, temp);
+            if (ret == -1) {
+                Log.i(TAG, "Writing into emul_temp sysfs failed");
+            }
+        }
+    };
+
+    // override function
+    public boolean updateZoneTemp() {
+        int curZoneTemp = ThermalManager.INVALID_TEMP;
+        int rawSensorTemp, sensorTemp;
+        int weightedTemp;
+        boolean flag = false;
+
+        if (isUEventSupported()) {
+            // In UEvent mode, the obtained temperature is the zone temperature
+            return true;
+        } else {
+            for (ThermalSensor ts : getThermalSensorList()) {
+                if (ts != null && ts.getSensorActiveStatus()) {
+                    if (flag == false) {
+                        // one time initialization of zone temp
+                        curZoneTemp = 0;
+                        flag = true;
+                    }
+                    weightedTemp = getWeightedTemp(ts);
+                    if (weightedTemp != ThermalManager.INVALID_TEMP) {
+                        curZoneTemp += weightedTemp;
+                    }
+                }
+            }
+        }
+
+        if (curZoneTemp != ThermalManager.INVALID_TEMP) {
+            curZoneTemp += getOffset();
+            setZoneTemp(curZoneTemp);
+            if (getMovingAverageFlag() && !isUEventSupported()) {
+                // only for polling mode apply moving average on predicted zone temp
+                setZoneTemp(movingAverageTemp());
+            }
+            return true;
+        }
+
+        return false;
+    }
+
+    private int getWeightedTemp(ThermalSensor ts) {
+        return getWeightedTemp(ts, ts.getCurrTemp());
+    }
+
+    private int getWeightedTemp(ThermalSensor ts, int rawSensorTemp) {
+        int curZoneTemp = 0;
+        Integer weights[], order[];
+        ThermalSensorAttrib sa = mThermalSensorsAttribMap.get(ts.getSensorName());
+
+        // No point in calculating 'WeightedTemp' on an 'anyway invalid' temperature
+        if (rawSensorTemp == ThermalManager.INVALID_TEMP || sa == null) {
+            return ThermalManager.INVALID_TEMP;
+        }
+
+        weights = sa.getWeights();
+        order = sa.getOrder();
+        if (weights == null && order == null) return rawSensorTemp;
+        if (weights != null) {
+            if (order == null) {
+                // only first weight will be considered
+                return (weights[0] * rawSensorTemp) / 1000;
+            } else if (order != null && weights.length == order.length) {
+                // if order array is provided in xml,
+                // it should be of same size as weights array
+                int sensorTemp = 0;
+                for (int i = 0; i < weights.length; i++) {
+                    // Divide by 1000 to convert to mC
+                    sensorTemp += (weights[i] * (int) Math.pow(rawSensorTemp, order[i])) / 1000;
+                }
+                return sensorTemp;
+            }
+        }
+        // for every other mismatch return the raw sensor temp
+        return rawSensorTemp;
+    }
+}
diff --git a/ituxd/src/com/intel/thermal/ituxdApp.java b/ituxd/src/com/intel/thermal/ituxdApp.java
new file mode 100644
index 0000000..aa2777d
--- /dev/null
+++ b/ituxd/src/com/intel/thermal/ituxdApp.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.intel.thermal;
+
+import android.app.Application;
+import android.content.Intent;
+import android.os.SystemProperties;
+import android.util.Log;
+
+public class ituxdApp extends Application {
+
+    static final String TAG = "ituxdApp";
+
+    public ituxdApp() {
+
+    }
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+
+        if ("1".equals(SystemProperties.get("persist.service.thermal", "0"))) {
+            Log.i(TAG, "Thermal Service enabled");
+            startService(new Intent(this, ThermalService.class));
+        } else {
+            Log.i(TAG, "Thermal Service disabled");
+        }
+    }
+}