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