blob: 1f4fd4d7c6669a423df4cb223067cb8013181df4 [file] [log] [blame]
/*
* 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;
}
}