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