| /* |
| * 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; |
| } |
| } |