Home | History | Annotate | Download | only in thermal
      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 
    273         public ZoneCoolerBindingInfo() {
    274             mZoneToCoolDevBucketSize = new ArrayList<Integer>();
    275             mCoolDevToThrottBucketSize = new ArrayList<Integer>();
    276         }
    277 
    278         public int getLastState() {
    279             // mMaxStates = k + 1(for critical) + 1(for TOFF)
    280             return mMaxStates - 2;
    281         }
    282 
    283         public void setMaxStates(int state) {
    284             mMaxStates = state;
    285         }
    286 
    287         public int getMaxStates() {
    288             return mMaxStates;
    289         }
    290 
    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 
    300         public int getZoneToCoolDevBucketSizeIndex(int index) {
    301             if (mZoneToCoolDevBucketSize.size() > index)
    302                 return mZoneToCoolDevBucketSize.get(index);
    303 
    304             return 1;
    305         }
    306 
    307         public int getCoolDevToThrottBucketSizeIndex(int index) {
    308             if (mZoneToCoolDevBucketSize.size() > index)
    309                 return mCoolDevToThrottBucketSize.get(index);
    310 
    311             return 1;
    312         }
    313 
    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 
    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 
    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 
    364             public CoolingDeviceInfo() {
    365             }
    366 
    367             public int getMaxThrottleStates() {
    368                 return mMaxThrottleStates;
    369             }
    370 
    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 
    402             public int getCoolingDeviceId() {
    403                 return mCDeviceID;
    404             }
    405 
    406             public void setCoolingDeviceId(int deviceID) {
    407                 mCDeviceID = deviceID;
    408             }
    409 
    410             public int getCoolingDeviceStates() {
    411                 return mCoolingDeviceStates;
    412             }
    413 
    414             public void setCoolingDeviceStates(int num) {
    415                 mCoolingDeviceStates = num;
    416             }
    417 
    418             public ArrayList<Integer> getThrottleMaskList() {
    419                 return mDeviceThrottleMask;
    420             }
    421 
    422             public ArrayList<Integer> getDeThrottleMaskList() {
    423                 return mDeviceDethrottleMask;
    424             }
    425 
    426             public void setThrottleMaskList(ArrayList<Integer> list) {
    427                 this.mDeviceThrottleMask = list;
    428             }
    429 
    430             public void setDeThrottleMaskList(ArrayList<Integer> list) {
    431                 this.mDeviceDethrottleMask = list;
    432             }
    433 
    434         }
    435 
    436         public ArrayList<CoolingDeviceInfo> getCoolingDeviceInfoList() {
    437             return mCoolingDeviceInfoList;
    438         }
    439 
    440         public void createNewCoolingDeviceInstance() {
    441             lastCoolingDevInfoInstance = new CoolingDeviceInfo();
    442         }
    443 
    444         public CoolingDeviceInfo getLastCoolingDeviceInstance() {
    445             return lastCoolingDevInfoInstance;
    446         }
    447 
    448         public void setZoneID(int zoneID) {
    449             mZoneID = zoneID;
    450         }
    451 
    452         public int getZoneID() {
    453             return mZoneID;
    454         }
    455 
    456         public void setCriticalActionShutdown(int val) {
    457             mIsCriticalActionShutdown = val;
    458         }
    459 
    460         public int getCriticalActionShutdown() {
    461             return mIsCriticalActionShutdown;
    462         }
    463 
    464         public void setCoolingDeviceInfoList(ArrayList<CoolingDeviceInfo> devinfoList) {
    465             mCoolingDeviceInfoList = devinfoList;
    466         }
    467 
    468         public void initializeCoolingDeviceInfoList() {
    469             mCoolingDeviceInfoList = new ArrayList<CoolingDeviceInfo>();
    470         }
    471 
    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 
    481        public int getMaxThermalStates() {
    482             return mMaxThermalStates;
    483        }
    484 
    485        public void printAttrs() {
    486            Log.i(TAG, Integer.toString(mMaxThermalStates));
    487        }
    488        public PlatformInfo() {}
    489     }
    490 
    491     /* methods */
    492     public ThermalManager() {
    493         // empty constructor
    494     }
    495 
    496     public static void setContext(Context context) {
    497         sContext = context;
    498     }
    499 
    500     public static String getVersion() {
    501         return sVersion;
    502     }
    503 
    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 
    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 
    521     public static void setCurBindMap(String profName) {
    522         synchronized (sProfileSwitchLock) {
    523             sZoneCoolerBindMap = sProfileBindMap.get(profName);
    524         }
    525     }
    526 
    527     public static Hashtable<Integer, ZoneCoolerBindingInfo> getCurBindMap() {
    528         synchronized (sProfileSwitchLock) {
    529             return sZoneCoolerBindMap;
    530         }
    531     }
    532 
    533     public static Hashtable<Integer, ZoneCoolerBindingInfo> getBindMap(String profName) {
    534         return sProfileBindMap.get(profName);
    535     }
    536 
    537     private static void setCurProfileName(String profName) {
    538         sCurProfileName = profName;
    539     }
    540 
    541     public static String getCurProfileName() {
    542         return sCurProfileName;
    543     }
    544 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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      **/
    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 
    734     public static boolean checkShutdownCondition() {
    735         synchronized (sCriticalPendingLock) {
    736            return sCriticalZonesCount > 0;
    737         }
    738     }
    739 
    740     public static ThermalSensor getSensor(String sensorName) {
    741         if (sensorName == null || sSensorMap == null) return null;
    742         return sSensorMap.get(sensorName);
    743     }
    744 
    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 
    767     public static void initializeStickyIntent() {
    768         sQueryProfileIntent = new Intent();
    769         sQueryProfileIntent.setAction(ACTION_QUERY_THERMAL_PROFILE);
    770     }
    771 
    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 
    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