blob: b68bd3d7d9fb8137a8ce961e28dec30af96ce9f0 [file] [log] [blame]
/*
* Copyright 2014 Intel Corporation All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intel.thermal;
import android.content.Context;
import android.content.Intent;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.util.Log;
import java.io.File;
import java.io.IOException;
import java.lang.NumberFormatException;
import java.lang.StringBuilder;
import java.util.ArrayList;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;
/**
* The ThermalManager class contains data structures that are common to both
* Thermal Sensor/Zone and Cooling device parts.
*
* @hide
*/
public class ThermalManager {
private static final String TAG = "ThermalManager";
private static Context sContext;
private static String sVersion;
private static String sCurProfileName;
private static String sProfileNameList;
private static int sProfileCount;
private static final String ITUX_VERSION_PROPERTY = "ro.thermal.ituxversion";
/* Parameter needed for reading configuration files */
public static final String SENSOR_FILE_NAME = "thermal_sensor_config.xml";
public static final String THROTTLE_FILE_NAME = "thermal_throttle_config.xml";
public static final String DEFAULT_DIR_PATH = "/system/etc/";
public static final String DEBUG_DIR_PATH = "/data/";
public static String sSensorFilePath;
public static String sThrottleFilePath;
/* *XmlId's are assigned if config files are choosen from overlays */
public static int sSensorFileXmlId = -1;
public static int sThrottleFileXmlId = -1;
/* Set to true if config are available in DEFAULT or DEBUG path */
public static boolean sIsConfigFiles = false;
/* Whether we are using the config files from overlays directory or from /etc/ */
public static boolean sIsOverlays = false;
/* Parameters required for MaxTrip data */
public static final String TJMAX_PATH = "/sys/devices/platform/coretemp.0/temp2_crit";
public static final int sDefaultTjMax = 90000;
public static int sTjMaxTemp;
public static final int sMaxSkinTrip = 150000;
public static String sUEventDevPath = "DEVPATH=/devices/virtual/thermal/thermal_zone";
/**
* Thermal Zone State Changed Action: This is broadcast when the state of a
* thermal zone changes.
*/
public static final String ACTION_THERMAL_ZONE_STATE_CHANGED =
"com.intel.thermal.action.THERMAL_ZONE_STATE_CHANGED";
public static PlatformInfo sPlatformInfo;
public static ThermalCooling sCoolingManager;
/* List of Thermal zones for current profile. Access protected by 'sProfileSwitchLock' */
private static ArrayList<ThermalZone> sThermalZonesList;
/* Hashtable of (ProfileName and ListOfZonesUnderThisProfile) */
public static Hashtable<String, ArrayList<ThermalZone>> sProfileZoneMap =
new Hashtable<String, ArrayList<ThermalZone>>();
/**
* This holds the map for the current profile. Access protected by 'sProfileSwitchLock'.
* Should be initialized for every profile change.
*/
private static Hashtable<Integer, ZoneCoolerBindingInfo> sZoneCoolerBindMap =
new Hashtable<Integer, ZoneCoolerBindingInfo>();
/* Hashtable of (ProfileName and Hashtable(zoneID, ZoneCoolerBindingInfo) object */
public static Hashtable<String, Hashtable<Integer, ZoneCoolerBindingInfo>> sProfileBindMap =
new Hashtable<String, Hashtable<Integer, ZoneCoolerBindingInfo>>();
/* Hashtable of (Cooling Device ID and ThermalCoolingDevice object) */
public static Hashtable<Integer, ThermalCoolingDevice> sCDevMap =
new Hashtable<Integer, ThermalCoolingDevice>();
/* Hashtable of sensor name and sensor object */
public static Hashtable<String, ThermalSensor> sSensorMap =
new Hashtable<String, ThermalSensor>();
public static final int CRITICAL_TRUE = 1;
public static final int CRITICAL_FALSE = 0;
/* sZoneCriticalPendingMap stores info whether a zone is in critical state and platform
* shutdown has not yet occured due to some scenario like ongoing emergency call
**/
public static Hashtable<Integer, Integer> sZoneCriticalPendingMap = null;
/* this lock is to access sZoneCriticalPendingMap synchronously */
private static final Object sCriticalPendingLock = new Object();
/* this count keeps track of number of zones in pending critical state.When
* sZoneCriticalPendingMap is updated, the count is either incremented or
* decremented depending on whether criical pending flag for a zone is true/
* false. By keeping a count we can avoid scanning through the entire map to
* see if there is a pending critical shutdown
**/
private static int sCriticalZonesCount = 0;
/* Blocking queue to hold thermal events from thermal zones */
private static final int EVENT_QUEUE_SIZE = 10;
public static BlockingQueue<ThermalEvent> sEventQueue = new ArrayBlockingQueue<ThermalEvent>(EVENT_QUEUE_SIZE);
/* this lock is to handle uevent callbacks synchronously */
private static final Object sLock = new Object();
/**
* Extra for {@link ACTION_THERMAL_ZONE_STATE_CHANGED}:
* integer containing the thermal zone.
*/
public static final String EXTRA_ZONE = "zone";
/**
* Extra for {@link ACTION_THERMAL_ZONE_STATE_CHANGED}:
* integer containing the thermal state of the zone.
*/
public static final String EXTRA_STATE = "state";
/**
* Extra for {@link ACTION_THERMAL_ZONE_STATE_CHANGED}:
* integer containing the thermal event type for the zone.
*/
public static final String EXTRA_EVENT = "event";
/**
* Extra for {@link ACTION_THERMAL_ZONE_STATE_CHANGED}:
* integer containing the temperature of the zone.
*/
public static final String EXTRA_TEMP = "temp";
public static final String ACTION_CHANGE_THERMAL_PROFILE =
"android.intent.action.CHANGE_THERMAL_PROFILE";
/**
* Extra for {@link ACTION_THERMAL_ZONE_STATE_CHANGED}:
* String containing the name of the zone.
*/
public static final String EXTRA_NAME = "name";
public static final String EXTRA_PROFILE = "Profile";
private static Intent sQueryProfileIntent;
public static final String ACTION_QUERY_THERMAL_PROFILE =
"com.intel.thermal.action.QUERY_THERMAL_PROFILE";
public static final String ACTION_KILL = "kill";
/**
* Integer containing the number of thermal profiles.
*/
public static final String EXTRA_NUM_PROFILE = "NumProfiles";
/**
* Space separated string containing list of thermal profile names.
*/
public static final String EXTRA_PROFILE_LIST = "ProfileList";
/**
* String containing current thermal profile name.
*/
public static final String EXTRA_CUR_PROFILE = "CurProfile";
/* values for "STATE" field in the THERMAL_STATE_CHANGED Intent */
public static final int THERMAL_STATE_OFF = -1;
public static final int THERMAL_STATE_NORMAL = 0;
public static final int THERMAL_STATE_WARNING = 1;
public static final int THERMAL_STATE_ALERT = 2;
public static final int THERMAL_STATE_CRITICAL = 3;
public static final int DEFAULT_NUM_THROTTLE_VALUES = 4;
// 5 including TOFF and TCRITICAL
public static final int DEFAULT_NUM_ZONE_STATES = 5;
public static final String STATE_NAMES[] = {
"OFF", "NORMAL", "WARNING", "ALERT", "CRITICAL"
};
/* values of the "EVENT" field in the THERMAL_STATE_CHANGED intent */
/* Indicates type of event */
public static final int THERMAL_LOW_EVENT = 0;
public static final int THERMAL_HIGH_EVENT = 1;
public static final int THERMAL_EMUL_TEMP_EVENT = 2;
public static final int INVALID_TEMP = 0xDEADBEEF;
/* base sysfs path for sensors */
public static final String sSysfsSensorBasePath = "/sys/class/thermal/thermal_zone";
public static final String sSysfsSensorHighTempPath = "trip_point_1_temp";
public static final String sSysfsSensorLowTempPath = "trip_point_0_temp";
public static final String sCoolingDeviceBasePath = "/sys/class/thermal/cooling_device";
public static final String sCoolingDeviceState = "/cur_state";
public static final int THROTTLE_MASK_ENABLE = 1;
public static final int DETHROTTLE_MASK_ENABLE = 1;
/**
* Magic number (agreed upon between the Thermal driver and the Thermal Service)
* symbolising Dynamic Turbo OFF
*/
public static final int DISABLE_DYNAMIC_TURBO = 0xB0FF;
public static boolean sIsDynamicTurboEnabled = false;
/* thermal notifier system properties for shutdown action */
public static boolean sShutdownTone = false;
public static boolean sShutdownToast = false;
public static boolean sShutdownVibra = false;
/* Name of default Thermal Profile */
public static final String DEFAULT_PROFILE_NAME = "Default";
/* Lock protecting profile-switch */
private static final Object sProfileSwitchLock = new Object();
/**
* This class stores the zone throttle info. It contains the zoneID,
* CriticalShutdown flag and CoolingDeviceInfo arraylist.
*/
public static class ZoneCoolerBindingInfo {
private int mZoneID;
// max states includes TOFF also.
// if user provides k threshold values in XML.
// mMaxStates = k + 1(for critical) + 1(for TOFF)
// this is same as the max states stored in corresponding zone object
protected int mMaxStates;
private int mIsCriticalActionShutdown;
/* cooler ID mask, 1 - throttle device, 0- no action, -1- dont care */
private ArrayList<CoolingDeviceInfo> mCoolingDeviceInfoList = null;
// ManyToOneMapping: ZoneStates >= CoolingDeviceStates
private ArrayList<Integer> mZoneToCoolDevBucketSize = null;
// OneToOneMapping: CoolingDeviceStates >= ThrottleValues
private ArrayList<Integer> mCoolDevToThrottBucketSize = null;
private CoolingDeviceInfo lastCoolingDevInfoInstance = null;
public ZoneCoolerBindingInfo() {
mZoneToCoolDevBucketSize = new ArrayList<Integer>();
mCoolDevToThrottBucketSize = new ArrayList<Integer>();
}
public int getLastState() {
// mMaxStates = k + 1(for critical) + 1(for TOFF)
return mMaxStates - 2;
}
public void setMaxStates(int state) {
mMaxStates = state;
}
public int getMaxStates() {
return mMaxStates;
}
public void setZoneToCoolDevBucketSize() {
int size = 1;
int zoneStates = getMaxStates();
for (CoolingDeviceInfo coolDev : mCoolingDeviceInfoList) {
size = (zoneStates - 1) / coolDev.getCoolingDeviceStates();
mZoneToCoolDevBucketSize.add(size == 0 ? 1 : size);
}
}
public int getZoneToCoolDevBucketSizeIndex(int index) {
if (mZoneToCoolDevBucketSize.size() > index)
return mZoneToCoolDevBucketSize.get(index);
return 1;
}
public int getCoolDevToThrottBucketSizeIndex(int index) {
if (mZoneToCoolDevBucketSize.size() > index)
return mCoolDevToThrottBucketSize.get(index);
return 1;
}
public void setCoolDevToThrottBucketSize() {
int size = 1;
for (CoolingDeviceInfo coolDev : mCoolingDeviceInfoList) {
size = coolDev.getMaxThrottleStates() / coolDev.getCoolingDeviceStates();
mCoolDevToThrottBucketSize.add(size == 0 ? 1 : size);
}
}
public void printAttributes() {
if (mCoolingDeviceInfoList == null) return;
StringBuilder s = new StringBuilder();
for (CoolingDeviceInfo c : mCoolingDeviceInfoList) {
if (c != null) {
s.append(c.getCoolingDeviceId());
s.append(",");
}
}
Log.i(TAG, "zone id:" + mZoneID + " coolingDevID mapped:" + s.toString());
}
public void printMappedAttributes() {
if (mZoneToCoolDevBucketSize == null || mCoolDevToThrottBucketSize == null) return;
StringBuilder s = new StringBuilder();
for (int bs : mZoneToCoolDevBucketSize) {
s.append(bs);
s.append(",");
}
Log.i(TAG, "zone id:" + mZoneID + " ZoneToCoolDevBucketSize:" + s.toString());
// clear the string
s.delete(0,s.length());
for (int bs : mCoolDevToThrottBucketSize) {
s.append(bs);
s.append(",");
}
Log.i(TAG, "zone id:" + mZoneID + " CoolDevToThrottBucketSize:" + s.toString());
}
public class CoolingDeviceInfo {
private int mCDeviceID;
// mCoolingDeviceState is number of device states exposed under a zone.
// this must be less than or equal to its total number of throttle values
private int mCoolingDeviceStates = DEFAULT_NUM_THROTTLE_VALUES;
// store a copy here for fast lookup during throttling/dethrottling
private int mMaxThrottleStates = 0;
private ArrayList<Integer> mDeviceThrottleMask = null;
private ArrayList<Integer> mDeviceDethrottleMask = null;
public CoolingDeviceInfo() {
}
public int getMaxThrottleStates() {
return mMaxThrottleStates;
}
public boolean checkMaskList(int throttleStates) {
boolean ret = true;
// if the list is empty this mean, THROTTLE MASK and/or
// DETHTOTTLE mask was not provided. Initialize default mask.
if (mDeviceThrottleMask == null) {
mDeviceThrottleMask = new ArrayList<Integer>();
for (int i = 0; i < mCoolingDeviceStates; i++) {
mDeviceThrottleMask.add(THROTTLE_MASK_ENABLE);
}
} else if (mDeviceThrottleMask.size() != mCoolingDeviceStates) {
Log.i(TAG, "cdevid:" + mCDeviceID
+ " has mismatch in Cooling device state and mask array!deactivate!");
ret = false;
}
if (mDeviceDethrottleMask == null) {
mDeviceDethrottleMask = new ArrayList<Integer>();
for (int i = 0; i < mCoolingDeviceStates; i++) {
mDeviceDethrottleMask.add(DETHROTTLE_MASK_ENABLE);
}
} else if (mDeviceDethrottleMask.size() != mCoolingDeviceStates) {
Log.i(TAG, "cdevid:" + mCDeviceID
+ " has mismatch in Cooling device state and mask array!deactivate!");
ret = false;
}
if (ret) {
mMaxThrottleStates = throttleStates;
}
return ret;
}
public int getCoolingDeviceId() {
return mCDeviceID;
}
public void setCoolingDeviceId(int deviceID) {
mCDeviceID = deviceID;
}
public int getCoolingDeviceStates() {
return mCoolingDeviceStates;
}
public void setCoolingDeviceStates(int num) {
mCoolingDeviceStates = num;
}
public ArrayList<Integer> getThrottleMaskList() {
return mDeviceThrottleMask;
}
public ArrayList<Integer> getDeThrottleMaskList() {
return mDeviceDethrottleMask;
}
public void setThrottleMaskList(ArrayList<Integer> list) {
this.mDeviceThrottleMask = list;
}
public void setDeThrottleMaskList(ArrayList<Integer> list) {
this.mDeviceDethrottleMask = list;
}
}
public ArrayList<CoolingDeviceInfo> getCoolingDeviceInfoList() {
return mCoolingDeviceInfoList;
}
public void createNewCoolingDeviceInstance() {
lastCoolingDevInfoInstance = new CoolingDeviceInfo();
}
public CoolingDeviceInfo getLastCoolingDeviceInstance() {
return lastCoolingDevInfoInstance;
}
public void setZoneID(int zoneID) {
mZoneID = zoneID;
}
public int getZoneID() {
return mZoneID;
}
public void setCriticalActionShutdown(int val) {
mIsCriticalActionShutdown = val;
}
public int getCriticalActionShutdown() {
return mIsCriticalActionShutdown;
}
public void setCoolingDeviceInfoList(ArrayList<CoolingDeviceInfo> devinfoList) {
mCoolingDeviceInfoList = devinfoList;
}
public void initializeCoolingDeviceInfoList() {
mCoolingDeviceInfoList = new ArrayList<CoolingDeviceInfo>();
}
public void addCoolingDeviceToList(CoolingDeviceInfo CdeviceInfo) {
mCoolingDeviceInfoList.add(CdeviceInfo);
}
}
/* platform information */
public static class PlatformInfo {
public int mMaxThermalStates;
public int getMaxThermalStates() {
return mMaxThermalStates;
}
public void printAttrs() {
Log.i(TAG, Integer.toString(mMaxThermalStates));
}
public PlatformInfo() {}
}
/* methods */
public ThermalManager() {
// empty constructor
}
public static void setContext(Context context) {
sContext = context;
}
public static String getVersion() {
return sVersion;
}
public static void loadiTUXVersion() {
sVersion = SystemProperties.get(ITUX_VERSION_PROPERTY, "none");
if (sVersion.equalsIgnoreCase("none")) {
Log.i(TAG, "iTUX Version not found!");
} else {
Log.i(TAG, "iTUX Version:" + sVersion);
}
}
public static void addThermalEvent(ThermalEvent event) {
try {
ThermalManager.sEventQueue.put(event);
} catch (InterruptedException ex) {
Log.i(TAG, "caught InterruptedException in posting to event queue");
}
}
public static void setCurBindMap(String profName) {
synchronized (sProfileSwitchLock) {
sZoneCoolerBindMap = sProfileBindMap.get(profName);
}
}
public static Hashtable<Integer, ZoneCoolerBindingInfo> getCurBindMap() {
synchronized (sProfileSwitchLock) {
return sZoneCoolerBindMap;
}
}
public static Hashtable<Integer, ZoneCoolerBindingInfo> getBindMap(String profName) {
return sProfileBindMap.get(profName);
}
private static void setCurProfileName(String profName) {
sCurProfileName = profName;
}
public static String getCurProfileName() {
return sCurProfileName;
}
private static boolean isProfileExists(String profName) {
if (sProfileZoneMap.get(profName) == null || sProfileBindMap.get(profName) == null) {
return false;
}
return true;
}
private static void startNewProfile(String profName) {
sThermalZonesList = sProfileZoneMap.get(profName);
sZoneCoolerBindMap = sProfileBindMap.get(profName);
if (sThermalZonesList == null || sZoneCoolerBindMap == null) {
Log.i(TAG, "Couldn't shift to profile:" + profName);
return;
}
initializeZoneCriticalPendingMap();
setCurProfileName(profName);
int activeZones = startMonitoringZones();
Log.i(TAG, activeZones + " zones found active in profile " + profName);
// broadcast a sticky intent for the clients
sendQueryProfileIntent();
}
public static void stopCurrentProfile() {
for (ThermalZone zone : sThermalZonesList) {
// Stop Polling threads
zone.stopMonitoring();
// Unregister UEvent/EmulTemp observers
zone.unregisterReceiver();
// Reset Parameters:
// Zone State: Normal, Event Type: LOW, Temperature: Normal Threshold
zone.setZoneState(0);
zone.setEventType(ThermalManager.THERMAL_LOW_EVENT);
zone.setZoneTemp(zone.getZoneTempThreshold(0));
// Send ThermalIntent with above parameters
// This will release all throttle controls this zone had.
// Since we are in the middle of a profile switch(stop),
// set the override parameter as true, so that this
// event is actually queued for processing.
// TODO: Find a way to take care of zones that are not
// present in thermal_sensor_config.xml but present in
// thermal_throttle_config.xml (usually from other components)
zone.sendThermalEvent();
// Reprogram the sensor thresholds if this zone supported interrupts
// TODO: We are reprogramming the calibrated thresholds in case the
// the sensor was using 'weights' and 'offset'. Hope this is fine.
if (zone.isUEventSupported()) {
zone.programThresholds((zone.getThermalSensorList()).get(0));
}
}
}
public static void startDefaultProfile() {
if (isProfileExists(DEFAULT_PROFILE_NAME)) {
startNewProfile(DEFAULT_PROFILE_NAME);
}
// register for Thermal Profile Change Intent only after
// we have started the default profile
sCoolingManager.registerProfChangeListener();
}
public static void changeThermalProfile(String newProfName) {
synchronized (sProfileSwitchLock) {
if (newProfName.equalsIgnoreCase(sCurProfileName)) {
Log.i(TAG, "New Profile same as current profile. Profile change request Ignored");
return;
}
if (!isProfileExists(newProfName)) {
Log.i(TAG, "New Profile does not exist in xml. Profile change request Ignored");
return;
}
Log.i(TAG, "ACTION_CHANGE_THERMAL_PROFILE received. New Profile: " + newProfName);
stopCurrentProfile();
startNewProfile(newProfName);
}
}
public static void setBucketSizeForProfiles() {
Iterator it = ThermalManager.sProfileZoneMap.entrySet().iterator();
while (it.hasNext()) {
Map.Entry entryProfZone = (Map.Entry) it.next();
String keyProfile = (String) entryProfZone.getKey();
sThermalZonesList = (ArrayList<ThermalZone>) entryProfZone.getValue();
setCurBindMap(keyProfile);
for (ThermalZone zone : sThermalZonesList) {
if (sZoneCoolerBindMap == null) {
Log.e(TAG, "ZoneCoolerBindMap null while setBucketSizeForProfiles");
return;
}
ZoneCoolerBindingInfo bindInfo = sZoneCoolerBindMap.get(zone.getZoneId());
if (bindInfo == null) {
Log.e(TAG, "CoolerBindingInfo for zoneid:" + zone.getZoneId() + "not mapped");
return;
}
bindInfo.setMaxStates(zone.getMaxStates());
bindInfo.setZoneToCoolDevBucketSize();
bindInfo.setCoolDevToThrottBucketSize();
if (zone.isUEventSupported()) {
// calibration of thresholds based on weight, order
if (!zone.isMaxThreshExceed())
zone.calibrateThresholds();
}
}
}
}
public static int startMonitoringZones() {
int activeZonesCount = 0;
for (ThermalZone zone : sThermalZonesList) {
zone.computeZoneActiveStatus();
if (zone.getZoneActiveStatus() == false) {
Log.i(TAG, "deactivating inactive zone:" + zone.getZoneName());
continue;
}
ZoneCoolerBindingInfo bindInfo = sZoneCoolerBindMap.get(zone.getZoneId());
if (bindInfo != null) {
// TODO: To be conditioned under debug
bindInfo.printMappedAttributes();
}
if (zone.isUEventSupported()) {
zone.registerUevent();
} else {
// start polling thread for each zone
zone.startMonitoring();
}
zone.startEmulTempObserver();
activeZonesCount++;
}
return activeZonesCount;
}
public static void readShutdownNotiferProperties() {
try {
if ("1".equals(SystemProperties.get("persist.thermal.shutdown.msg", "0"))) {
sShutdownToast = true;
}
if ("1".equals(SystemProperties.get("persist.thermal.shutdown.tone", "0"))) {
sShutdownTone = true;
}
if ("1".equals(SystemProperties.get("persist.thermal.shutdown.vibra", "0"))) {
sShutdownVibra = true;
}
} catch (java.lang.IllegalArgumentException e) {
Log.e(TAG, "exception caught in reading thermal system properties");
}
}
private static void initializeZoneCriticalPendingMap() {
sZoneCriticalPendingMap = new Hashtable<Integer, Integer>();
if (sZoneCriticalPendingMap == null) return;
Enumeration en;
try {
// look up for zone list is performed from sZoneCoolerBindMap instead of
// sThermalZonesList since some non thermal zones may not have entry in
// sThermalZonesList. This is because such zones only have entry in throttle
// config file and not in sensor config files.
// 'sZoneCoolerBindMap' is protected by caller here.
en = sZoneCoolerBindMap.keys();
while (en.hasMoreElements()) {
int zone = (Integer) en.nextElement();
sZoneCriticalPendingMap.put(zone, CRITICAL_FALSE);
}
} catch (NoSuchElementException e) {
Log.i(TAG, "NoSuchElementException in InitializeZoneCriticalPendingMap()");
}
}
/*
* updateZoneCriticalPendingMap updates sZoneCriticalPendingMap synchronously.
* sCriticalZonesCount is incremented iff old value in the map for the zone is
* FALSE (ensures count is incremented only once for a zone) and decremented
* iff oldval is TRUE (ensures no negative value for count)
**/
public static boolean updateZoneCriticalPendingMap(int zoneid, int flag) {
synchronized (sCriticalPendingLock) {
if (sZoneCriticalPendingMap == null) return false;
Integer oldVal = sZoneCriticalPendingMap.get(zoneid);
if (oldVal == null) return false;
sZoneCriticalPendingMap.put(zoneid, flag);
if (oldVal == CRITICAL_FALSE && flag == CRITICAL_TRUE) {
sCriticalZonesCount++;
} else if (oldVal == CRITICAL_TRUE && flag == CRITICAL_FALSE) {
sCriticalZonesCount--;
}
return true;
}
}
public static boolean checkShutdownCondition() {
synchronized (sCriticalPendingLock) {
return sCriticalZonesCount > 0;
}
}
public static ThermalSensor getSensor(String sensorName) {
if (sensorName == null || sSensorMap == null) return null;
return sSensorMap.get(sensorName);
}
public static void buildProfileNameList() {
int count = 0;
StringBuilder s = new StringBuilder();
Iterator it = sProfileZoneMap.entrySet().iterator();
while (it.hasNext()) {
Map.Entry entry = (Map.Entry) it.next();
String key = (String) entry.getKey();
// create list of only valid profiles
if (isProfileExists(key)) {
// build a space seperate list of string
s.append(key);
s.append(" ");
count++;
}
}
sProfileNameList = s.toString();
sProfileCount = count;
Log.i(TAG, "profile name list:" + sProfileNameList);
Log.i(TAG, "profile count:" + sProfileCount);
}
public static void initializeStickyIntent() {
sQueryProfileIntent = new Intent();
sQueryProfileIntent.setAction(ACTION_QUERY_THERMAL_PROFILE);
}
private static void sendQueryProfileIntent() {
if (sQueryProfileIntent != null && sContext != null) {
sQueryProfileIntent.putExtra(ThermalManager.EXTRA_NUM_PROFILE, sProfileCount);
sQueryProfileIntent.putExtra(ThermalManager.EXTRA_PROFILE_LIST, sProfileNameList);
sQueryProfileIntent.putExtra(ThermalManager.EXTRA_CUR_PROFILE, sCurProfileName);
sContext.sendStickyBroadcastAsUser(sQueryProfileIntent, UserHandle.ALL);
}
}
public static void clearData() {
sThermalZonesList.clear();
// clearing hastables
sProfileZoneMap.clear();
sZoneCoolerBindMap.clear();
sProfileBindMap.clear();
sCDevMap.clear();
sSensorMap.clear();
sZoneCriticalPendingMap.clear();
}
}