Home | History | Annotate | Download | only in thermal
      1 /*
      2  * Copyright 2014 Intel Corporation All Rights Reserved.
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.intel.thermal;
     18 
     19 import android.os.UEventObserver;
     20 import android.util.Log;
     21 
     22 import java.lang.Math;
     23 import java.util.ArrayList;
     24 import java.util.Arrays;
     25 
     26 /**
     27  * The VirtualThermalZone class extends the ThermalZone class, with a default
     28  * implementation of the isZoneStateChanged() method. This computes the
     29  * zone state by computing the equation, which can be linear / higher order implementation
     30  * @hide
     31  */
     32 public class VirtualThermalZone extends ThermalZone {
     33 
     34     private static final String TAG = "VirtualThermalZone";
     35     private String mEmulTempPath;
     36     private ThermalZoneMonitor mTzm = null;
     37 
     38     public void setEmulTempPath(String path) {
     39         mEmulTempPath = path;
     40     }
     41 
     42     public String getEmulTempPath() {
     43         return mEmulTempPath;
     44     }
     45 
     46     public VirtualThermalZone() {
     47         super();
     48     }
     49 
     50     // overridden to start UEvent observer only for Virtual zone
     51     public void startEmulTempObserver() {
     52         if (!getEmulTempFlag()) {
     53             return;
     54         }
     55         int indx = ThermalUtils.getThermalZoneIndex(getZoneName());
     56         if (indx == -1) {
     57             Log.i(TAG, "Could not obtain emul_temp sysfs node for " + getZoneName());
     58             return;
     59         }
     60         String uEventDevPath = ThermalManager.sUEventDevPath + indx;
     61         setEmulTempPath(ThermalManager.sSysfsSensorBasePath + indx + "/emul_temp");
     62         mEmulTempObserver.startObserving(uEventDevPath);
     63     }
     64 
     65     public void unregisterReceiver() {
     66         super.unregisterReceiver();
     67         if (getEmulTempFlag()) {
     68             mEmulTempObserver.stopObserving();
     69         }
     70     }
     71 
     72     public void startMonitoring() {
     73         mTzm = new ThermalZoneMonitor(this);
     74     }
     75 
     76     public void stopMonitoring() {
     77         if (mTzm != null) {
     78             mTzm.stopMonitor();
     79         }
     80     }
     81 
     82     // override fucntion
     83     public void calibrateThresholds() {
     84         ThermalSensor ts = getThermalSensorList().get(0);
     85         ThermalSensorAttrib sa = mThermalSensorsAttribMap.get(ts.getSensorName());
     86         if (sa == null) {
     87             return;
     88         }
     89         Integer weights[] = sa.getWeights();
     90         int m = weights[0];
     91         int c = getOffset();
     92 
     93         if (m == 0) return;
     94         for (int i = 0; i < mZoneTempThresholdsRaw.length; i++) {
     95             // We do not want to convert '0'. Let it represent 0 C.
     96             if (mZoneTempThresholdsRaw[i] == 0) continue;
     97             // Get raw systherm temperature: y=mx+c <--> x=(y-c)/m
     98             mZoneTempThresholds[i] = ((mZoneTempThresholdsRaw[i] - c) * 1000) / m;
     99         }
    100         Log.i(TAG, "calibrateThresholds[]: " + Arrays.toString(mZoneTempThresholds));
    101     }
    102 
    103     private int calculateZoneTemp() {
    104         int curZoneTemp = 0;
    105         int weightedTemp;
    106         ArrayList<ThermalSensor> list = getThermalSensorList();
    107 
    108         // Check if the SensorList is sane and usable
    109         if (list == null || list.get(0) == null) {
    110             return ThermalManager.INVALID_TEMP;
    111         }
    112 
    113         if (isUEventSupported()) {
    114             // for uevent based monitoring only first sensor used
    115             ThermalSensor ts = list.get(0);
    116             weightedTemp = getWeightedTemp(ts, ts.readSensorTemp());
    117             return weightedTemp == ThermalManager.INVALID_TEMP
    118                     ? ThermalManager.INVALID_TEMP : weightedTemp + getOffset();
    119         }
    120 
    121         // Polling mode
    122         for (ThermalSensor ts : list) {
    123             if (ts != null && ts.getSensorActiveStatus()) {
    124                 weightedTemp = getWeightedTemp(ts, ts.readSensorTemp());
    125                 if (weightedTemp == ThermalManager.INVALID_TEMP) {
    126                     return ThermalManager.INVALID_TEMP;
    127                 }
    128                 curZoneTemp += weightedTemp;
    129             }
    130         }
    131         return curZoneTemp + getOffset();
    132     }
    133 
    134     private UEventObserver mEmulTempObserver = new UEventObserver() {
    135         @Override
    136         public void onUEvent(UEventObserver.UEvent event) {
    137             String type = event.get("EVENT");
    138             if (type == null || Integer.parseInt(type) != ThermalManager.THERMAL_EMUL_TEMP_EVENT) {
    139                 Log.i(TAG, "EventType does not match");
    140                 return;
    141             }
    142 
    143             if (!getZoneName().equals(event.get("NAME"))) {
    144                 Log.i(TAG, "ZoneName does not match");
    145                 return;
    146             }
    147 
    148             int temp = calculateZoneTemp();
    149             if (temp == ThermalManager.INVALID_TEMP) {
    150                 Log.i(TAG, "Obtained INVALID_TEMP[0xDEADBEEF]");
    151                 return;
    152             }
    153 
    154             String path = getEmulTempPath();
    155             if (path == null) {
    156                 Log.i(TAG, "EmulTempPath is null");
    157                 return;
    158             }
    159 
    160             int ret = ThermalUtils.writeSysfs(path, temp);
    161             if (ret == -1) {
    162                 Log.i(TAG, "Writing into emul_temp sysfs failed");
    163             }
    164         }
    165     };
    166 
    167     // override function
    168     public boolean updateZoneTemp() {
    169         int curZoneTemp = ThermalManager.INVALID_TEMP;
    170         int rawSensorTemp, sensorTemp;
    171         int weightedTemp;
    172         boolean flag = false;
    173 
    174         if (isUEventSupported()) {
    175             // In UEvent mode, the obtained temperature is the zone temperature
    176             return true;
    177         } else {
    178             for (int i = 0; i < mThermalSensors.size(); i++) {
    179                 if (mThermalSensors.get(i) != null
    180                         && mThermalSensors.get(i).getSensorActiveStatus()) {
    181                     if (flag == false) {
    182                         // one time initialization of zone temp
    183                         curZoneTemp = 0;
    184                         flag = true;
    185                     }
    186                     weightedTemp = getWeightedTemp(mThermalSensors.get(i));
    187                     if (weightedTemp != ThermalManager.INVALID_TEMP) {
    188                         curZoneTemp += weightedTemp;
    189                     }
    190                 }
    191             }
    192         }
    193 
    194         if (curZoneTemp != ThermalManager.INVALID_TEMP) {
    195             curZoneTemp += getOffset();
    196             setZoneTemp(curZoneTemp);
    197             if (getMovingAverageFlag() && !isUEventSupported()) {
    198                 // only for polling mode apply moving average on predicted zone temp
    199                 setZoneTemp(movingAverageTemp());
    200             }
    201             return true;
    202         }
    203 
    204         return false;
    205     }
    206 
    207     private int getWeightedTemp(ThermalSensor ts) {
    208         return getWeightedTemp(ts, ts.getCurrTemp());
    209     }
    210 
    211     private int getWeightedTemp(ThermalSensor ts, int rawSensorTemp) {
    212         int curZoneTemp = 0;
    213         Integer weights[], order[];
    214         ThermalSensorAttrib sa = mThermalSensorsAttribMap.get(ts.getSensorName());
    215 
    216         // No point in calculating 'WeightedTemp' on an 'anyway invalid' temperature
    217         if (rawSensorTemp == ThermalManager.INVALID_TEMP || sa == null) {
    218             return ThermalManager.INVALID_TEMP;
    219         }
    220 
    221         weights = sa.getWeights();
    222         order = sa.getOrder();
    223         if (weights == null && order == null) return rawSensorTemp;
    224         if (weights != null) {
    225             if (order == null) {
    226                 // only first weight will be considered
    227                 return (weights[0] * rawSensorTemp) / 1000;
    228             } else if (order != null && weights.length == order.length) {
    229                 // if order array is provided in xml,
    230                 // it should be of same size as weights array
    231                 int sensorTemp = 0;
    232                 for (int i = 0; i < weights.length; i++) {
    233                     // Divide by 1000 to convert to mC
    234                     sensorTemp += (weights[i] * (int) Math.pow(rawSensorTemp, order[i])) / 1000;
    235                 }
    236                 return sensorTemp;
    237             }
    238         }
    239         // for every other mismatch return the raw sensor temp
    240         return rawSensorTemp;
    241     }
    242 }
    243