Add thermal service into system_server
This system service will listen to ThermalHAL for throttling events and
take actions accordingly, e.g. shutdown device and/or sending
notification to registered listeners to IThermalSerivce.
Bug: 79443945
Bug: 118510237
Bug: 111086696
Bug: 116541003
Test: Boot and test callback on ThermalHAL 1.1
Test: Boot and test callback on ThermalHAL 2.0
Test: Kill ThermalHAL process
Test: Change device threshold to trigger shutdown
Change-Id: I1f4066c9f1cf9ab46c1738a0a4435802512e4339
diff --git a/Android.bp b/Android.bp
index 8163ff8..10b92f3 100644
--- a/Android.bp
+++ b/Android.bp
@@ -706,6 +706,8 @@
"android.hardware.contexthub-V1.0-java",
"android.hardware.health-V1.0-java-constants",
"android.hardware.thermal-V1.0-java-constants",
+ "android.hardware.thermal-V1.1-java",
+ "android.hardware.thermal-V2.0-java",
"android.hardware.tv.input-V1.0-java-constants",
"android.hardware.usb-V1.0-java-constants",
"android.hardware.usb-V1.1-java-constants",
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index ccf8417..2aa32c4 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -4227,6 +4227,15 @@
/**
* Use with {@link #getSystemService(String)} to retrieve a
+ * {@link android.os.ThermalService} for accessing the thermal service.
+ *
+ * @see #getSystemService(String)
+ * @hide
+ */
+ public static final String THERMAL_SERVICE = "thermalservice";
+
+ /**
+ * Use with {@link #getSystemService(String)} to retrieve a
* {@link android.content.pm.ShortcutManager} for accessing the launcher shortcut service.
*
* @see #getSystemService(String)
diff --git a/core/java/android/os/IThermalEventListener.aidl b/core/java/android/os/IThermalEventListener.aidl
index 9a6de60..fc93b5c 100644
--- a/core/java/android/os/IThermalEventListener.aidl
+++ b/core/java/android/os/IThermalEventListener.aidl
@@ -27,6 +27,5 @@
* Called when a thermal throttling start/stop event is received.
* @param temperature the temperature at which the event was generated.
*/
- void notifyThrottling(
- in boolean isThrottling, in Temperature temperature);
+ void notifyThrottling(in Temperature temperature);
}
diff --git a/core/java/android/os/IThermalService.aidl b/core/java/android/os/IThermalService.aidl
index e388eda..287a5ed 100644
--- a/core/java/android/os/IThermalService.aidl
+++ b/core/java/android/os/IThermalService.aidl
@@ -19,6 +19,8 @@
import android.os.IThermalEventListener;
import android.os.Temperature;
+import java.util.List;
+
/**
* {@hide}
*/
@@ -30,22 +32,29 @@
*/
void registerThermalEventListener(in IThermalEventListener listener);
/**
+ * Register a listener for thermal events on given temperature type.
+ * @param listener the IThermalEventListener to be notified.
+ * @param type the temperature type IThermalEventListener to be notified.
+ * {@hide}
+ */
+ void registerThermalEventListenerWithType(in IThermalEventListener listener, in int type);
+ /**
* Unregister a previously-registered listener for thermal events.
* @param listener the IThermalEventListener to no longer be notified.
* {@hide}
*/
void unregisterThermalEventListener(in IThermalEventListener listener);
/**
- * Send a thermal throttling start/stop notification to all listeners.
- * @param temperature the temperature at which the event was generated.
+ * Get current temperature with its throttling status.
+ * @return list of android.os.Temperature
* {@hide}
*/
- oneway void notifyThrottling(
- in boolean isThrottling, in Temperature temperature);
+ List<Temperature> getCurrentTemperatures();
/**
- * Return whether system performance is currently thermal throttling.
- * @return true if thermal throttling is currently in effect
+ * Get current temperature with its throttling status on given temperature type.
+ * @param type the temperature type to query.
+ * @return list of android.os.Temperature
* {@hide}
*/
- boolean isThrottling();
+ List<Temperature> getCurrentTemperaturesWithType(in int type);
}
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index e0b2c78..27c281d 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -477,6 +477,13 @@
public static final String SHUTDOWN_BATTERY_THERMAL_STATE = "thermal,battery";
/**
+ * The value to pass as the 'reason' argument to android_reboot() when device temperature
+ * is too high.
+ * @hide
+ */
+ public static final String SHUTDOWN_THERMAL_STATE = "thermal";
+
+ /**
* The value to pass as the 'reason' argument to android_reboot() when device is running
* critically low on battery.
* @hide
diff --git a/core/java/android/os/Temperature.java b/core/java/android/os/Temperature.java
index 8767731..37ed52c 100644
--- a/core/java/android/os/Temperature.java
+++ b/core/java/android/os/Temperature.java
@@ -16,6 +16,13 @@
package android.os;
+import android.annotation.IntDef;
+import android.hardware.thermal.V2_0.TemperatureType;
+import android.hardware.thermal.V2_0.ThrottlingSeverity;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
/**
* Temperature values used by IThermalService.
*/
@@ -24,24 +31,89 @@
* @hide
*/
public class Temperature implements Parcelable {
- /* Temperature value */
+ /** Temperature value */
private float mValue;
- /* A temperature type from HardwarePropertiesManager */
+ /** A temperature type from ThermalHAL */
private int mType;
+ /** Name of this temperature */
+ private String mName;
+ /** The level of the sensor is currently in throttling */
+ private int mStatus;
- public Temperature() {
- this(HardwarePropertiesManager.UNDEFINED_TEMPERATURE,
- Integer.MIN_VALUE);
+ /** @hide */
+ @IntDef(prefix = { "THROTTLING_" }, value = {
+ THROTTLING_NONE,
+ THROTTLING_LIGHT,
+ THROTTLING_MODERATE,
+ THROTTLING_SEVERE,
+ THROTTLING_CRITICAL,
+ THROTTLING_WARNING,
+ THROTTLING_SHUTDOWN,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ThrottlingStatus {}
+
+ /** Keep in sync with hardware/interfaces/thermal/2.0/types.hal */
+ public static final int THROTTLING_NONE = ThrottlingSeverity.NONE;
+ public static final int THROTTLING_LIGHT = ThrottlingSeverity.LIGHT;
+ public static final int THROTTLING_MODERATE = ThrottlingSeverity.MODERATE;
+ public static final int THROTTLING_SEVERE = ThrottlingSeverity.SEVERE;
+ public static final int THROTTLING_CRITICAL = ThrottlingSeverity.CRITICAL;
+ public static final int THROTTLING_WARNING = ThrottlingSeverity.WARNING;
+ public static final int THROTTLING_SHUTDOWN = ThrottlingSeverity.SHUTDOWN;
+
+ /** @hide */
+ @IntDef(prefix = { "TYPE_" }, value = {
+ TYPE_UNKNOWN,
+ TYPE_CPU,
+ TYPE_GPU,
+ TYPE_BATTERY,
+ TYPE_SKIN,
+ TYPE_USB_PORT,
+ TYPE_POWER_AMPLIFIER,
+ TYPE_BCL_VOLTAGE,
+ TYPE_BCL_CURRENT,
+ TYPE_BCL_PERCENTAGE,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Type {}
+
+ /* Keep in sync with hardware/interfaces/thermal/2.0/types.hal */
+ public static final int TYPE_UNKNOWN = TemperatureType.UNKNOWN;
+ public static final int TYPE_CPU = TemperatureType.CPU;
+ public static final int TYPE_GPU = TemperatureType.GPU;
+ public static final int TYPE_BATTERY = TemperatureType.BATTERY;
+ public static final int TYPE_SKIN = TemperatureType.SKIN;
+ public static final int TYPE_USB_PORT = TemperatureType.USB_PORT;
+ public static final int TYPE_POWER_AMPLIFIER = TemperatureType.POWER_AMPLIFIER;
+ public static final int TYPE_BCL_VOLTAGE = TemperatureType.BCL_VOLTAGE;
+ public static final int TYPE_BCL_CURRENT = TemperatureType.BCL_CURRENT;
+ public static final int TYPE_BCL_PERCENTAGE = TemperatureType.BCL_PERCENTAGE;
+
+ /**
+ * Verify a valid temperature type.
+ *
+ * @return true if a temperature type is valid otherwise false.
+ */
+ public static boolean isValidType(int type) {
+ return type >= TYPE_UNKNOWN && type <= TYPE_BCL_PERCENTAGE;
}
- public Temperature(float value, int type) {
+ public Temperature() {
+ this(Float.NaN, TYPE_UNKNOWN, "", THROTTLING_NONE);
+ }
+
+ public Temperature(float value, @Type int type, String name, int status) {
mValue = value;
- mType = type;
+ mType = isValidType(type) ? type : TYPE_UNKNOWN;
+ mName = name;
+ mStatus = status;
}
/**
* Return the temperature value.
- * @return a temperature value in floating point.
+ *
+ * @return a temperature value in floating point could be NaN.
*/
public float getValue() {
return mValue;
@@ -49,18 +121,30 @@
/**
* Return the temperature type.
- * @return a temperature type:
- * HardwarePropertiesManager.DEVICE_TEMPERATURE_CPU, etc.
+ *
+ * @return a temperature type: TYPE_*
*/
- public int getType() {
+ public @Type int getType() {
return mType;
}
- /*
- * Parcel read/write code must be kept in sync with
- * frameworks/native/services/thermalservice/aidl/android/os/
- * Temperature.cpp
+ /**
+ * Return the temperature name.
+ *
+ * @return a temperature name as String.
*/
+ public String getName() {
+ return mName;
+ }
+
+ /**
+ * Return the temperature throttling status.
+ *
+ * @return a temperature throttling status: THROTTLING_*
+ */
+ public @ThrottlingStatus int getStatus() {
+ return mStatus;
+ }
private Temperature(Parcel p) {
readFromParcel(p);
@@ -68,31 +152,36 @@
/**
* Fill in Temperature members from a Parcel.
+ *
* @param p the parceled Temperature object.
*/
public void readFromParcel(Parcel p) {
mValue = p.readFloat();
mType = p.readInt();
+ mName = p.readString();
+ mStatus = p.readInt();
}
@Override
public void writeToParcel(Parcel p, int flags) {
p.writeFloat(mValue);
p.writeInt(mType);
+ p.writeString(mName);
+ p.writeInt(mStatus);
}
public static final Parcelable.Creator<Temperature> CREATOR =
new Parcelable.Creator<Temperature>() {
- @Override
- public Temperature createFromParcel(Parcel p) {
- return new Temperature(p);
- }
+ @Override
+ public Temperature createFromParcel(Parcel p) {
+ return new Temperature(p);
+ }
- @Override
- public Temperature[] newArray(int size) {
- return new Temperature[size];
- }
- };
+ @Override
+ public Temperature[] newArray(int size) {
+ return new Temperature[size];
+ }
+ };
@Override
public int describeContents() {
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
index 568a039..35ae899 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
@@ -399,8 +399,8 @@
if (b != null) {
mThermalService = IThermalService.Stub.asInterface(b);
try {
- mThermalService.registerThermalEventListener(
- new ThermalEventListener());
+ mThermalService.registerThermalEventListenerWithType(
+ new ThermalEventListener(), Temperature.TYPE_SKIN);
} catch (RemoteException e) {
// Should never happen.
}
@@ -552,7 +552,7 @@
// Thermal event received from vendor thermal management subsystem
private final class ThermalEventListener extends IThermalEventListener.Stub {
- @Override public void notifyThrottling(boolean isThrottling, Temperature temp) {
+ @Override public void notifyThrottling(Temperature temp) {
// Trigger an update of the temperature warning. Only one
// callback can be enabled at a time, so remove any existing
// callback; updateTemperatureWarning will schedule another one.
diff --git a/services/core/java/com/android/server/power/OWNERS b/services/core/java/com/android/server/power/OWNERS
index d118c4e..20e4985 100644
--- a/services/core/java/com/android/server/power/OWNERS
+++ b/services/core/java/com/android/server/power/OWNERS
@@ -2,3 +2,4 @@
per-file BatterySaverPolicy.java=omakoto@google.com
per-file ShutdownThread.java=fkupolov@google.com
+per-file ThermalManagerService.java=wvw@google.com
\ No newline at end of file
diff --git a/services/core/java/com/android/server/power/ThermalManagerService.java b/services/core/java/com/android/server/power/ThermalManagerService.java
new file mode 100644
index 0000000..812fd82
--- /dev/null
+++ b/services/core/java/com/android/server/power/ThermalManagerService.java
@@ -0,0 +1,392 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * 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.android.server.power;
+
+import android.content.Context;
+import android.hardware.thermal.V1_0.ThermalStatus;
+import android.hardware.thermal.V1_0.ThermalStatusCode;
+import android.hardware.thermal.V1_1.IThermalCallback;
+import android.hardware.thermal.V2_0.IThermalChangedCallback;
+import android.hardware.thermal.V2_0.ThrottlingSeverity;
+import android.os.Binder;
+import android.os.HwBinder;
+import android.os.IThermalEventListener;
+import android.os.IThermalService;
+import android.os.PowerManager;
+import android.os.RemoteCallbackList;
+import android.os.RemoteException;
+import android.util.Slog;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.DumpUtils;
+import com.android.server.FgThread;
+import com.android.server.SystemService;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.NoSuchElementException;
+
+/**
+ * This is a system service that listens to HAL thermal events and dispatch those to listeners.
+ * <p>The service will also trigger actions based on severity of the throttling status.</p>
+ *
+ * @hide
+ */
+public class ThermalManagerService extends SystemService {
+ private static final String TAG = ThermalManagerService.class.getSimpleName();
+
+ /** Registered observers of the thermal changed events. Cookie is used to store type */
+ @GuardedBy("mLock")
+ private final RemoteCallbackList<IThermalEventListener> mThermalEventListeners =
+ new RemoteCallbackList<>();
+
+ /** Lock to protect HAL handles and listen list. */
+ private final Object mLock = new Object();
+
+ /** Newly registered callback. */
+ @GuardedBy("mLock")
+ private IThermalEventListener mNewListenerCallback = null;
+
+ /** Newly registered callback type, null means not filter type. */
+ @GuardedBy("mLock")
+ private Integer mNewListenerType = null;
+
+ /** Local PMS handle. */
+ private final PowerManager mPowerManager;
+
+ /** Proxy object for the Thermal HAL 2.0 service. */
+ @GuardedBy("mLock")
+ private android.hardware.thermal.V2_0.IThermal mThermalHal20 = null;
+
+ /** Proxy object for the Thermal HAL 1.1 service. */
+ @GuardedBy("mLock")
+ private android.hardware.thermal.V1_1.IThermal mThermalHal11 = null;
+
+ /** Cookie for matching the right end point. */
+ private static final int THERMAL_HAL_DEATH_COOKIE = 5612;
+
+ /** HWbinder callback for Thermal HAL 2.0. */
+ private final IThermalChangedCallback.Stub mThermalCallback20 =
+ new IThermalChangedCallback.Stub() {
+ @Override
+ public void notifyThrottling(
+ android.hardware.thermal.V2_0.Temperature temperature) {
+ android.os.Temperature thermalSvcTemp = new android.os.Temperature(
+ temperature.value, temperature.type, temperature.name,
+ temperature.throttlingStatus);
+ final long token = Binder.clearCallingIdentity();
+ try {
+ notifyThrottlingImpl(thermalSvcTemp);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+ };
+
+ /** HWbinder callback for Thermal HAL 1.1. */
+ private final IThermalCallback.Stub mThermalCallback11 =
+ new IThermalCallback.Stub() {
+ @Override
+ public void notifyThrottling(boolean isThrottling,
+ android.hardware.thermal.V1_0.Temperature temperature) {
+ android.os.Temperature thermalSvcTemp = new android.os.Temperature(
+ temperature.currentValue, temperature.type, temperature.name,
+ isThrottling ? ThrottlingSeverity.SEVERE : ThrottlingSeverity.NONE);
+ final long token = Binder.clearCallingIdentity();
+ try {
+ notifyThrottlingImpl(thermalSvcTemp);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+ };
+
+ public ThermalManagerService(Context context) {
+ super(context);
+ mPowerManager = context.getSystemService(PowerManager.class);
+ }
+
+ private void setNewListener(IThermalEventListener listener, Integer type) {
+ synchronized (mLock) {
+ mNewListenerCallback = listener;
+ mNewListenerType = type;
+ }
+ }
+
+ private void clearNewListener() {
+ synchronized (mLock) {
+ mNewListenerCallback = null;
+ mNewListenerType = null;
+ }
+ }
+
+ private final IThermalService.Stub mService = new IThermalService.Stub() {
+ @Override
+ public void registerThermalEventListener(IThermalEventListener listener) {
+ synchronized (mLock) {
+ mThermalEventListeners.register(listener, null);
+ // Notify its callback after new client registered.
+ setNewListener(listener, null);
+ long token = Binder.clearCallingIdentity();
+ try {
+ notifyCurrentTemperaturesLocked();
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ clearNewListener();
+ }
+ }
+ }
+
+ @Override
+ public void registerThermalEventListenerWithType(IThermalEventListener listener, int type) {
+ synchronized (mLock) {
+ mThermalEventListeners.register(listener, new Integer(type));
+ setNewListener(listener, new Integer(type));
+ // Notify its callback after new client registered.
+ long token = Binder.clearCallingIdentity();
+ try {
+ notifyCurrentTemperaturesLocked();
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ clearNewListener();
+ }
+ }
+ }
+
+ @Override
+ public void unregisterThermalEventListener(IThermalEventListener listener) {
+ synchronized (mLock) {
+ long token = Binder.clearCallingIdentity();
+ try {
+ mThermalEventListeners.unregister(listener);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+ }
+
+ @Override
+ public List<android.os.Temperature> getCurrentTemperatures() {
+ List<android.os.Temperature> ret;
+ long token = Binder.clearCallingIdentity();
+ try {
+ ret = getCurrentTemperaturesInternal(false, 0 /* not used */);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ return ret;
+ }
+
+ @Override
+ public List<android.os.Temperature> getCurrentTemperaturesWithType(int type) {
+ List<android.os.Temperature> ret;
+ long token = Binder.clearCallingIdentity();
+ try {
+ ret = getCurrentTemperaturesInternal(true, type);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ return ret;
+ }
+
+ @Override
+ protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ if (!DumpUtils.checkDumpPermission(getContext(), TAG, pw)) return;
+ pw.println("ThermalEventListeners dump:");
+ synchronized (mLock) {
+ mThermalEventListeners.dump(pw, "\t");
+ pw.println("ThermalHAL 1.1 connected: " + (mThermalHal11 != null ? "yes" : "no"));
+ pw.println("ThermalHAL 2.0 connected: " + (mThermalHal20 != null ? "yes" : "no"));
+ }
+ }
+ };
+
+ private List<android.os.Temperature> getCurrentTemperaturesInternal(boolean shouldFilter,
+ int type) {
+ List<android.os.Temperature> ret = new ArrayList<>();
+ synchronized (mLock) {
+ if (mThermalHal20 == null) {
+ return ret;
+ }
+ try {
+ mThermalHal20.getCurrentTemperatures(shouldFilter, type,
+ (ThermalStatus status,
+ ArrayList<android.hardware.thermal.V2_0.Temperature>
+ temperatures) -> {
+ if (ThermalStatusCode.SUCCESS == status.code) {
+ for (android.hardware.thermal.V2_0.Temperature
+ temperature : temperatures) {
+ ret.add(new android.os.Temperature(
+ temperature.value, temperature.type, temperature.name,
+ temperature.throttlingStatus));
+ }
+ } else {
+ Slog.e(TAG,
+ "Couldn't get temperatures because of HAL error: "
+ + status.debugMessage);
+ }
+
+ });
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Couldn't getCurrentTemperatures, reconnecting...", e);
+ connectToHalLocked();
+ // Post to listeners after reconnect to HAL.
+ notifyCurrentTemperaturesLocked();
+ }
+ }
+ return ret;
+ }
+
+ private void notifyListener(android.os.Temperature temperature, IThermalEventListener listener,
+ Integer type) {
+ // Skip if listener registered with a different type
+ if (type != null && type != temperature.getType()) {
+ return;
+ }
+ final boolean thermalCallbackQueued = FgThread.getHandler().post(() -> {
+ try {
+ listener.notifyThrottling(temperature);
+ } catch (RemoteException | RuntimeException e) {
+ Slog.e(TAG, "Thermal callback failed to call", e);
+ }
+ });
+ if (!thermalCallbackQueued) {
+ Slog.e(TAG, "Thermal callback failed to queue");
+ }
+ }
+
+ private void notifyThrottlingImpl(android.os.Temperature temperature) {
+ synchronized (mLock) {
+ // Thermal Shutdown for Skin temperature
+ if (temperature.getStatus() == android.os.Temperature.THROTTLING_SHUTDOWN
+ && temperature.getType() == android.os.Temperature.TYPE_SKIN) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mPowerManager.shutdown(false, PowerManager.SHUTDOWN_THERMAL_STATE, false);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ if (mNewListenerCallback != null) {
+ // Only notify current newly added callback.
+ notifyListener(temperature, mNewListenerCallback, mNewListenerType);
+ } else {
+ final int length = mThermalEventListeners.beginBroadcast();
+ try {
+ for (int i = 0; i < length; i++) {
+ final IThermalEventListener listener =
+ mThermalEventListeners.getBroadcastItem(i);
+ final Integer type = (Integer) mThermalEventListeners.getBroadcastCookie(i);
+ notifyListener(temperature, listener, type);
+ }
+ } finally {
+ mThermalEventListeners.finishBroadcast();
+ }
+ }
+ }
+ }
+
+ @Override
+ public void onStart() {
+ publishBinderService(Context.THERMAL_SERVICE, mService);
+ }
+
+ @Override
+ public void onBootPhase(int phase) {
+ if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
+ onActivityManagerReady();
+ }
+ }
+
+ private void notifyCurrentTemperaturesCallbackLocked(ThermalStatus status,
+ ArrayList<android.hardware.thermal.V2_0.Temperature> temperatures) {
+ if (ThermalStatusCode.SUCCESS != status.code) {
+ Slog.e(TAG, "Couldn't get temperatures because of HAL error: "
+ + status.debugMessage);
+ return;
+ }
+ for (android.hardware.thermal.V2_0.Temperature temperature : temperatures) {
+ android.os.Temperature thermal_svc_temp =
+ new android.os.Temperature(
+ temperature.value, temperature.type,
+ temperature.name,
+ temperature.throttlingStatus);
+ notifyThrottlingImpl(thermal_svc_temp);
+ }
+ }
+
+ private void notifyCurrentTemperaturesLocked() {
+ if (mThermalHal20 == null) {
+ return;
+ }
+ try {
+ mThermalHal20.getCurrentTemperatures(false, 0,
+ this::notifyCurrentTemperaturesCallbackLocked);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Couldn't get temperatures, reconnecting...", e);
+ connectToHalLocked();
+ }
+ }
+
+ private void onActivityManagerReady() {
+ synchronized (mLock) {
+ connectToHalLocked();
+ // Post to listeners after connect to HAL.
+ notifyCurrentTemperaturesLocked();
+ }
+ }
+
+ final class DeathRecipient implements HwBinder.DeathRecipient {
+ @Override
+ public void serviceDied(long cookie) {
+ if (cookie == THERMAL_HAL_DEATH_COOKIE) {
+ Slog.e(TAG, "Thermal HAL service died cookie: " + cookie);
+ synchronized (mLock) {
+ connectToHalLocked();
+ // Post to listeners after reconnect to HAL.
+ notifyCurrentTemperaturesLocked();
+ }
+ }
+ }
+ }
+
+ private void connectToHalLocked() {
+ try {
+ mThermalHal20 = android.hardware.thermal.V2_0.IThermal.getService();
+ mThermalHal20.linkToDeath(new DeathRecipient(), THERMAL_HAL_DEATH_COOKIE);
+ mThermalHal20.registerThermalChangedCallback(mThermalCallback20, false,
+ 0 /* not used */);
+ } catch (NoSuchElementException | RemoteException e) {
+ Slog.e(TAG, "Thermal HAL 2.0 service not connected, trying 1.1.");
+ mThermalHal20 = null;
+ try {
+ mThermalHal11 = android.hardware.thermal.V1_1.IThermal.getService();
+ mThermalHal11.linkToDeath(new DeathRecipient(), THERMAL_HAL_DEATH_COOKIE);
+ mThermalHal11.registerThermalCallback(mThermalCallback11);
+ } catch (NoSuchElementException | RemoteException e2) {
+ Slog.e(TAG,
+ "Thermal HAL 1.1 service not connected, no thermal call back "
+ + "will be called.");
+ mThermalHal11 = null;
+ }
+ }
+ }
+
+}
diff --git a/services/core/java/com/android/server/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java
index 4d3fc1a..2be55c0 100644
--- a/services/core/java/com/android/server/stats/StatsCompanionService.java
+++ b/services/core/java/com/android/server/stats/StatsCompanionService.java
@@ -253,8 +253,8 @@
if (b != null) {
sThermalService = IThermalService.Stub.asInterface(b);
try {
- sThermalService.registerThermalEventListener(
- new ThermalEventListener());
+ sThermalService.registerThermalEventListenerWithType(
+ new ThermalEventListener(), Temperature.TYPE_SKIN);
Slog.i(TAG, "register thermal listener successfully");
} catch (RemoteException e) {
// Should never happen.
@@ -1853,7 +1853,8 @@
// Thermal event received from vendor thermal management subsystem
private static final class ThermalEventListener extends IThermalEventListener.Stub {
@Override
- public void notifyThrottling(boolean isThrottling, Temperature temp) {
+ public void notifyThrottling(Temperature temp) {
+ boolean isThrottling = temp.getStatus() >= Temperature.THROTTLING_SEVERE;
StatsLog.write(StatsLog.THERMAL_THROTTLING, temp.getType(),
isThrottling ? 1 : 0, temp.getValue());
}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 54a140d..43190ac4 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -115,6 +115,7 @@
import com.android.server.policy.PhoneWindowManager;
import com.android.server.power.PowerManagerService;
import com.android.server.power.ShutdownThread;
+import com.android.server.power.ThermalManagerService;
import com.android.server.restrictions.RestrictionsManagerService;
import com.android.server.security.KeyAttestationApplicationIdProviderService;
import com.android.server.security.KeyChainSystemService;
@@ -607,6 +608,10 @@
mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);
traceEnd();
+ traceBeginAndSlog("StartThermalManager");
+ mSystemServiceManager.startService(ThermalManagerService.class);
+ traceEnd();
+
// Now that the power manager has been started, let the activity manager
// initialize power management features.
traceBeginAndSlog("InitPowerManagement");