1bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan/*
2bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan * Copyright 2014 Intel Corporation All Rights Reserved.
3bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan *
4bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan * Licensed under the Apache License, Version 2.0 (the "License");
5bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan * you may not use this file except in compliance with the License.
6bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan * You may obtain a copy of the License at
7bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan *
8bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan *      http://www.apache.org/licenses/LICENSE-2.0
9bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan *
10bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan * Unless required by applicable law or agreed to in writing, software
11bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan * distributed under the License is distributed on an "AS IS" BASIS,
12bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan * See the License for the specific language governing permissions and
14bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan * limitations under the License.
15bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan */
16bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
17bc0b49155603ba1c0c1fc86d13127d04021e7c70shravanpackage com.intel.thermal;
18bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
19bc0b49155603ba1c0c1fc86d13127d04021e7c70shravanimport android.os.UEventObserver;
20bc0b49155603ba1c0c1fc86d13127d04021e7c70shravanimport android.util.Log;
21bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
22bc0b49155603ba1c0c1fc86d13127d04021e7c70shravanimport java.util.ArrayList;
23bc0b49155603ba1c0c1fc86d13127d04021e7c70shravanimport java.util.Arrays;
24bc0b49155603ba1c0c1fc86d13127d04021e7c70shravanimport java.util.Hashtable;
25bc0b49155603ba1c0c1fc86d13127d04021e7c70shravanimport java.util.Iterator;
26bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
27bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan/**
28bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan * The ThermalZone class contains attributes of a Thermal zone. A Thermal zone
29bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan * can have one or more sensors associated with it. Whenever the temperature of a
30bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan * thermal zone crosses the thresholds configured, actions are taken.
31bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan */
32bc0b49155603ba1c0c1fc86d13127d04021e7c70shravanpublic class ThermalZone {
33bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
34bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    private static final String TAG = "ThermalZone";
35bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
36bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    protected int mZoneID;               /* ID of the Thermal zone */
37bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    protected int mCurrThermalState;     /* Current thermal state of the zone */
38bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    protected int mCurrEventType;        /* specifies thermal event type, HIGH or LOW */
39bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    protected String mZoneName;          /* Name of the Thermal zone */
40bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    protected int mMaxStates;
41bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    /* List of sensors under this thermal zone */
42bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    protected ArrayList<ThermalSensor> mThermalSensors = null;
43bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    // sensor name - sensorAttrib object hash to improve lookup performace
44bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    // during runtime thermal monitoring like re-programming sensor thresholds
45bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    // calculating weighted zone temp.
46bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    protected Hashtable<String, ThermalSensorAttrib> mThermalSensorsAttribMap = null;
47bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    protected int mZoneTemp;             /* Temperature of the Thermal Zone */
48bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    protected boolean mSupportsEmulTemp = true;
49bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    private int mDebounceInterval;    /* Debounce value to avoid thrashing of throttling actions */
50bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    private Integer mPollDelay[];     /* Delay between sucessive polls in milli seconds */
51bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    protected boolean mSupportsUEvent;  /* Determines if Sensor supports Uevents */
52bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    private String mZoneLogic;      /* Logic to be used to determine thermal state of zone */
53bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    private boolean mIsZoneActive = false;
54bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    private boolean mMaxThreshExceeded = false;
55bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    private int mTripMax;
56bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    private int mOffset = 0;
57bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    protected Integer mZoneTempThresholds[];  /* Array containing temperature thresholds */
58bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    // mZoneTempThresholdsRaw contains the Raw thresholds (as specified in xml).
59bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    // mZoneTempThresholds contsins the calibrated thresholds that are used
60bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    // to detect zone state change at runtime.
61bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    protected Integer mZoneTempThresholdsRaw[];
62bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
63bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    /* MovingAverage related declarations */
64bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    private int mRecordedValuesHead = -1; /* Index pointing to the head of past values of sensor */
65bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    private int mRecordedValues[];        /* Recorded values of sensor */
66bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    private int mNumberOfInstances[];     /* Number of recorded instances to be considered */
67bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    private ArrayList<Integer> mWindowList = null;
68bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    private boolean mIsMovingAverage = false; /* By default false */
69bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
70bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    // override this method in ModemZone to limit num states to default
71bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    public void setMaxStates(int state) {
72bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        mMaxStates = state;
73bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    }
74bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
75bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    public void updateMaxStates(int state) {
76bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        setMaxStates(state);
77bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    }
78bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
79bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    public int getMaxStates() {
80bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        return mMaxStates;
81bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    }
82bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
83bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    public boolean getMovingAverageFlag() {
84bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        return mIsMovingAverage;
85bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    }
86bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
87bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    public void setMovingAvgWindow(ArrayList<Integer> windowList) {
88bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        int maxValue = Integer.MIN_VALUE; // -2^31
89bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
90bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        if (windowList == null || mPollDelay == null) {
91bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            Log.i(TAG, "setMovingAvgWindow input is null");
92bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            mIsMovingAverage = false;
93bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            return;
94bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        }
95bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        mNumberOfInstances = new int[windowList.size()];
96bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        if (mNumberOfInstances == null) {
97bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            Log.i(TAG, "failed to create poll windowlist");
98bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            mIsMovingAverage = false;
99bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            return;
100bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        }
101bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        mIsMovingAverage = true;
102bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        for (int i = 0; i < windowList.size(); i++) {
103bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            if (mPollDelay[i] == 0) {
104bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                mIsMovingAverage = false;
105bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                Log.i(TAG, "Polling delay is zero, WMA disabled\n");
106bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                return;
107bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            }
108bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            mNumberOfInstances[i] = windowList.get(i) / mPollDelay[i];
109bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            if (mNumberOfInstances[i] <= 0) {
110bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                mIsMovingAverage = false;
111bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                Log.i(TAG, "Polling delay greater than moving average window, WMA disabled\n");
112bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                return;
113bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            }
114bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            maxValue = Math.max(mNumberOfInstances[i], maxValue);
115bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        }
116bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        mRecordedValues = new int[maxValue];
117bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    }
118bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
119bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    public int movingAverageTemp() {
120bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        int index, calIndex;
121bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        int predictedTemp = 0;
122bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
123bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        mRecordedValuesHead = (mRecordedValuesHead + 1) % mRecordedValues.length;
124bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        mRecordedValues[mRecordedValuesHead] = mZoneTemp;
125bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
126bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        // Sensor State starts with -1, InstancesList starts with 0
127bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        for (index = 0; index < mNumberOfInstances[mCurrThermalState + 1]; index++) {
128bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            calIndex = mRecordedValuesHead - index;
129bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            if (calIndex < 0) {
130bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                calIndex = mRecordedValues.length + calIndex;
131bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            }
132bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            predictedTemp += mRecordedValues[calIndex];
133bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        }
134bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        return predictedTemp / index;
135bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    }
136bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
137bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    public void printAttrs() {
138bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        Log.i(TAG, "mZoneID:" + Integer.toString(mZoneID));
139bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        Log.i(TAG, "mDBInterval: " + Integer.toString(mDebounceInterval));
140bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        Log.i(TAG, "mZoneName:" + mZoneName);
141bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        Log.i(TAG, "mSupportsUEvent:" + Boolean.toString(mSupportsUEvent));
142bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        Log.i(TAG, "mZoneLogic:" + mZoneLogic);
143bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        Log.i(TAG, "mOffset:" + mOffset);
144bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        Log.i(TAG, "mPollDelay[]:" + Arrays.toString(mPollDelay));
145bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        Log.i(TAG, "mZoneTempThresholds[]: " + Arrays.toString(mZoneTempThresholds));
146bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        Log.i(TAG, "mNumberOfInstances[]: " + Arrays.toString(mNumberOfInstances));
147bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        Log.i(TAG, "mEmulTempFlag:" + mSupportsEmulTemp);
148bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        Log.i(TAG, "MaxStates:" + getMaxStates());
149bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        printStateThresholdMap();
150bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        printSensors();
151bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        printSensorAttribList();
152bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    }
153bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
154bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    public void printStateThresholdMap() {
155bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        if (mZoneTempThresholds == null
156bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                || mZoneTempThresholds.length < ThermalManager.DEFAULT_NUM_ZONE_STATES) return;
157bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        StringBuilder s = new StringBuilder();
158bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        s.append("[" + "State0" + "<" + mZoneTempThresholds[1] + "];");
159bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        for (int index = 2; index < getMaxStates(); index++) {
160bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            int curstate = index - 1;
161bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            s.append("[" + mZoneTempThresholds[index - 1] + "<=" + "State"
162bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                    + curstate + "<" + mZoneTempThresholds[index] + "];");
163bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        }
164bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        Log.i(TAG, "states-threshold map:" + s.toString());
165bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    }
166bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
167bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    private void printSensors() {
168bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        if (mThermalSensors == null) return;
169bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        StringBuilder s =  new StringBuilder();
170bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        for (ThermalSensor ts : mThermalSensors) {
171bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            if (ts != null) {
172bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                s.append(ts.getSensorName());
173bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                s.append(",");
174bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            }
175bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        }
176bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        Log.i(TAG, "zoneID: " + mZoneID + " sensors mapped:" + s.toString());
177bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    }
178bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
179bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    private void printSensorAttribList() {
180bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        if (mThermalSensorsAttribMap == null) return;
181bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        Iterator it = (Iterator) mThermalSensorsAttribMap.keySet().iterator();
182bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        if (it == null) return;
183bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        ThermalSensorAttrib sensorAttrib = null;
184bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        while (it.hasNext()) {
185bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            sensorAttrib = mThermalSensorsAttribMap.get((String) it.next());
186bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            if (sensorAttrib != null) sensorAttrib.printAttrs();
187bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        }
188bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    }
189bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
190bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    public ThermalZone() {
191bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        mCurrThermalState = ThermalManager.THERMAL_STATE_OFF;
192bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        mZoneTemp = ThermalManager.INVALID_TEMP;
193bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    }
194bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
195bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    public static String getStateAsString(int index) {
196bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        if (index < -1 || index > 3)
197bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            return "Invalid";
198bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        return ThermalManager.STATE_NAMES[index + 1];
199bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    }
200bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
201bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    public static String getEventTypeAsString(int type) {
202bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        return type == 0 ? "LOW" : "HIGH";
203bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    }
204bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
205bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    public void setSensorList(ArrayList<ThermalSensorAttrib> sensorAtribList) {
206bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        if (sensorAtribList == null || ThermalManager.sSensorMap == null) return;
207bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        for (ThermalSensorAttrib sa : sensorAtribList) {
208bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            // since each object of sensor attrib list is already validated during
209bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            // parsing it is gauranteed that 'sa != null' and a valid sensor object 's'
210bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            // will be returned. Hence skipping null check..
211bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            if (mThermalSensors == null) {
212bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                // first time allocation
213bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                mThermalSensors = new ArrayList<ThermalSensor>();
214bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                if (mThermalSensors == null) {
215bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                    // allocation failure. return
216bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                    return;
217bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                }
218bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            }
219bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            if (mThermalSensorsAttribMap == null) {
220bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                // first time allocation
221bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                mThermalSensorsAttribMap = new Hashtable<String, ThermalSensorAttrib>();
222bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                if (mThermalSensorsAttribMap == null) return;
223bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            }
224bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            mThermalSensors.add(ThermalManager.getSensor(sa.getSensorName()));
225bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            mThermalSensorsAttribMap.put(sa.getSensorName(), sa);
226bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        }
227bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    }
228bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
229bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    public ArrayList<ThermalSensor> getThermalSensorList() {
230bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        return mThermalSensors;
231bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    }
232bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
233bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    public int getZoneState() {
234bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        return mCurrThermalState;
235bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    }
236bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
237bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    public void setZoneState(int state) {
238bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        mCurrThermalState = state;
239bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    }
240bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
241bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    public int getEventType() {
242bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        return mCurrEventType;
243bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    }
244bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
245bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    public void setEventType(int type) {
246bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        mCurrEventType = type;
247bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    }
248bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
249bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    public void setZoneTemp(int temp) {
250bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        mZoneTemp = temp;
251bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    }
252bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
253bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    public int getZoneTemp() {
254bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        return mZoneTemp;
255bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    }
256bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
257bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    public void setZoneId(int id) {
258bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        mZoneID = id;
259bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    }
260bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
261bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    public int getZoneId() {
262bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        return mZoneID;
263bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    }
264bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
265bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    public void setZoneName(String name) {
266bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        mZoneName = name;
267bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    }
268bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
269bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    public String getZoneName() {
270bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        return mZoneName;
271bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    }
272bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
273bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    public void setSupportsUEvent(int flag) {
274bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        mSupportsUEvent = (flag == 1);
275bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    }
276bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
277bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    public boolean isUEventSupported() {
278bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        return mSupportsUEvent;
279bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    }
280bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
281bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    public boolean isMaxThreshExceed() {
282bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        return mMaxThreshExceeded;
283bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    }
284bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
285bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    public void setZoneLogic(String type) {
286bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        mZoneLogic = type;
287bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    }
288bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
289bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    public String getZoneLogic() {
290bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        return mZoneLogic;
291bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    }
292bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
293bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    public void setDBInterval(int interval) {
294bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        mDebounceInterval = interval;
295bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    }
296bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
297bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    public int getDBInterval() {
298bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        return mDebounceInterval;
299bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    }
300bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
301bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    public int getOffset() {
302bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        return mOffset;
303bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    }
304bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
305bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    public void setOffset(int offset) {
306bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        mOffset  = offset;
307bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    }
308bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
309bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    public void setPollDelay(ArrayList<Integer> delayList) {
310bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        if (delayList != null) {
311bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            mPollDelay = new Integer[delayList.size()];
312bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            if (mPollDelay != null) {
313bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                mPollDelay = delayList.toArray(mPollDelay);
314bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            }
315bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        }
316bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    }
317bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
318bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    public Integer[] getPollDelay() {
319bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        return mPollDelay;
320bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    }
321bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
322bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    /**
323bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan     * In polldelay array, index of TOFF = 0, Normal = 1, Warning = 2, Alert =
324bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan     * 3, Critical = 4. Whereas a ThermalZone states are enumerated as TOFF =
325bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan     * -1, Normal = 0, Warning = 1, Alert = 2, Critical = 3. Hence we add 1
326bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan     * while querying poll delay
327bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan     */
328bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    public int getPollDelay(int index) {
329bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        index++;
330bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
331bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        // If poll delay is requested for an invalid state, return the delay
332bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        // corresponding to normal state
333bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        if (index < 0 || index >= mPollDelay.length)
334bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            index = 1;
335bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
336bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        return mPollDelay[index];
337bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    }
338bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
339bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    public void setZoneTempThreshold(ArrayList<Integer> thresholdList) {
340bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        if (mZoneName.contains("CPU") || mZoneName.contains("SoC"))
341bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            mTripMax = ThermalManager.sTjMaxTemp;
342bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        else
343bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            mTripMax = ThermalManager.sMaxSkinTrip;
344bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
345bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        if (thresholdList != null ) {
346bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            // In Uevent mode, if any threshold specified for a particular
347bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            // zone exceeds the max threshold temp, we de-activate that zone.
348bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            if (mSupportsUEvent) {
349bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                for (int i = 0; i < thresholdList.size(); i++) {
350bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                    if (thresholdList.get(i) <= mTripMax)
351bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                        continue;
352bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                    else
353bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                        mMaxThreshExceeded = true;
354bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                }
355bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            }
356bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            if (mMaxThreshExceeded == false) {
357bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                mZoneTempThresholds = new Integer[thresholdList.size()];
358bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                mZoneTempThresholdsRaw = new Integer[thresholdList.size()];
359bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                if (mZoneTempThresholds != null) {
360bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                    mZoneTempThresholds = thresholdList.toArray(mZoneTempThresholds);
361bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                }
362bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                if (mZoneTempThresholdsRaw != null) {
363bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                    mZoneTempThresholdsRaw = thresholdList.toArray(mZoneTempThresholdsRaw);
364bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                }
365bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            }
366bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        }
367bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    }
368bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
369bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    public int getZoneTempThreshold(int index) {
370bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        if (index < 0 || index >= mZoneTempThresholds.length)
371bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            return -1;
372bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        return mZoneTempThresholds[index];
373bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    }
374bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
375bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    public Integer[] getZoneTempThreshold() {
376bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        return mZoneTempThresholds;
377bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    }
378bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
379bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    public boolean getZoneActiveStatus() {
380bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        return mIsZoneActive;
381bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    }
382bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
383bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    public void computeZoneActiveStatus() {
384bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        // init again. needed because of a profile change
385bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        mIsZoneActive = false;
386bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        if (mSupportsUEvent) {
387bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            // Zone de-activated when any threshold for that zone is
388bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            // above the allowed Max threshold.
389bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            if (mMaxThreshExceeded == true) {
390bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                Log.i(TAG, "deactivate zone:" + mZoneName +
391bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                        ". Zone Threshold exceeds max trip temp:" + mTripMax);
392bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                mIsZoneActive = false;
393bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                return;
394bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            }
395bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        }
396bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        if (mZoneTempThresholds == null) {
397bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            Log.i(TAG, "deactivate zone:" + getZoneName() + " threshold list is NULL! ");
398bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            mIsZoneActive = false;
399bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            return;
400bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        }
401bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        // 1. minimum number of states supported must be DEFAULT NUM STATES
402bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        // 2. if sensor list null disable zone
403bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        if (mMaxStates < ThermalManager.DEFAULT_NUM_ZONE_STATES) {
404bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            // substract by 1 since TOFF is transparent to USER
405bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            int minStateSupport = ThermalManager.DEFAULT_NUM_ZONE_STATES - 1;
406bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            Log.i(TAG, "deactivate zone:" + getZoneName() + " supports < "
407bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                    + minStateSupport + " states");
408bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            mIsZoneActive = false;
409bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            return;
410bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        }
411bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        if (mThermalSensors == null) {
412bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            Log.i(TAG, "deactivate zone:" + getZoneName() + " sensor list null! ");
413bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            mIsZoneActive = false;
414bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            return;
415bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        }
416bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
417bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        if (mSupportsUEvent) {
418bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            // if uevent just check the first sensor
419bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            ThermalSensor s = mThermalSensors.get(0);
420bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            if (s != null && s.getSensorActiveStatus()) {
421bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                mIsZoneActive = true;
422bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                return;
423bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            }
424bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        } else {
425bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            if (mPollDelay == null) {
426bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                Log.i(TAG, "deactivate zone:" + getZoneName()
427bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                        + " polldelay list null in poll mode! ");
428bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                mIsZoneActive = false;
429bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                return;
430bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            }
431bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            if (mZoneTempThresholds.length != mPollDelay.length) {
432bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                Log.i(TAG, "deactivate zone:" + getZoneName()
433bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                        + " mismatch of polldelay and threshold list in polling mode!");
434bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                mIsZoneActive = false;
435bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                return;
436bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            }
437bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            for (ThermalSensor ts : mThermalSensors) {
438bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                if (ts != null && ts.getSensorActiveStatus()) {
439bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                    mIsZoneActive = true;
440bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                    return;
441bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                }
442bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            }
443bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        }
444bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    }
445bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
446bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    public void setEmulTempFlag(int flag) {
447bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        mSupportsEmulTemp = (flag == 1);
448bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    }
449bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
450bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    public boolean getEmulTempFlag() {
451bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        return mSupportsEmulTemp;
452bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    }
453bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
454bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    // override in Specific zone class which inherit ThermalZone
455bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    public void startMonitoring() {
456bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    }
457bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
458bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    // override in Specific zone class which inherit ThermalZone
459bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    public void stopMonitoring() {
460bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    }
461bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
462bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    // override in ModemZone to unregister Modem specific intents
463bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    // override in VirtualThermalZone to stop UEvent observers
464bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    public void unregisterReceiver() {
465bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        if (isUEventSupported()) {
466bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            mUEventObserver.stopObserving();
467bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        }
468bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    }
469bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
470bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    // override in VirtualThermalZone class
471bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    public void startEmulTempObserver() {
472bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    }
473bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
474bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    // override in VirtualThermalZone class
475bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    public void calibrateThresholds() {
476bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    }
477bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
478bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    /**
479bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan     * Function that calculates the state of the Thermal Zone after reading
480bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan     * temperatures of all sensors in the zone. This function is used when a
481bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan     * zone operates in polling mode.
482bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan     */
483bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    public boolean isZoneStateChanged() {
484c9dcd35c3100acf9ab3d8d679c12abcf021a33d4Shravan        for (int i = 0; i < mThermalSensors.size(); i++) {
485c9dcd35c3100acf9ab3d8d679c12abcf021a33d4Shravan            if (mThermalSensors.get(i).getSensorActiveStatus()) {
486c9dcd35c3100acf9ab3d8d679c12abcf021a33d4Shravan                mThermalSensors.get(i).updateSensorTemp();
487bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            }
488bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        }
489bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        return updateZoneParams();
490bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    }
491bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
492bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    /**
493bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan     * Function that calculates the state of the Thermal Zone after reading
494bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan     * temperatures of all sensors in the zone. This is an overloaded function
495bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan     * used when a zone supports UEvent notifications from kernel. When a
496bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan     * sensor sends an UEvent, it also sends its current temperature as a
497bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan     * parameter of the UEvent.
498bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan     */
499bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    public boolean isZoneStateChanged(ThermalSensor s, int temp) {
500bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        if (s == null) return false;
501bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        s.setCurrTemp(temp);
502bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        setZoneTemp(temp);
503bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        return updateZoneParams();
504bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    }
505bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
506bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    /**
507bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan     * Method to update Zone Temperature and Zone Thermal State
508bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan     */
509bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    public boolean updateZoneParams() {
510bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        int newZoneState;
511bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        int prevZoneState = mCurrThermalState;
512bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
513bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        if (!updateZoneTemp()) {
514bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            return false;
515bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        }
516bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
517bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        newZoneState = ThermalUtils.calculateThermalState(mZoneTemp, mZoneTempThresholds);
518bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        if (newZoneState == prevZoneState) {
519bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            return false;
520bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        }
521bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
522bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        if (newZoneState == ThermalManager.THERMAL_STATE_OFF) {
523bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            setZoneState(newZoneState);
524bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            return true;
525bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        }
526bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
527bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        int threshold = ThermalUtils.getLowerThresholdTemp(prevZoneState, mZoneTempThresholds);
528bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        // For Interrupt based zones, HW (should) takes care of the debounce.
529bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        if (!isUEventSupported()) {
530bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            if (newZoneState < prevZoneState && getZoneTemp() > (threshold - getDBInterval())) {
531bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                Log.i(TAG, " THERMAL_LOW_EVENT for zone:" + getZoneName()
532bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                        + " rejected due to debounce interval");
533bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                return false;
534bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            }
535bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        }
536bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
537bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        setZoneState(newZoneState);
538bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        setEventType(newZoneState > prevZoneState
539bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                ? ThermalManager.THERMAL_HIGH_EVENT
540bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                : ThermalManager.THERMAL_LOW_EVENT);
541bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        return true;
542bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    }
543bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
544bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    public boolean updateZoneTemp() {
545bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        return false;
546bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    }
547bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
548bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    public void registerUevent() {
549bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        int indx;
550bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
551bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        if (mThermalSensors == null) return;
552bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        if (mThermalSensors.size() > 1) {
553bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            Log.i(TAG, "for zone:" + getZoneName() + " in uevent mode only first sensor used!");
554bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        }
555bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        ThermalSensor sensor = mThermalSensors.get(0);
556bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        if (sensor == null) return;
557bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        String path = sensor.getUEventDevPath();
558bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        if (path.equalsIgnoreCase("invalid")) return;
559bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        // first time update of sensor temp and zone temp
560bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        sensor.updateSensorTemp();
561bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        setZoneTemp(sensor.getCurrTemp());
562bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        if (updateZoneParams()) {
563bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            // first intent after initialization
564bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            sendThermalEvent();
565bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        }
566bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        mUEventObserver.startObserving(path);
567bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        programThresholds(sensor);
568bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    }
569bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
570bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    public UEventObserver mUEventObserver = new UEventObserver() {
571bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        @Override
572bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        public void onUEvent(UEventObserver.UEvent event) {
573bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            String sensorName;
574bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            int sensorTemp, errorVal, eventType = -1;
575bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            ThermalZone zone;
576bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            if (mThermalSensors ==  null) return;
577bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
578bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            // Name of the sensor and current temperature are mandatory parameters of an UEvent
579bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            sensorName = event.get("NAME");
580bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            sensorTemp = Integer.parseInt(event.get("TEMP"));
581bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
582bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            // eventType is an optional parameter. so, check for null case
583bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            if (event.get("EVENT") != null)
584bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                eventType = Integer.parseInt(event.get("EVENT"));
585bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
586bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            if (sensorName != null) {
587bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                Log.i(TAG, "UEvent received for sensor:" + sensorName + " temp:" + sensorTemp);
588bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                // check the name against the first sensor
589bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                ThermalSensor sensor = mThermalSensors.get(0);
590bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                if (sensor != null && sensor.getSensorName() != null
591bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                        && sensor.getSensorName().equalsIgnoreCase(sensorName)) {
592bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                    // Adjust the sensor temperature based on the 'error correction' temperature.
593bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                    // For 'LOW' event, debounce interval will take care of this.
594bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                    errorVal = sensor.getErrorCorrectionTemp();
595bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                    if (eventType == ThermalManager.THERMAL_HIGH_EVENT)
596bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                        sensorTemp += errorVal;
597bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
598bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                    if (isZoneStateChanged(sensor, sensorTemp)) {
599bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                        sendThermalEvent();
600bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                        // reprogram threshold
601bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                        programThresholds(sensor);
602bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                    }
603bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                }
604bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            }
605bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        }
606bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    };
607bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
608bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    public void programThresholds(ThermalSensor s) {
609bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        if (s == null) return;
610bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        int zoneState = getZoneState();
611bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        if (zoneState == ThermalManager.THERMAL_STATE_OFF) return;
612bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        int lowerTripPoint = ThermalUtils.getLowerThresholdTemp(zoneState, getZoneTempThreshold());
613bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        int upperTripPoint = ThermalUtils.getUpperThresholdTemp(zoneState, getZoneTempThreshold());
614bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        if (lowerTripPoint != ThermalManager.INVALID_TEMP
615bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                && upperTripPoint != ThermalManager.INVALID_TEMP) {
616bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            if (ThermalUtils.writeSysfs(s.getSensorLowTempPath(), lowerTripPoint) == -1) {
617bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                Log.i(TAG, "error while programming lower trip point:" + lowerTripPoint
618bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                        + "for sensor:" + s.getSensorName());
619bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            }
620bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            if (ThermalUtils.writeSysfs(s.getSensorHighTempPath(), upperTripPoint) == -1) {
621bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                Log.i(TAG, "error while programming upper trip point:" + upperTripPoint
622bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                        + "for sensor:" + s.getSensorName());
623bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan            }
624bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        }
625bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    }
626bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan
627bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    public void sendThermalEvent() {
628bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        ThermalEvent event = new ThermalEvent(mZoneID, mCurrEventType,
629bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                mCurrThermalState, mZoneTemp, mZoneName,
630bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan                ThermalManager.getCurProfileName());
631bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan        ThermalManager.addThermalEvent(event);
632bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan    }
633bc0b49155603ba1c0c1fc86d13127d04021e7c70shravan}
634