• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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