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.content.Context;
20 import android.content.Intent;
21 import android.os.SystemProperties;
22 import android.os.UserHandle;
23 import android.util.Log;
24 
25 import java.io.File;
26 import java.io.IOException;
27 import java.lang.NumberFormatException;
28 import java.lang.StringBuilder;
29 import java.util.ArrayList;
30 import java.util.concurrent.ArrayBlockingQueue;
31 import java.util.concurrent.BlockingQueue;
32 import java.util.Enumeration;
33 import java.util.Hashtable;
34 import java.util.Iterator;
35 import java.util.Map;
36 import java.util.NoSuchElementException;
37 /**
38  * The ThermalManager class contains data structures that are common to both
39  * Thermal Sensor/Zone and Cooling device parts.
40  *
41  * @hide
42  */
43 public class ThermalManager {
44     private static final String TAG = "ThermalManager";
45     private static Context sContext;
46     private static String sVersion;
47     private static String sCurProfileName;
48     private static String sProfileNameList;
49     private static int sProfileCount;
50     private static final String ITUX_VERSION_PROPERTY = "ro.thermal.ituxversion";
51     /* Parameter needed for reading configuration files */
52     public static final String SENSOR_FILE_NAME = "thermal_sensor_config.xml";
53     public static final String THROTTLE_FILE_NAME = "thermal_throttle_config.xml";
54     public static final String DEFAULT_DIR_PATH = "/system/etc/";
55     public static final String DEBUG_DIR_PATH = "/data/";
56     public static String sSensorFilePath;
57     public static String sThrottleFilePath;
58     /* *XmlId's are assigned if config files are choosen from overlays */
59     public static int sSensorFileXmlId = -1;
60     public static int sThrottleFileXmlId = -1;
61     /* Set to true if config are available in DEFAULT or DEBUG path */
62     public static boolean sIsConfigFiles = false;
63     /* Whether we are using the config files from overlays directory or from /etc/ */
64     public static boolean sIsOverlays = false;
65     /* Parameters required for MaxTrip data */
66     public static final String TJMAX_PATH = "/sys/devices/platform/coretemp.0/temp2_crit";
67     public static final int sDefaultTjMax = 90000;
68     public static int sTjMaxTemp;
69     public static final int sMaxSkinTrip = 150000;
70 
71     public static String sUEventDevPath = "DEVPATH=/devices/virtual/thermal/thermal_zone";
72     /**
73      * Thermal Zone State Changed Action: This is broadcast when the state of a
74      * thermal zone changes.
75      */
76     public static final String ACTION_THERMAL_ZONE_STATE_CHANGED =
77             "com.intel.thermal.action.THERMAL_ZONE_STATE_CHANGED";
78 
79     public static PlatformInfo sPlatformInfo;
80     public static ThermalCooling sCoolingManager;
81     /* List of Thermal zones for current profile. Access protected by 'sProfileSwitchLock' */
82     private static ArrayList<ThermalZone> sThermalZonesList;
83 
84     /* Hashtable of (ProfileName and ListOfZonesUnderThisProfile) */
85     public static Hashtable<String, ArrayList<ThermalZone>> sProfileZoneMap =
86             new Hashtable<String, ArrayList<ThermalZone>>();
87 
88     /**
89      * This holds the map for the current profile. Access protected by 'sProfileSwitchLock'.
90      * Should be initialized for every profile change.
91      */
92     private static Hashtable<Integer, ZoneCoolerBindingInfo> sZoneCoolerBindMap =
93             new Hashtable<Integer, ZoneCoolerBindingInfo>();
94 
95     /* Hashtable of (ProfileName and Hashtable(zoneID, ZoneCoolerBindingInfo) object */
96     public static Hashtable<String, Hashtable<Integer, ZoneCoolerBindingInfo>> sProfileBindMap =
97             new Hashtable<String, Hashtable<Integer, ZoneCoolerBindingInfo>>();
98 
99     /* Hashtable of (Cooling Device ID and ThermalCoolingDevice object) */
100     public static Hashtable<Integer, ThermalCoolingDevice> sCDevMap =
101             new Hashtable<Integer, ThermalCoolingDevice>();
102 
103     /* Hashtable of sensor name and sensor object */
104     public static Hashtable<String, ThermalSensor> sSensorMap =
105             new Hashtable<String, ThermalSensor>();
106 
107     public static final int CRITICAL_TRUE = 1;
108     public static final int CRITICAL_FALSE = 0;
109     /* sZoneCriticalPendingMap stores info whether a zone is in critical state and platform
110      * shutdown has not yet occured due to some scenario like ongoing emergency call
111      **/
112     public static Hashtable<Integer, Integer> sZoneCriticalPendingMap = null;
113     /* this lock is to access sZoneCriticalPendingMap synchronously */
114     private static final Object sCriticalPendingLock = new Object();
115     /* this count keeps track of number of zones in pending critical state.When
116      * sZoneCriticalPendingMap is updated, the count is either incremented or
117      * decremented depending on whether criical pending flag for a zone is true/
118      * false. By keeping a count we can avoid scanning through the entire map to
119      * see if there is a pending critical shutdown
120      **/
121     private static int sCriticalZonesCount = 0;
122 
123     /* Blocking queue to hold thermal events from thermal zones */
124     private static final int EVENT_QUEUE_SIZE = 10;
125 
126     public static BlockingQueue<ThermalEvent> sEventQueue = new ArrayBlockingQueue<ThermalEvent>(EVENT_QUEUE_SIZE);
127     /* this lock is to handle uevent callbacks synchronously */
128     private static final Object sLock = new Object();
129 
130     /**
131      * Extra for {@link ACTION_THERMAL_ZONE_STATE_CHANGED}:
132      * integer containing the thermal zone.
133      */
134     public static final String EXTRA_ZONE = "zone";
135 
136     /**
137      * Extra for {@link ACTION_THERMAL_ZONE_STATE_CHANGED}:
138      * integer containing the thermal state of the zone.
139      */
140     public static final String EXTRA_STATE = "state";
141 
142     /**
143      * Extra for {@link ACTION_THERMAL_ZONE_STATE_CHANGED}:
144      * integer containing the thermal event type for the zone.
145      */
146     public static final String EXTRA_EVENT = "event";
147 
148     /**
149      * Extra for {@link ACTION_THERMAL_ZONE_STATE_CHANGED}:
150      * integer containing the temperature of the zone.
151      */
152     public static final String EXTRA_TEMP = "temp";
153     public static final String ACTION_CHANGE_THERMAL_PROFILE =
154             "android.intent.action.CHANGE_THERMAL_PROFILE";
155     /**
156      * Extra for {@link ACTION_THERMAL_ZONE_STATE_CHANGED}:
157      * String containing the name of the zone.
158      */
159     public static final String EXTRA_NAME = "name";
160     public static final String EXTRA_PROFILE = "Profile";
161 
162     private static Intent sQueryProfileIntent;
163     public static final String ACTION_QUERY_THERMAL_PROFILE =
164             "com.intel.thermal.action.QUERY_THERMAL_PROFILE";
165     public static final String ACTION_KILL = "kill";
166 
167     /**
168      * Integer containing the number of thermal profiles.
169      */
170     public static final String EXTRA_NUM_PROFILE = "NumProfiles";
171     /**
172      * Space separated string containing list of thermal profile names.
173      */
174     public static final String EXTRA_PROFILE_LIST = "ProfileList";
175     /**
176      * String containing current thermal profile name.
177      */
178     public static final String EXTRA_CUR_PROFILE = "CurProfile";
179 
180     /* values for "STATE" field in the THERMAL_STATE_CHANGED Intent */
181     public static final int THERMAL_STATE_OFF = -1;
182 
183     public static final int THERMAL_STATE_NORMAL = 0;
184 
185     public static final int THERMAL_STATE_WARNING = 1;
186 
187     public static final int THERMAL_STATE_ALERT = 2;
188 
189     public static final int THERMAL_STATE_CRITICAL = 3;
190 
191     public static final int DEFAULT_NUM_THROTTLE_VALUES = 4;
192 
193     // 5 including TOFF and TCRITICAL
194     public static final int DEFAULT_NUM_ZONE_STATES = 5;
195 
196     public static final String STATE_NAMES[] = {
197             "OFF", "NORMAL", "WARNING", "ALERT", "CRITICAL"
198     };
199 
200     /* values of the "EVENT" field in the THERMAL_STATE_CHANGED intent */
201     /* Indicates type of event */
202     public static final int THERMAL_LOW_EVENT = 0;
203 
204     public static final int THERMAL_HIGH_EVENT = 1;
205 
206     public static final int THERMAL_EMUL_TEMP_EVENT = 2;
207 
208     public static final int INVALID_TEMP = 0xDEADBEEF;
209 
210     /* Absolute zero in millidegree C */
211     public static final int ABS_ZERO = -273000;
212 
213     /* base sysfs path for sensors */
214     public static final String sSysfsSensorBasePath = "/sys/class/thermal/thermal_zone";
215 
216     public static final String sSysfsSensorHighTempPath = "trip_point_1_temp";
217 
218     public static final String sSysfsSensorLowTempPath = "trip_point_0_temp";
219 
220     public static final String sCoolingDeviceBasePath = "/sys/class/thermal/cooling_device";
221 
222     public static final String sCoolingDeviceState = "/cur_state";
223 
224     public static final int THROTTLE_MASK_ENABLE = 1;
225 
226     public static final int DETHROTTLE_MASK_ENABLE = 1;
227 
228     /**
229      * Magic number (agreed upon between the Thermal driver and the Thermal Service)
230      * symbolising Dynamic Turbo OFF
231      */
232     public static final int DISABLE_DYNAMIC_TURBO = 0xB0FF;
233 
234     public static boolean sIsDynamicTurboEnabled = false;
235 
236     /* thermal notifier system properties for shutdown action */
237     public static boolean sShutdownTone = false;
238 
239     public static boolean sShutdownToast = false;
240 
241     public static boolean sShutdownVibra = false;
242 
243     /* Name of default Thermal Profile */
244     public static final String DEFAULT_PROFILE_NAME = "Default";
245 
246     /* Lock protecting profile-switch */
247     private static final Object sProfileSwitchLock = new Object();
248 
249     /**
250      * This class stores the zone throttle info. It contains the zoneID,
251      * CriticalShutdown flag and CoolingDeviceInfo arraylist.
252      */
253     public static class ZoneCoolerBindingInfo {
254         private int mZoneID;
255         // max states includes TOFF also.
256         // if user provides k threshold values in XML.
257         // mMaxStates = k + 1(for critical) + 1(for TOFF)
258         // this is same as the max states stored in corresponding zone object
259         protected int mMaxStates;
260         private int mIsCriticalActionShutdown;
261 
262         /* cooler ID mask, 1 - throttle device, 0- no action, -1- dont care */
263         private ArrayList<CoolingDeviceInfo> mCoolingDeviceInfoList = null;
264 
265         // ManyToOneMapping: ZoneStates >= CoolingDeviceStates
266         private ArrayList<Integer> mZoneToCoolDevBucketSize = null;
267 
268         // OneToOneMapping: CoolingDeviceStates >= ThrottleValues
269         private ArrayList<Integer> mCoolDevToThrottBucketSize = null;
270 
271         private CoolingDeviceInfo lastCoolingDevInfoInstance = null;
272 
ZoneCoolerBindingInfo()273         public ZoneCoolerBindingInfo() {
274             mZoneToCoolDevBucketSize = new ArrayList<Integer>();
275             mCoolDevToThrottBucketSize = new ArrayList<Integer>();
276         }
277 
getLastState()278         public int getLastState() {
279             // mMaxStates = k + 1(for critical) + 1(for TOFF)
280             return mMaxStates - 2;
281         }
282 
setMaxStates(int state)283         public void setMaxStates(int state) {
284             mMaxStates = state;
285         }
286 
getMaxStates()287         public int getMaxStates() {
288             return mMaxStates;
289         }
290 
setZoneToCoolDevBucketSize()291         public void setZoneToCoolDevBucketSize() {
292             int size = 1;
293             int zoneStates = getMaxStates();
294             for (CoolingDeviceInfo coolDev : mCoolingDeviceInfoList) {
295                 size = (zoneStates - 1) / coolDev.getCoolingDeviceStates();
296                 mZoneToCoolDevBucketSize.add(size == 0 ? 1 : size);
297             }
298         }
299 
getZoneToCoolDevBucketSizeIndex(int index)300         public int getZoneToCoolDevBucketSizeIndex(int index) {
301             if (mZoneToCoolDevBucketSize.size() > index)
302                 return mZoneToCoolDevBucketSize.get(index);
303 
304             return 1;
305         }
306 
getCoolDevToThrottBucketSizeIndex(int index)307         public int getCoolDevToThrottBucketSizeIndex(int index) {
308             if (mZoneToCoolDevBucketSize.size() > index)
309                 return mCoolDevToThrottBucketSize.get(index);
310 
311             return 1;
312         }
313 
setCoolDevToThrottBucketSize()314         public void setCoolDevToThrottBucketSize() {
315             int size = 1;
316             for (CoolingDeviceInfo coolDev : mCoolingDeviceInfoList) {
317                 size = coolDev.getMaxThrottleStates() / coolDev.getCoolingDeviceStates();
318                 mCoolDevToThrottBucketSize.add(size == 0 ? 1 : size);
319             }
320         }
321 
printAttributes()322         public void printAttributes() {
323             if (mCoolingDeviceInfoList == null) return;
324             StringBuilder s = new StringBuilder();
325             for (CoolingDeviceInfo c : mCoolingDeviceInfoList) {
326                 if (c != null) {
327                     s.append(c.getCoolingDeviceId());
328                     s.append(",");
329                 }
330             }
331             Log.i(TAG, "zone id:" + mZoneID + " coolingDevID  mapped:" + s.toString());
332         }
333 
printMappedAttributes()334         public void printMappedAttributes() {
335             if (mZoneToCoolDevBucketSize == null || mCoolDevToThrottBucketSize == null) return;
336             StringBuilder s = new StringBuilder();
337             for (int bs : mZoneToCoolDevBucketSize) {
338                 s.append(bs);
339                 s.append(",");
340             }
341             Log.i(TAG, "zone id:" + mZoneID + " ZoneToCoolDevBucketSize:" + s.toString());
342             // clear the string
343             s.delete(0,s.length());
344             for (int bs : mCoolDevToThrottBucketSize) {
345                 s.append(bs);
346                 s.append(",");
347             }
348             Log.i(TAG, "zone id:" + mZoneID + " CoolDevToThrottBucketSize:" + s.toString());
349         }
350 
351         public class CoolingDeviceInfo {
352             private int mCDeviceID;
353 
354             // mCoolingDeviceState is number of device states exposed under a zone.
355             // this must be less than or equal to its total number of throttle values
356             private int mCoolingDeviceStates = DEFAULT_NUM_THROTTLE_VALUES;
357 
358             // store a copy here for fast lookup during throttling/dethrottling
359             private int mMaxThrottleStates = 0;
360             private ArrayList<Integer> mDeviceThrottleMask = null;
361 
362             private ArrayList<Integer> mDeviceDethrottleMask = null;
363 
CoolingDeviceInfo()364             public CoolingDeviceInfo() {
365             }
366 
getMaxThrottleStates()367             public int getMaxThrottleStates() {
368                 return mMaxThrottleStates;
369             }
370 
checkMaskList(int throttleStates)371             public boolean checkMaskList(int throttleStates) {
372                 boolean ret = true;
373                 // if the list is empty this mean, THROTTLE MASK and/or
374                 // DETHTOTTLE mask was not provided. Initialize default mask.
375                 if (mDeviceThrottleMask ==  null) {
376                     mDeviceThrottleMask = new ArrayList<Integer>();
377                     for (int i = 0; i < mCoolingDeviceStates; i++) {
378                         mDeviceThrottleMask.add(THROTTLE_MASK_ENABLE);
379                     }
380                 } else if (mDeviceThrottleMask.size() != mCoolingDeviceStates) {
381                     Log.i(TAG, "cdevid:" + mCDeviceID
382                             + " has mismatch in Cooling device state and mask array!deactivate!");
383                     ret = false;
384                 }
385 
386                 if (mDeviceDethrottleMask ==  null) {
387                     mDeviceDethrottleMask = new ArrayList<Integer>();
388                     for (int i = 0; i < mCoolingDeviceStates; i++) {
389                         mDeviceDethrottleMask.add(DETHROTTLE_MASK_ENABLE);
390                     }
391                 } else if (mDeviceDethrottleMask.size() != mCoolingDeviceStates) {
392                     Log.i(TAG, "cdevid:" + mCDeviceID
393                             + " has mismatch in Cooling device state and mask array!deactivate!");
394                     ret = false;
395                 }
396                 if (ret) {
397                     mMaxThrottleStates = throttleStates;
398                 }
399                 return ret;
400             }
401 
getCoolingDeviceId()402             public int getCoolingDeviceId() {
403                 return mCDeviceID;
404             }
405 
setCoolingDeviceId(int deviceID)406             public void setCoolingDeviceId(int deviceID) {
407                 mCDeviceID = deviceID;
408             }
409 
getCoolingDeviceStates()410             public int getCoolingDeviceStates() {
411                 return mCoolingDeviceStates;
412             }
413 
setCoolingDeviceStates(int num)414             public void setCoolingDeviceStates(int num) {
415                 mCoolingDeviceStates = num;
416             }
417 
getThrottleMaskList()418             public ArrayList<Integer> getThrottleMaskList() {
419                 return mDeviceThrottleMask;
420             }
421 
getDeThrottleMaskList()422             public ArrayList<Integer> getDeThrottleMaskList() {
423                 return mDeviceDethrottleMask;
424             }
425 
setThrottleMaskList(ArrayList<Integer> list)426             public void setThrottleMaskList(ArrayList<Integer> list) {
427                 this.mDeviceThrottleMask = list;
428             }
429 
setDeThrottleMaskList(ArrayList<Integer> list)430             public void setDeThrottleMaskList(ArrayList<Integer> list) {
431                 this.mDeviceDethrottleMask = list;
432             }
433 
434         }
435 
getCoolingDeviceInfoList()436         public ArrayList<CoolingDeviceInfo> getCoolingDeviceInfoList() {
437             return mCoolingDeviceInfoList;
438         }
439 
createNewCoolingDeviceInstance()440         public void createNewCoolingDeviceInstance() {
441             lastCoolingDevInfoInstance = new CoolingDeviceInfo();
442         }
443 
getLastCoolingDeviceInstance()444         public CoolingDeviceInfo getLastCoolingDeviceInstance() {
445             return lastCoolingDevInfoInstance;
446         }
447 
setZoneID(int zoneID)448         public void setZoneID(int zoneID) {
449             mZoneID = zoneID;
450         }
451 
getZoneID()452         public int getZoneID() {
453             return mZoneID;
454         }
455 
setCriticalActionShutdown(int val)456         public void setCriticalActionShutdown(int val) {
457             mIsCriticalActionShutdown = val;
458         }
459 
getCriticalActionShutdown()460         public int getCriticalActionShutdown() {
461             return mIsCriticalActionShutdown;
462         }
463 
setCoolingDeviceInfoList(ArrayList<CoolingDeviceInfo> devinfoList)464         public void setCoolingDeviceInfoList(ArrayList<CoolingDeviceInfo> devinfoList) {
465             mCoolingDeviceInfoList = devinfoList;
466         }
467 
initializeCoolingDeviceInfoList()468         public void initializeCoolingDeviceInfoList() {
469             mCoolingDeviceInfoList = new ArrayList<CoolingDeviceInfo>();
470         }
471 
addCoolingDeviceToList(CoolingDeviceInfo CdeviceInfo)472         public void addCoolingDeviceToList(CoolingDeviceInfo CdeviceInfo) {
473             mCoolingDeviceInfoList.add(CdeviceInfo);
474         }
475     }
476 
477     /* platform information */
478     public static class PlatformInfo {
479        public int mMaxThermalStates;
480 
getMaxThermalStates()481        public int getMaxThermalStates() {
482             return mMaxThermalStates;
483        }
484 
printAttrs()485        public void printAttrs() {
486            Log.i(TAG, Integer.toString(mMaxThermalStates));
487        }
PlatformInfo()488        public PlatformInfo() {}
489     }
490 
491     /* methods */
ThermalManager()492     public ThermalManager() {
493         // empty constructor
494     }
495 
setContext(Context context)496     public static void setContext(Context context) {
497         sContext = context;
498     }
499 
getVersion()500     public static String getVersion() {
501         return sVersion;
502     }
503 
loadiTUXVersion()504     public static void loadiTUXVersion() {
505         sVersion = SystemProperties.get(ITUX_VERSION_PROPERTY, "none");
506         if (sVersion.equalsIgnoreCase("none")) {
507             Log.i(TAG, "iTUX Version not found!");
508         } else {
509             Log.i(TAG, "iTUX Version:" + sVersion);
510         }
511     }
512 
addThermalEvent(ThermalEvent event)513     public static void addThermalEvent(ThermalEvent event) {
514         try {
515             ThermalManager.sEventQueue.put(event);
516         } catch (InterruptedException ex) {
517             Log.i(TAG, "caught InterruptedException in posting to event queue");
518         }
519     }
520 
setCurBindMap(String profName)521     public static void setCurBindMap(String profName) {
522         synchronized (sProfileSwitchLock) {
523             sZoneCoolerBindMap = sProfileBindMap.get(profName);
524         }
525     }
526 
getCurBindMap()527     public static Hashtable<Integer, ZoneCoolerBindingInfo> getCurBindMap() {
528         synchronized (sProfileSwitchLock) {
529             return sZoneCoolerBindMap;
530         }
531     }
532 
getBindMap(String profName)533     public static Hashtable<Integer, ZoneCoolerBindingInfo> getBindMap(String profName) {
534         return sProfileBindMap.get(profName);
535     }
536 
setCurProfileName(String profName)537     private static void setCurProfileName(String profName) {
538         sCurProfileName = profName;
539     }
540 
getCurProfileName()541     public static String getCurProfileName() {
542         return sCurProfileName;
543     }
544 
isProfileExists(String profName)545     private static boolean isProfileExists(String profName) {
546         if (sProfileZoneMap.get(profName) == null || sProfileBindMap.get(profName) == null) {
547             return false;
548         }
549         return true;
550     }
551 
startNewProfile(String profName)552     private static void startNewProfile(String profName) {
553         sThermalZonesList = sProfileZoneMap.get(profName);
554         sZoneCoolerBindMap = sProfileBindMap.get(profName);
555         if (sThermalZonesList == null || sZoneCoolerBindMap == null) {
556             Log.i(TAG, "Couldn't shift to profile:" + profName);
557             return;
558         }
559         initializeZoneCriticalPendingMap();
560         setCurProfileName(profName);
561         int activeZones = startMonitoringZones();
562         Log.i(TAG, activeZones + " zones found active in profile " + profName);
563         // broadcast a sticky intent for the clients
564         sendQueryProfileIntent();
565     }
566 
stopCurrentProfile()567     public static void stopCurrentProfile() {
568         for (ThermalZone zone : sThermalZonesList) {
569             // Stop Polling threads
570             zone.stopMonitoring();
571             // Unregister UEvent/EmulTemp observers
572             zone.unregisterReceiver();
573             // Reset Parameters:
574             // Zone State: Normal, Event Type: LOW, Temperature: Normal Threshold
575             zone.setZoneState(0);
576             zone.setEventType(ThermalManager.THERMAL_LOW_EVENT);
577             zone.setZoneTemp(zone.getZoneTempThreshold(0));
578             // Send ThermalIntent with above parameters
579             // This will release all throttle controls this zone had.
580             // Since we are in the middle of a profile switch(stop),
581             // set the override parameter as true, so that this
582             // event is actually queued for processing.
583             // TODO: Find a way to take care of zones that are not
584             // present in thermal_sensor_config.xml but present in
585             // thermal_throttle_config.xml (usually from other components)
586             zone.sendThermalEvent();
587             // Reprogram the sensor thresholds if this zone supported interrupts
588             // TODO: We are reprogramming the calibrated thresholds in case the
589             // the sensor was using 'weights' and 'offset'. Hope this is fine.
590             if (zone.isUEventSupported()) {
591                 zone.programThresholds((zone.getThermalSensorList()).get(0));
592             }
593         }
594     }
595 
startDefaultProfile()596     public static void startDefaultProfile() {
597         if (isProfileExists(DEFAULT_PROFILE_NAME)) {
598             startNewProfile(DEFAULT_PROFILE_NAME);
599         }
600         // register for Thermal Profile Change Intent only after
601         // we have started the default profile
602         sCoolingManager.registerProfChangeListener();
603     }
604 
changeThermalProfile(String newProfName)605     public static void changeThermalProfile(String newProfName) {
606         synchronized (sProfileSwitchLock) {
607             if (newProfName.equalsIgnoreCase(sCurProfileName)) {
608                 Log.i(TAG, "New Profile same as current profile. Profile change request Ignored");
609                 return;
610             }
611             if (!isProfileExists(newProfName)) {
612                 Log.i(TAG, "New Profile does not exist in xml. Profile change request Ignored");
613                 return;
614             }
615             Log.i(TAG, "ACTION_CHANGE_THERMAL_PROFILE received. New Profile: " + newProfName);
616 
617             stopCurrentProfile();
618             startNewProfile(newProfName);
619         }
620     }
621 
setBucketSizeForProfiles()622     public static void setBucketSizeForProfiles() {
623         Iterator it = ThermalManager.sProfileZoneMap.entrySet().iterator();
624         while (it.hasNext()) {
625             Map.Entry entryProfZone = (Map.Entry) it.next();
626             String keyProfile = (String) entryProfZone.getKey();
627             sThermalZonesList = (ArrayList<ThermalZone>) entryProfZone.getValue();
628             setCurBindMap(keyProfile);
629             for (ThermalZone zone : sThermalZonesList) {
630                 if (sZoneCoolerBindMap == null) {
631                     Log.e(TAG, "ZoneCoolerBindMap null while setBucketSizeForProfiles");
632                     return;
633                 }
634                 ZoneCoolerBindingInfo bindInfo = sZoneCoolerBindMap.get(zone.getZoneId());
635                 if (bindInfo == null) {
636                     Log.e(TAG, "CoolerBindingInfo for zoneid:" + zone.getZoneId() + "not mapped");
637                     return;
638                 }
639                 bindInfo.setMaxStates(zone.getMaxStates());
640                 bindInfo.setZoneToCoolDevBucketSize();
641                 bindInfo.setCoolDevToThrottBucketSize();
642                 if (zone.isUEventSupported()) {
643                     // calibration of thresholds based on weight, order
644                     if (!zone.isMaxThreshExceed())
645                         zone.calibrateThresholds();
646                 }
647             }
648         }
649     }
650 
startMonitoringZones()651     public static int startMonitoringZones() {
652         int activeZonesCount = 0;
653         for (ThermalZone zone : sThermalZonesList) {
654             zone.computeZoneActiveStatus();
655             if (zone.getZoneActiveStatus() == false) {
656                 Log.i(TAG, "deactivating inactive zone:" + zone.getZoneName());
657                 continue;
658             }
659 
660             ZoneCoolerBindingInfo bindInfo = sZoneCoolerBindMap.get(zone.getZoneId());
661             if (bindInfo != null) {
662                 // TODO: To be conditioned under debug
663                 bindInfo.printMappedAttributes();
664             }
665             if (zone.isUEventSupported()) {
666                 zone.registerUevent();
667             } else {
668                 // start polling thread for each zone
669                 zone.startMonitoring();
670             }
671             zone.startEmulTempObserver();
672             activeZonesCount++;
673         }
674         return activeZonesCount;
675     }
676 
readShutdownNotiferProperties()677     public static void readShutdownNotiferProperties() {
678         try {
679             if ("1".equals(SystemProperties.get("persist.thermal.shutdown.msg", "0"))) {
680                 sShutdownToast = true;
681             }
682             if ("1".equals(SystemProperties.get("persist.thermal.shutdown.tone", "0"))) {
683                 sShutdownTone = true;
684             }
685             if ("1".equals(SystemProperties.get("persist.thermal.shutdown.vibra", "0"))) {
686                 sShutdownVibra = true;
687             }
688         } catch (java.lang.IllegalArgumentException e) {
689             Log.e(TAG, "exception caught in reading thermal system properties");
690         }
691     }
692 
initializeZoneCriticalPendingMap()693     private static void initializeZoneCriticalPendingMap() {
694         sZoneCriticalPendingMap = new Hashtable<Integer, Integer>();
695         if (sZoneCriticalPendingMap == null) return;
696         Enumeration en;
697         try {
698             // look up for zone list is performed from sZoneCoolerBindMap instead of
699             // sThermalZonesList since some non thermal zones may not have entry in
700             // sThermalZonesList. This is because such zones only have entry in throttle
701             // config file and not in sensor config files.
702             // 'sZoneCoolerBindMap' is protected by caller here.
703             en = sZoneCoolerBindMap.keys();
704             while (en.hasMoreElements()) {
705                 int zone = (Integer) en.nextElement();
706                 sZoneCriticalPendingMap.put(zone, CRITICAL_FALSE);
707             }
708         } catch (NoSuchElementException e) {
709             Log.i(TAG, "NoSuchElementException in InitializeZoneCriticalPendingMap()");
710         }
711     }
712 
713     /*
714      * updateZoneCriticalPendingMap updates sZoneCriticalPendingMap synchronously.
715      * sCriticalZonesCount is incremented iff old value in the map for the zone is
716      * FALSE (ensures count is incremented only once for a zone) and decremented
717      * iff oldval is TRUE (ensures no negative value for count)
718      **/
updateZoneCriticalPendingMap(int zoneid, int flag)719     public static boolean updateZoneCriticalPendingMap(int zoneid, int flag) {
720         synchronized (sCriticalPendingLock) {
721             if (sZoneCriticalPendingMap == null) return false;
722                 Integer oldVal = sZoneCriticalPendingMap.get(zoneid);
723                 if (oldVal == null) return false;
724                 sZoneCriticalPendingMap.put(zoneid, flag);
725                 if (oldVal == CRITICAL_FALSE && flag == CRITICAL_TRUE) {
726                    sCriticalZonesCount++;
727                 } else if (oldVal == CRITICAL_TRUE && flag == CRITICAL_FALSE) {
728                    sCriticalZonesCount--;
729                 }
730                 return true;
731         }
732     }
733 
checkShutdownCondition()734     public static boolean checkShutdownCondition() {
735         synchronized (sCriticalPendingLock) {
736            return sCriticalZonesCount > 0;
737         }
738     }
739 
getSensor(String sensorName)740     public static ThermalSensor getSensor(String sensorName) {
741         if (sensorName == null || sSensorMap == null) return null;
742         return sSensorMap.get(sensorName);
743     }
744 
buildProfileNameList()745     public static void buildProfileNameList() {
746         int count = 0;
747         StringBuilder s = new StringBuilder();
748         Iterator it = sProfileZoneMap.entrySet().iterator();
749         while (it.hasNext()) {
750             Map.Entry entry = (Map.Entry) it.next();
751             String key = (String) entry.getKey();
752             // create list of only valid profiles
753             if (isProfileExists(key)) {
754                 // build a space seperate list of string
755                 s.append(key);
756                 s.append(" ");
757                 count++;
758             }
759         }
760 
761         sProfileNameList = s.toString();
762         sProfileCount = count;
763         Log.i(TAG, "profile name list:" + sProfileNameList);
764         Log.i(TAG, "profile count:" + sProfileCount);
765     }
766 
initializeStickyIntent()767     public static void initializeStickyIntent() {
768         sQueryProfileIntent = new Intent();
769         sQueryProfileIntent.setAction(ACTION_QUERY_THERMAL_PROFILE);
770     }
771 
sendQueryProfileIntent()772     private static void sendQueryProfileIntent() {
773         if (sQueryProfileIntent != null && sContext != null) {
774             sQueryProfileIntent.putExtra(ThermalManager.EXTRA_NUM_PROFILE, sProfileCount);
775             sQueryProfileIntent.putExtra(ThermalManager.EXTRA_PROFILE_LIST, sProfileNameList);
776             sQueryProfileIntent.putExtra(ThermalManager.EXTRA_CUR_PROFILE, sCurProfileName);
777             sContext.sendStickyBroadcastAsUser(sQueryProfileIntent, UserHandle.ALL);
778         }
779     }
780 
clearData()781     public static void clearData() {
782         sThermalZonesList.clear();
783         // clearing hastables
784         sProfileZoneMap.clear();
785         sZoneCoolerBindMap.clear();
786         sProfileBindMap.clear();
787         sCDevMap.clear();
788         sSensorMap.clear();
789         sZoneCriticalPendingMap.clear();
790     }
791 }
792