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
17package com.intel.thermal;
18
19import com.intel.thermal.ThermalManager;
20
21import android.util.Log;
22
23import java.io.File;
24import java.util.ArrayList;
25import java.util.Arrays;
26
27/**
28 * The ThermalSensor class describes the attributes of a Thermal Sensor. This
29 * class implements methods that retrieve temperature sensor information from
30 * the kernel through the native interface.
31 *
32 * @hide
33 */
34public class ThermalSensor {
35
36    private static final String TAG = "ThermalSensor";
37    private String mSensorPath;     /* sys path to read temp from */
38    private String mSensorName;     /* name of the sensor */
39    private String mInputTempPath;  /* sys path to read the current temp */
40    private String mHighTempPath;   /* sys path to set the intermediate upper threshold */
41    private String mLowTempPath;    /* sys path to set the intermediate lower threshold */
42    private String mUEventDevPath;  /* sys path for uevent listener */
43    private int mErrorCorrectionTemp; /* Temperature difference in mC */
44    private int mSensorID = -1;
45    private int mSensorState;       /* Thermal state of the sensor */
46    private int mCurrTemp;          /* Holds the latest temperature of the sensor */
47    private int mSensorSysfsIndx; /* Index of this sensor in the sysfs */
48    private boolean mIsSensorActive = false; /* Whether this sensor is active */
49
50    public void printAttrs() {
51        Log.i(TAG, "mSensorName: " + mSensorName);
52        Log.i(TAG, "mSensorPath: " + mSensorPath);
53        Log.i(TAG, "mInputTempPath: " + mInputTempPath);
54        Log.i(TAG, "mHighTempPath: " + mHighTempPath);
55        Log.i(TAG, "mLowTempPath: " + mLowTempPath);
56        Log.i(TAG, "mUEventDevPath: " + mUEventDevPath);
57        Log.i(TAG, "mErrorCorrection: " + mErrorCorrectionTemp);
58    }
59
60    private void setSensorSysfsPath() {
61        int indx = ThermalUtils.getThermalZoneIndex(mSensorName);
62        // The battery subsystem exposes sensors under different names.
63        // The only commonality among them is that all of them contain
64        // the string "battery".
65        if (indx == -1 && mSensorName.contains("battery")) {
66            indx = ThermalUtils.getThermalZoneIndexContains("battery");
67        }
68
69        if (indx != -1) {
70            mSensorPath = ThermalManager.sSysfsSensorBasePath + indx + "/";
71        }
72
73        mSensorSysfsIndx = indx;
74    }
75
76    public boolean getSensorActiveStatus() {
77        return mIsSensorActive;
78    }
79
80    public String getSensorSysfsPath() {
81        return mSensorPath;
82    }
83
84    public ThermalSensor() {
85        mSensorState = ThermalManager.THERMAL_STATE_OFF;
86        mCurrTemp = ThermalManager.INVALID_TEMP;
87        mSensorPath = "auto";
88        mInputTempPath = "auto";
89        mHighTempPath = "auto";
90        mLowTempPath = "auto";
91        mUEventDevPath = "auto";
92
93        // Set default value of 'correction temperature' to 1000mC
94        mErrorCorrectionTemp = 1000;
95    }
96
97    public int getSensorID() {
98        return mSensorID;
99    }
100
101    public int getSensorSysfsIndx() {
102        return mSensorSysfsIndx;
103    }
104
105    public String getSensorPath() {
106        return mSensorPath;
107    }
108
109    /**
110     * This function sets the sensor path to the given String value. If the
111     * String is "auto" it loops through the standard sysfs path, to obtain the
112     * 'mSensorPath'. The standard sysfs path is /sys/class/
113     * thermal/thermal_zoneX and the look up is based on 'mSensorName'.
114     * If sensor path is "none", sensor temp is not read via any sysfs
115     */
116    public void setSensorPath(String path) {
117        if (path.equalsIgnoreCase("auto")) {
118            setSensorSysfsPath();
119        } else {
120            mSensorPath = path;
121        }
122    }
123
124    private boolean isSensorSysfsValid(String path) {
125        return ThermalUtils.isFileExists(path);
126    }
127
128    public String getSensorName() {
129        return mSensorName;
130    }
131
132    public void setSensorName(String name) {
133        mSensorName = name;
134    }
135
136    public void setUEventDevPath(String devPath) {
137        mUEventDevPath = devPath;
138    }
139
140    public String getUEventDevPath() {
141        return mUEventDevPath;
142    }
143
144    public void setErrorCorrectionTemp(int temp) {
145        mErrorCorrectionTemp = temp;
146    }
147
148    public int getErrorCorrectionTemp() {
149        return mErrorCorrectionTemp;
150    }
151
152
153    public void setInputTempPath(String name) {
154        // sensor path is none, it means sensor temperature reporting is
155        // not sysfs based. So turn sensor active by default.
156        // If the sensor path does not exist, deactivate the sensor.
157        if (mSensorPath != null && mSensorPath.equalsIgnoreCase("none")) {
158            mIsSensorActive = true;
159        } else {
160            if (name != null && name.equalsIgnoreCase("auto")) {
161                name = "temp";
162            }
163            mInputTempPath = mSensorPath + name;
164            if (!isSensorSysfsValid(mInputTempPath)) {
165                mIsSensorActive = false;
166                Log.i(TAG, "Sensor:" + mSensorName + " path:" + mInputTempPath
167                        + " is invalid...deactivaing Sensor");
168            } else {
169                mIsSensorActive = true;
170            }
171        }
172    }
173
174    public String getSensorInputTempPath() {
175        return mInputTempPath;
176    }
177
178    public void setHighTempPath(String name) {
179        if (name != null && name.equalsIgnoreCase("auto")) {
180            mHighTempPath = mSensorPath + ThermalManager.sSysfsSensorHighTempPath;
181        } else {
182            if (mSensorPath != null && mSensorPath.equalsIgnoreCase("none")) {
183                mHighTempPath = "invalid";
184            } else {
185                mHighTempPath = mSensorPath + name;
186            }
187        }
188    }
189
190    public String getSensorHighTempPath() {
191        return mHighTempPath;
192    }
193
194    public void setLowTempPath(String name) {
195        if (name != null && name.equalsIgnoreCase("auto")) {
196            mLowTempPath = mSensorPath + ThermalManager.sSysfsSensorLowTempPath;
197        } else {
198            if (mSensorPath != null && mSensorPath.equalsIgnoreCase("none")) {
199                mLowTempPath = "invalid";
200            } else {
201                mLowTempPath = mSensorPath + name;
202            }
203        }
204    }
205
206    public String getSensorLowTempPath() {
207        return mLowTempPath;
208    }
209
210    public void setCurrTemp(int temp) {
211        mCurrTemp = temp;
212    }
213
214    public int getCurrTemp() {
215        return mCurrTemp;
216    }
217
218    /**
219     * Method that actually does a Sysfs read.
220     */
221    public int readSensorTemp() {
222        int val = ThermalUtils.readSysfsTemp(mInputTempPath);
223        if (val <= ThermalManager.ABS_ZERO) {
224            // Error will be returned as negative offset from absolute zero in milli degree C
225            Log.e(TAG, "readSensorTemp failed with error:" + (val - ThermalManager.ABS_ZERO));
226            val = ThermalManager.INVALID_TEMP;
227        }
228        return val;
229    }
230
231    /**
232     * Method to read the current temperature from sensor. This method should be
233     * used only when we want to obtain the latest temperature from sensors.
234     * Otherwise, the getCurrTemp method should be used, which returns the
235     * previously read value.
236     */
237    public void updateSensorTemp() {
238        int val = readSensorTemp();
239        if (val != ThermalManager.INVALID_TEMP) {
240            setCurrTemp(val);
241        }
242    }
243
244    public int getSensorThermalState() {
245        return mSensorState;
246    }
247
248    public void setSensorThermalState(int state) {
249        mSensorState = state;
250    }
251
252    public void setAutoValues() {
253        if (mSensorPath.equalsIgnoreCase("auto")) {
254            setSensorPath(mSensorPath);
255        }
256        if (mInputTempPath.equalsIgnoreCase("auto")) {
257            setInputTempPath(mInputTempPath);
258        }
259        if (mHighTempPath.equalsIgnoreCase("auto")) {
260            setHighTempPath(mHighTempPath);
261        }
262        if (mLowTempPath.equalsIgnoreCase("auto")) {
263            setLowTempPath(mLowTempPath);
264        }
265        if (mUEventDevPath.equalsIgnoreCase("auto")) {
266            // build the sensor UEvent listener path
267            if (mSensorSysfsIndx == -1) {
268                mUEventDevPath = "invalid";
269                Log.i(TAG, "Cannot build UEvent path for sensor:" + mSensorName);
270                return;
271            } else {
272                mUEventDevPath = ThermalManager.sUEventDevPath + mSensorSysfsIndx;
273            }
274        } else if (!mUEventDevPath.contains("DEVPATH=")) {
275            mUEventDevPath = "DEVPATH=" + mUEventDevPath;
276        }
277    }
278
279}
280