Loading Android.bp +1 −1 Original line number Diff line number Diff line Loading @@ -109,7 +109,7 @@ filegroup { ":android.hardware.radio.voice-V3-java-source", ":android.hardware.security.keymint-V3-java-source", ":android.hardware.security.secureclock-V1-java-source", ":android.hardware.thermal-V2-java-source", ":android.hardware.thermal-V3-java-source", ":android.hardware.tv.tuner-V3-java-source", ":android.security.apc-java-source", ":android.security.authorization-java-source", Loading core/java/android/os/flags.aconfig +8 −0 Original line number Diff line number Diff line Loading @@ -90,6 +90,14 @@ flag { bug: "288119641" } flag { name: "allow_thermal_thresholds_callback" is_exported: true namespace: "game" description: "Enable thermal threshold callback" bug: "360486877" } flag { name: "android_os_build_vanilla_ice_cream" is_exported: true Loading services/core/java/com/android/server/power/ThermalManagerService.java +107 −75 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ import android.content.Context; import android.hardware.thermal.IThermal; import android.hardware.thermal.IThermalChangedCallback; import android.hardware.thermal.TemperatureThreshold; import android.hardware.thermal.TemperatureType; import android.hardware.thermal.ThrottlingSeverity; import android.hardware.thermal.V1_0.ThermalStatus; import android.hardware.thermal.V1_0.ThermalStatusCode; Loading Loading @@ -134,6 +135,31 @@ public class ThermalManagerService extends SystemService { @VisibleForTesting final TemperatureWatcher mTemperatureWatcher = new TemperatureWatcher(); private final ThermalHalWrapper.WrapperThermalChangedCallback mWrapperCallback = new ThermalHalWrapper.WrapperThermalChangedCallback() { @Override public void onTemperatureChanged(Temperature temperature) { final long token = Binder.clearCallingIdentity(); try { ThermalManagerService.this.onTemperatureChanged(temperature, true); } finally { Binder.restoreCallingIdentity(token); } } @Override public void onThresholdChanged(TemperatureThreshold threshold) { final long token = Binder.clearCallingIdentity(); try { synchronized (mTemperatureWatcher.mSamples) { mTemperatureWatcher.updateTemperatureThresholdLocked(threshold, true); } } finally { Binder.restoreCallingIdentity(token); } } }; private final Context mContext; public ThermalManagerService(Context context) { Loading @@ -146,7 +172,7 @@ public class ThermalManagerService extends SystemService { mContext = context; mHalWrapper = halWrapper; if (halWrapper != null) { halWrapper.setCallback(this::onTemperatureChangedCallback); halWrapper.setCallback(mWrapperCallback); } mStatus = Temperature.THROTTLING_NONE; } Loading @@ -171,19 +197,19 @@ public class ThermalManagerService extends SystemService { // Connect to HAL and post to listeners. boolean halConnected = (mHalWrapper != null); if (!halConnected) { mHalWrapper = new ThermalHalAidlWrapper(this::onTemperatureChangedCallback); mHalWrapper = new ThermalHalAidlWrapper(mWrapperCallback); halConnected = mHalWrapper.connectToHal(); } if (!halConnected) { mHalWrapper = new ThermalHal20Wrapper(this::onTemperatureChangedCallback); mHalWrapper = new ThermalHal20Wrapper(mWrapperCallback); halConnected = mHalWrapper.connectToHal(); } if (!halConnected) { mHalWrapper = new ThermalHal11Wrapper(this::onTemperatureChangedCallback); mHalWrapper = new ThermalHal11Wrapper(mWrapperCallback); halConnected = mHalWrapper.connectToHal(); } if (!halConnected) { mHalWrapper = new ThermalHal10Wrapper(this::onTemperatureChangedCallback); mHalWrapper = new ThermalHal10Wrapper(mWrapperCallback); halConnected = mHalWrapper.connectToHal(); } if (!halConnected) { Loading @@ -200,7 +226,7 @@ public class ThermalManagerService extends SystemService { onTemperatureChanged(temperatures.get(i), false); } onTemperatureMapChangedLocked(); mTemperatureWatcher.updateThresholds(); mTemperatureWatcher.getAndUpdateThresholds(); mHalReady.set(true); } } Loading Loading @@ -335,16 +361,6 @@ public class ThermalManagerService extends SystemService { } } /* HwBinder callback **/ private void onTemperatureChangedCallback(Temperature temperature) { final long token = Binder.clearCallingIdentity(); try { onTemperatureChanged(temperature, true); } finally { Binder.restoreCallingIdentity(token); } } private void registerStatsCallbacks() { final StatsManager statsManager = mContext.getSystemService(StatsManager.class); if (statsManager != null) { Loading Loading @@ -924,19 +940,19 @@ public class ThermalManagerService extends SystemService { /** Lock to protect HAL handle. */ protected final Object mHalLock = new Object(); @FunctionalInterface interface TemperatureChangedCallback { void onValues(Temperature temperature); interface WrapperThermalChangedCallback { void onTemperatureChanged(Temperature temperature); void onThresholdChanged(TemperatureThreshold threshold); } /** Temperature callback. */ protected TemperatureChangedCallback mCallback; protected WrapperThermalChangedCallback mCallback; /** Cookie for matching the right end point. */ protected static final int THERMAL_HAL_DEATH_COOKIE = 5612; @VisibleForTesting protected void setCallback(TemperatureChangedCallback cb) { protected void setCallback(WrapperThermalChangedCallback cb) { mCallback = cb; } Loading @@ -959,7 +975,7 @@ public class ThermalManagerService extends SystemService { List<Temperature> temperatures = getCurrentTemperatures(false, 0); final int count = temperatures.size(); for (int i = 0; i < count; i++) { mCallback.onValues(temperatures.get(i)); mCallback.onTemperatureChanged(temperatures.get(i)); } } } Loading @@ -985,31 +1001,42 @@ public class ThermalManagerService extends SystemService { private IThermal mInstance = null; /** Callback for Thermal HAL AIDL. */ private final IThermalChangedCallback mThermalChangedCallback = private final IThermalChangedCallback mThermalCallbackAidl = new IThermalChangedCallback.Stub() { @Override public void notifyThrottling( android.hardware.thermal.Temperature temperature) throws RemoteException { @Override public void notifyThrottling( android.hardware.thermal.Temperature temperature) { Temperature svcTemperature = new Temperature(temperature.value, temperature.type, temperature.name, temperature.throttlingStatus); final long token = Binder.clearCallingIdentity(); try { mCallback.onValues(svcTemperature); mCallback.onTemperatureChanged(svcTemperature); } finally { Binder.restoreCallingIdentity(token); } } @Override public int getInterfaceVersion() throws RemoteException { @Override public void notifyThresholdChanged(TemperatureThreshold threshold) { if (Flags.allowThermalThresholdsCallback()) { if (threshold.type == TemperatureType.SKIN) { mCallback.onThresholdChanged(threshold); } } } @Override public int getInterfaceVersion() throws RemoteException { return this.VERSION; } @Override public String getInterfaceHash() throws RemoteException { @Override public String getInterfaceHash() throws RemoteException { return this.HASH; } }; ThermalHalAidlWrapper(TemperatureChangedCallback callback) { ThermalHalAidlWrapper(WrapperThermalChangedCallback callback) { mCallback = callback; } Loading Loading @@ -1153,7 +1180,7 @@ public class ThermalManagerService extends SystemService { @VisibleForTesting void registerThermalChangedCallback() { try { mInstance.registerThermalChangedCallback(mThermalChangedCallback); mInstance.registerThermalChangedCallback(mThermalCallbackAidl); } catch (IllegalArgumentException | IllegalStateException e) { Slog.e(TAG, "Couldn't registerThermalChangedCallback due to invalid status", e); Loading Loading @@ -1185,7 +1212,7 @@ public class ThermalManagerService extends SystemService { @GuardedBy("mHalLock") private android.hardware.thermal.V1_0.IThermal mThermalHal10 = null; ThermalHal10Wrapper(TemperatureChangedCallback callback) { ThermalHal10Wrapper(WrapperThermalChangedCallback callback) { mCallback = callback; } Loading Loading @@ -1317,14 +1344,14 @@ public class ThermalManagerService extends SystemService { : Temperature.THROTTLING_NONE); final long token = Binder.clearCallingIdentity(); try { mCallback.onValues(thermalSvcTemp); mCallback.onTemperatureChanged(thermalSvcTemp); } finally { Binder.restoreCallingIdentity(token); } } }; ThermalHal11Wrapper(TemperatureChangedCallback callback) { ThermalHal11Wrapper(WrapperThermalChangedCallback callback) { mCallback = callback; } Loading Loading @@ -1455,14 +1482,14 @@ public class ThermalManagerService extends SystemService { temperature.throttlingStatus); final long token = Binder.clearCallingIdentity(); try { mCallback.onValues(thermalSvcTemp); mCallback.onTemperatureChanged(thermalSvcTemp); } finally { Binder.restoreCallingIdentity(token); } } }; ThermalHal20Wrapper(TemperatureChangedCallback callback) { ThermalHal20Wrapper(WrapperThermalChangedCallback callback) { mCallback = callback; } Loading Loading @@ -1627,47 +1654,51 @@ public class ThermalManagerService extends SystemService { @VisibleForTesting long mInactivityThresholdMillis = INACTIVITY_THRESHOLD_MILLIS; void updateThresholds() { void getAndUpdateThresholds() { List<TemperatureThreshold> thresholds = mHalWrapper.getTemperatureThresholds(true, Temperature.TYPE_SKIN); synchronized (mSamples) { if (Flags.allowThermalHeadroomThresholds()) { Arrays.fill(mHeadroomThresholds, Float.NaN); } for (int t = 0; t < thresholds.size(); ++t) { TemperatureThreshold threshold = thresholds.get(t); for (final TemperatureThreshold threshold : thresholds) { updateTemperatureThresholdLocked(threshold, false); } } } // For an older device with multiple SKIN sensors, we will set a severity's headroom // threshold based on the minimum value of all as a workaround, unless override. @GuardedBy("mSamples") void updateTemperatureThresholdLocked(TemperatureThreshold threshold, boolean override) { if (threshold.hotThrottlingThresholds.length <= ThrottlingSeverity.SEVERE) { continue; return; } float severeThreshold = threshold.hotThrottlingThresholds[ThrottlingSeverity.SEVERE]; if (!Float.isNaN(severeThreshold)) { if (Float.isNaN(severeThreshold)) { return; } mSevereThresholds.put(threshold.name, severeThreshold); if (Flags.allowThermalHeadroomThresholds()) { if (!Flags.allowThermalHeadroomThresholds()) { return; } if (override) { Arrays.fill(mHeadroomThresholds, Float.NaN); } for (int severity = ThrottlingSeverity.LIGHT; severity <= ThrottlingSeverity.SHUTDOWN; severity++) { if (threshold.hotThrottlingThresholds.length > severity) { updateHeadroomThreshold(severity, threshold.hotThrottlingThresholds[severity], severeThreshold); } } } } } } float t = threshold.hotThrottlingThresholds[severity]; if (Float.isNaN(t)) { continue; } // For an older device with multiple SKIN sensors, we will set a severity's headroom // threshold based on the minimum value of all as a workaround. void updateHeadroomThreshold(int severity, float threshold, float severeThreshold) { if (!Float.isNaN(threshold)) { synchronized (mSamples) { if (severity == ThrottlingSeverity.SEVERE) { mHeadroomThresholds[severity] = 1.0f; return; continue; } float headroom = normalizeTemperature(threshold, severeThreshold); float headroom = normalizeTemperature(t, severeThreshold); if (Float.isNaN(mHeadroomThresholds[severity])) { mHeadroomThresholds[severity] = headroom; } else { Loading @@ -1677,6 +1708,7 @@ public class ThermalManagerService extends SystemService { } } } } private static final int RING_BUFFER_SIZE = 30; Loading services/core/jni/Android.bp +1 −1 Original line number Diff line number Diff line Loading @@ -191,7 +191,7 @@ cc_defaults { "android.hardware.power.stats@1.0", "android.hardware.power.stats-V1-ndk", "android.hardware.thermal@1.0", "android.hardware.thermal-V2-ndk", "android.hardware.thermal-V3-ndk", "android.hardware.tv.input@1.0", "android.hardware.tv.input-V2-ndk", "android.hardware.vibrator-V3-ndk", Loading services/tests/mockingservicestests/src/com/android/server/power/ThermalManagerServiceMockingTest.java +76 −13 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.server.power; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; Loading @@ -29,10 +30,16 @@ import android.hardware.thermal.TemperatureType; import android.hardware.thermal.ThrottlingSeverity; import android.os.Binder; import android.os.CoolingDevice; import android.os.Flags; import android.os.RemoteException; import android.os.Temperature; import android.platform.test.annotations.DisableFlags; import android.platform.test.annotations.EnableFlags; import android.platform.test.flag.junit.SetFlagsRule; import org.junit.Before; import org.junit.ClassRule; import org.junit.Rule; import org.junit.Test; import org.mockito.ArgumentCaptor; import org.mockito.Captor; Loading @@ -40,16 +47,36 @@ import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import java.util.Arrays; import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; public class ThermalManagerServiceMockingTest { @Mock private IThermal mAidlHalMock; @ClassRule public static final SetFlagsRule.ClassRule mSetFlagsClassRule = new SetFlagsRule.ClassRule(); @Rule public final SetFlagsRule mSetFlagsRule = mSetFlagsClassRule.createSetFlagsRule(); @Mock private IThermal mAidlHalMock; private Binder mAidlBinder = new Binder(); private CompletableFuture<Temperature> mTemperatureFuture; private ThermalManagerService.ThermalHalWrapper.TemperatureChangedCallback mTemperatureCallback; private CompletableFuture<TemperatureThreshold> mThresholdFuture; private ThermalManagerService.ThermalHalWrapper.WrapperThermalChangedCallback mTemperatureCallback = new ThermalManagerService.ThermalHalWrapper.WrapperThermalChangedCallback() { @Override public void onTemperatureChanged(Temperature temperature) { mTemperatureFuture.complete(temperature); } @Override public void onThresholdChanged(TemperatureThreshold threshold) { mThresholdFuture.complete(threshold); } }; private ThermalManagerService.ThermalHalAidlWrapper mAidlWrapper; @Captor ArgumentCaptor<IThermalChangedCallback> mAidlCallbackCaptor; Loading @@ -60,27 +87,63 @@ public class ThermalManagerServiceMockingTest { Mockito.when(mAidlHalMock.asBinder()).thenReturn(mAidlBinder); mAidlBinder.attachInterface(mAidlHalMock, IThermal.class.getName()); mTemperatureFuture = new CompletableFuture<>(); mTemperatureCallback = temperature -> mTemperatureFuture.complete(temperature); mThresholdFuture = new CompletableFuture<>(); mAidlWrapper = new ThermalManagerService.ThermalHalAidlWrapper(mTemperatureCallback); mAidlWrapper.initProxyAndRegisterCallback(mAidlBinder); } @Test @EnableFlags({Flags.FLAG_ALLOW_THERMAL_THRESHOLDS_CALLBACK}) public void setCallback_aidl() throws Exception { Mockito.verify(mAidlHalMock, Mockito.times(1)).registerThermalChangedCallback( mAidlCallbackCaptor.capture()); android.hardware.thermal.Temperature halT = android.hardware.thermal.Temperature halTemperature = new android.hardware.thermal.Temperature(); halT.type = TemperatureType.SOC; halT.name = "test"; halT.throttlingStatus = ThrottlingSeverity.SHUTDOWN; halT.value = 99.0f; mAidlCallbackCaptor.getValue().notifyThrottling(halT); halTemperature.type = TemperatureType.SOC; halTemperature.name = "test"; halTemperature.throttlingStatus = ThrottlingSeverity.SHUTDOWN; halTemperature.value = 99.0f; android.hardware.thermal.TemperatureThreshold halThreshold = new android.hardware.thermal.TemperatureThreshold(); halThreshold.type = TemperatureType.SKIN; halThreshold.name = "test"; halThreshold.hotThrottlingThresholds = new float[ThrottlingSeverity.SHUTDOWN + 1]; Arrays.fill(halThreshold.hotThrottlingThresholds, Float.NaN); halThreshold.hotThrottlingThresholds[ThrottlingSeverity.SEVERE] = 44.0f; mAidlCallbackCaptor.getValue().notifyThrottling(halTemperature); mAidlCallbackCaptor.getValue().notifyThresholdChanged(halThreshold); Temperature temperature = mTemperatureFuture.get(100, TimeUnit.MILLISECONDS); assertEquals(halT.name, temperature.getName()); assertEquals(halT.type, temperature.getType()); assertEquals(halT.value, temperature.getValue(), 0.1f); assertEquals(halT.throttlingStatus, temperature.getStatus()); assertEquals(halTemperature.name, temperature.getName()); assertEquals(halTemperature.type, temperature.getType()); assertEquals(halTemperature.value, temperature.getValue(), 0.1f); assertEquals(halTemperature.throttlingStatus, temperature.getStatus()); TemperatureThreshold threshold = mThresholdFuture.get(100, TimeUnit.MILLISECONDS); assertEquals(halThreshold.name, threshold.name); assertEquals(halThreshold.type, threshold.type); assertArrayEquals(halThreshold.hotThrottlingThresholds, threshold.hotThrottlingThresholds, 0.01f); } @Test @DisableFlags({Flags.FLAG_ALLOW_THERMAL_THRESHOLDS_CALLBACK}) public void setCallback_aidl_allow_thermal_thresholds_callback_false() throws Exception { Mockito.verify(mAidlHalMock, Mockito.times(1)).registerThermalChangedCallback( mAidlCallbackCaptor.capture()); android.hardware.thermal.TemperatureThreshold halThreshold = new android.hardware.thermal.TemperatureThreshold(); halThreshold.type = TemperatureType.SOC; halThreshold.name = "test"; halThreshold.hotThrottlingThresholds = new float[ThrottlingSeverity.SHUTDOWN + 1]; Arrays.fill(halThreshold.hotThrottlingThresholds, Float.NaN); halThreshold.hotThrottlingThresholds[ThrottlingSeverity.SEVERE] = 44.0f; mAidlCallbackCaptor.getValue().notifyThresholdChanged(halThreshold); Thread.sleep(1000); assertFalse(mThresholdFuture.isDone()); } @Test Loading Loading
Android.bp +1 −1 Original line number Diff line number Diff line Loading @@ -109,7 +109,7 @@ filegroup { ":android.hardware.radio.voice-V3-java-source", ":android.hardware.security.keymint-V3-java-source", ":android.hardware.security.secureclock-V1-java-source", ":android.hardware.thermal-V2-java-source", ":android.hardware.thermal-V3-java-source", ":android.hardware.tv.tuner-V3-java-source", ":android.security.apc-java-source", ":android.security.authorization-java-source", Loading
core/java/android/os/flags.aconfig +8 −0 Original line number Diff line number Diff line Loading @@ -90,6 +90,14 @@ flag { bug: "288119641" } flag { name: "allow_thermal_thresholds_callback" is_exported: true namespace: "game" description: "Enable thermal threshold callback" bug: "360486877" } flag { name: "android_os_build_vanilla_ice_cream" is_exported: true Loading
services/core/java/com/android/server/power/ThermalManagerService.java +107 −75 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ import android.content.Context; import android.hardware.thermal.IThermal; import android.hardware.thermal.IThermalChangedCallback; import android.hardware.thermal.TemperatureThreshold; import android.hardware.thermal.TemperatureType; import android.hardware.thermal.ThrottlingSeverity; import android.hardware.thermal.V1_0.ThermalStatus; import android.hardware.thermal.V1_0.ThermalStatusCode; Loading Loading @@ -134,6 +135,31 @@ public class ThermalManagerService extends SystemService { @VisibleForTesting final TemperatureWatcher mTemperatureWatcher = new TemperatureWatcher(); private final ThermalHalWrapper.WrapperThermalChangedCallback mWrapperCallback = new ThermalHalWrapper.WrapperThermalChangedCallback() { @Override public void onTemperatureChanged(Temperature temperature) { final long token = Binder.clearCallingIdentity(); try { ThermalManagerService.this.onTemperatureChanged(temperature, true); } finally { Binder.restoreCallingIdentity(token); } } @Override public void onThresholdChanged(TemperatureThreshold threshold) { final long token = Binder.clearCallingIdentity(); try { synchronized (mTemperatureWatcher.mSamples) { mTemperatureWatcher.updateTemperatureThresholdLocked(threshold, true); } } finally { Binder.restoreCallingIdentity(token); } } }; private final Context mContext; public ThermalManagerService(Context context) { Loading @@ -146,7 +172,7 @@ public class ThermalManagerService extends SystemService { mContext = context; mHalWrapper = halWrapper; if (halWrapper != null) { halWrapper.setCallback(this::onTemperatureChangedCallback); halWrapper.setCallback(mWrapperCallback); } mStatus = Temperature.THROTTLING_NONE; } Loading @@ -171,19 +197,19 @@ public class ThermalManagerService extends SystemService { // Connect to HAL and post to listeners. boolean halConnected = (mHalWrapper != null); if (!halConnected) { mHalWrapper = new ThermalHalAidlWrapper(this::onTemperatureChangedCallback); mHalWrapper = new ThermalHalAidlWrapper(mWrapperCallback); halConnected = mHalWrapper.connectToHal(); } if (!halConnected) { mHalWrapper = new ThermalHal20Wrapper(this::onTemperatureChangedCallback); mHalWrapper = new ThermalHal20Wrapper(mWrapperCallback); halConnected = mHalWrapper.connectToHal(); } if (!halConnected) { mHalWrapper = new ThermalHal11Wrapper(this::onTemperatureChangedCallback); mHalWrapper = new ThermalHal11Wrapper(mWrapperCallback); halConnected = mHalWrapper.connectToHal(); } if (!halConnected) { mHalWrapper = new ThermalHal10Wrapper(this::onTemperatureChangedCallback); mHalWrapper = new ThermalHal10Wrapper(mWrapperCallback); halConnected = mHalWrapper.connectToHal(); } if (!halConnected) { Loading @@ -200,7 +226,7 @@ public class ThermalManagerService extends SystemService { onTemperatureChanged(temperatures.get(i), false); } onTemperatureMapChangedLocked(); mTemperatureWatcher.updateThresholds(); mTemperatureWatcher.getAndUpdateThresholds(); mHalReady.set(true); } } Loading Loading @@ -335,16 +361,6 @@ public class ThermalManagerService extends SystemService { } } /* HwBinder callback **/ private void onTemperatureChangedCallback(Temperature temperature) { final long token = Binder.clearCallingIdentity(); try { onTemperatureChanged(temperature, true); } finally { Binder.restoreCallingIdentity(token); } } private void registerStatsCallbacks() { final StatsManager statsManager = mContext.getSystemService(StatsManager.class); if (statsManager != null) { Loading Loading @@ -924,19 +940,19 @@ public class ThermalManagerService extends SystemService { /** Lock to protect HAL handle. */ protected final Object mHalLock = new Object(); @FunctionalInterface interface TemperatureChangedCallback { void onValues(Temperature temperature); interface WrapperThermalChangedCallback { void onTemperatureChanged(Temperature temperature); void onThresholdChanged(TemperatureThreshold threshold); } /** Temperature callback. */ protected TemperatureChangedCallback mCallback; protected WrapperThermalChangedCallback mCallback; /** Cookie for matching the right end point. */ protected static final int THERMAL_HAL_DEATH_COOKIE = 5612; @VisibleForTesting protected void setCallback(TemperatureChangedCallback cb) { protected void setCallback(WrapperThermalChangedCallback cb) { mCallback = cb; } Loading @@ -959,7 +975,7 @@ public class ThermalManagerService extends SystemService { List<Temperature> temperatures = getCurrentTemperatures(false, 0); final int count = temperatures.size(); for (int i = 0; i < count; i++) { mCallback.onValues(temperatures.get(i)); mCallback.onTemperatureChanged(temperatures.get(i)); } } } Loading @@ -985,31 +1001,42 @@ public class ThermalManagerService extends SystemService { private IThermal mInstance = null; /** Callback for Thermal HAL AIDL. */ private final IThermalChangedCallback mThermalChangedCallback = private final IThermalChangedCallback mThermalCallbackAidl = new IThermalChangedCallback.Stub() { @Override public void notifyThrottling( android.hardware.thermal.Temperature temperature) throws RemoteException { @Override public void notifyThrottling( android.hardware.thermal.Temperature temperature) { Temperature svcTemperature = new Temperature(temperature.value, temperature.type, temperature.name, temperature.throttlingStatus); final long token = Binder.clearCallingIdentity(); try { mCallback.onValues(svcTemperature); mCallback.onTemperatureChanged(svcTemperature); } finally { Binder.restoreCallingIdentity(token); } } @Override public int getInterfaceVersion() throws RemoteException { @Override public void notifyThresholdChanged(TemperatureThreshold threshold) { if (Flags.allowThermalThresholdsCallback()) { if (threshold.type == TemperatureType.SKIN) { mCallback.onThresholdChanged(threshold); } } } @Override public int getInterfaceVersion() throws RemoteException { return this.VERSION; } @Override public String getInterfaceHash() throws RemoteException { @Override public String getInterfaceHash() throws RemoteException { return this.HASH; } }; ThermalHalAidlWrapper(TemperatureChangedCallback callback) { ThermalHalAidlWrapper(WrapperThermalChangedCallback callback) { mCallback = callback; } Loading Loading @@ -1153,7 +1180,7 @@ public class ThermalManagerService extends SystemService { @VisibleForTesting void registerThermalChangedCallback() { try { mInstance.registerThermalChangedCallback(mThermalChangedCallback); mInstance.registerThermalChangedCallback(mThermalCallbackAidl); } catch (IllegalArgumentException | IllegalStateException e) { Slog.e(TAG, "Couldn't registerThermalChangedCallback due to invalid status", e); Loading Loading @@ -1185,7 +1212,7 @@ public class ThermalManagerService extends SystemService { @GuardedBy("mHalLock") private android.hardware.thermal.V1_0.IThermal mThermalHal10 = null; ThermalHal10Wrapper(TemperatureChangedCallback callback) { ThermalHal10Wrapper(WrapperThermalChangedCallback callback) { mCallback = callback; } Loading Loading @@ -1317,14 +1344,14 @@ public class ThermalManagerService extends SystemService { : Temperature.THROTTLING_NONE); final long token = Binder.clearCallingIdentity(); try { mCallback.onValues(thermalSvcTemp); mCallback.onTemperatureChanged(thermalSvcTemp); } finally { Binder.restoreCallingIdentity(token); } } }; ThermalHal11Wrapper(TemperatureChangedCallback callback) { ThermalHal11Wrapper(WrapperThermalChangedCallback callback) { mCallback = callback; } Loading Loading @@ -1455,14 +1482,14 @@ public class ThermalManagerService extends SystemService { temperature.throttlingStatus); final long token = Binder.clearCallingIdentity(); try { mCallback.onValues(thermalSvcTemp); mCallback.onTemperatureChanged(thermalSvcTemp); } finally { Binder.restoreCallingIdentity(token); } } }; ThermalHal20Wrapper(TemperatureChangedCallback callback) { ThermalHal20Wrapper(WrapperThermalChangedCallback callback) { mCallback = callback; } Loading Loading @@ -1627,47 +1654,51 @@ public class ThermalManagerService extends SystemService { @VisibleForTesting long mInactivityThresholdMillis = INACTIVITY_THRESHOLD_MILLIS; void updateThresholds() { void getAndUpdateThresholds() { List<TemperatureThreshold> thresholds = mHalWrapper.getTemperatureThresholds(true, Temperature.TYPE_SKIN); synchronized (mSamples) { if (Flags.allowThermalHeadroomThresholds()) { Arrays.fill(mHeadroomThresholds, Float.NaN); } for (int t = 0; t < thresholds.size(); ++t) { TemperatureThreshold threshold = thresholds.get(t); for (final TemperatureThreshold threshold : thresholds) { updateTemperatureThresholdLocked(threshold, false); } } } // For an older device with multiple SKIN sensors, we will set a severity's headroom // threshold based on the minimum value of all as a workaround, unless override. @GuardedBy("mSamples") void updateTemperatureThresholdLocked(TemperatureThreshold threshold, boolean override) { if (threshold.hotThrottlingThresholds.length <= ThrottlingSeverity.SEVERE) { continue; return; } float severeThreshold = threshold.hotThrottlingThresholds[ThrottlingSeverity.SEVERE]; if (!Float.isNaN(severeThreshold)) { if (Float.isNaN(severeThreshold)) { return; } mSevereThresholds.put(threshold.name, severeThreshold); if (Flags.allowThermalHeadroomThresholds()) { if (!Flags.allowThermalHeadroomThresholds()) { return; } if (override) { Arrays.fill(mHeadroomThresholds, Float.NaN); } for (int severity = ThrottlingSeverity.LIGHT; severity <= ThrottlingSeverity.SHUTDOWN; severity++) { if (threshold.hotThrottlingThresholds.length > severity) { updateHeadroomThreshold(severity, threshold.hotThrottlingThresholds[severity], severeThreshold); } } } } } } float t = threshold.hotThrottlingThresholds[severity]; if (Float.isNaN(t)) { continue; } // For an older device with multiple SKIN sensors, we will set a severity's headroom // threshold based on the minimum value of all as a workaround. void updateHeadroomThreshold(int severity, float threshold, float severeThreshold) { if (!Float.isNaN(threshold)) { synchronized (mSamples) { if (severity == ThrottlingSeverity.SEVERE) { mHeadroomThresholds[severity] = 1.0f; return; continue; } float headroom = normalizeTemperature(threshold, severeThreshold); float headroom = normalizeTemperature(t, severeThreshold); if (Float.isNaN(mHeadroomThresholds[severity])) { mHeadroomThresholds[severity] = headroom; } else { Loading @@ -1677,6 +1708,7 @@ public class ThermalManagerService extends SystemService { } } } } private static final int RING_BUFFER_SIZE = 30; Loading
services/core/jni/Android.bp +1 −1 Original line number Diff line number Diff line Loading @@ -191,7 +191,7 @@ cc_defaults { "android.hardware.power.stats@1.0", "android.hardware.power.stats-V1-ndk", "android.hardware.thermal@1.0", "android.hardware.thermal-V2-ndk", "android.hardware.thermal-V3-ndk", "android.hardware.tv.input@1.0", "android.hardware.tv.input-V2-ndk", "android.hardware.vibrator-V3-ndk", Loading
services/tests/mockingservicestests/src/com/android/server/power/ThermalManagerServiceMockingTest.java +76 −13 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.server.power; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; Loading @@ -29,10 +30,16 @@ import android.hardware.thermal.TemperatureType; import android.hardware.thermal.ThrottlingSeverity; import android.os.Binder; import android.os.CoolingDevice; import android.os.Flags; import android.os.RemoteException; import android.os.Temperature; import android.platform.test.annotations.DisableFlags; import android.platform.test.annotations.EnableFlags; import android.platform.test.flag.junit.SetFlagsRule; import org.junit.Before; import org.junit.ClassRule; import org.junit.Rule; import org.junit.Test; import org.mockito.ArgumentCaptor; import org.mockito.Captor; Loading @@ -40,16 +47,36 @@ import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import java.util.Arrays; import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; public class ThermalManagerServiceMockingTest { @Mock private IThermal mAidlHalMock; @ClassRule public static final SetFlagsRule.ClassRule mSetFlagsClassRule = new SetFlagsRule.ClassRule(); @Rule public final SetFlagsRule mSetFlagsRule = mSetFlagsClassRule.createSetFlagsRule(); @Mock private IThermal mAidlHalMock; private Binder mAidlBinder = new Binder(); private CompletableFuture<Temperature> mTemperatureFuture; private ThermalManagerService.ThermalHalWrapper.TemperatureChangedCallback mTemperatureCallback; private CompletableFuture<TemperatureThreshold> mThresholdFuture; private ThermalManagerService.ThermalHalWrapper.WrapperThermalChangedCallback mTemperatureCallback = new ThermalManagerService.ThermalHalWrapper.WrapperThermalChangedCallback() { @Override public void onTemperatureChanged(Temperature temperature) { mTemperatureFuture.complete(temperature); } @Override public void onThresholdChanged(TemperatureThreshold threshold) { mThresholdFuture.complete(threshold); } }; private ThermalManagerService.ThermalHalAidlWrapper mAidlWrapper; @Captor ArgumentCaptor<IThermalChangedCallback> mAidlCallbackCaptor; Loading @@ -60,27 +87,63 @@ public class ThermalManagerServiceMockingTest { Mockito.when(mAidlHalMock.asBinder()).thenReturn(mAidlBinder); mAidlBinder.attachInterface(mAidlHalMock, IThermal.class.getName()); mTemperatureFuture = new CompletableFuture<>(); mTemperatureCallback = temperature -> mTemperatureFuture.complete(temperature); mThresholdFuture = new CompletableFuture<>(); mAidlWrapper = new ThermalManagerService.ThermalHalAidlWrapper(mTemperatureCallback); mAidlWrapper.initProxyAndRegisterCallback(mAidlBinder); } @Test @EnableFlags({Flags.FLAG_ALLOW_THERMAL_THRESHOLDS_CALLBACK}) public void setCallback_aidl() throws Exception { Mockito.verify(mAidlHalMock, Mockito.times(1)).registerThermalChangedCallback( mAidlCallbackCaptor.capture()); android.hardware.thermal.Temperature halT = android.hardware.thermal.Temperature halTemperature = new android.hardware.thermal.Temperature(); halT.type = TemperatureType.SOC; halT.name = "test"; halT.throttlingStatus = ThrottlingSeverity.SHUTDOWN; halT.value = 99.0f; mAidlCallbackCaptor.getValue().notifyThrottling(halT); halTemperature.type = TemperatureType.SOC; halTemperature.name = "test"; halTemperature.throttlingStatus = ThrottlingSeverity.SHUTDOWN; halTemperature.value = 99.0f; android.hardware.thermal.TemperatureThreshold halThreshold = new android.hardware.thermal.TemperatureThreshold(); halThreshold.type = TemperatureType.SKIN; halThreshold.name = "test"; halThreshold.hotThrottlingThresholds = new float[ThrottlingSeverity.SHUTDOWN + 1]; Arrays.fill(halThreshold.hotThrottlingThresholds, Float.NaN); halThreshold.hotThrottlingThresholds[ThrottlingSeverity.SEVERE] = 44.0f; mAidlCallbackCaptor.getValue().notifyThrottling(halTemperature); mAidlCallbackCaptor.getValue().notifyThresholdChanged(halThreshold); Temperature temperature = mTemperatureFuture.get(100, TimeUnit.MILLISECONDS); assertEquals(halT.name, temperature.getName()); assertEquals(halT.type, temperature.getType()); assertEquals(halT.value, temperature.getValue(), 0.1f); assertEquals(halT.throttlingStatus, temperature.getStatus()); assertEquals(halTemperature.name, temperature.getName()); assertEquals(halTemperature.type, temperature.getType()); assertEquals(halTemperature.value, temperature.getValue(), 0.1f); assertEquals(halTemperature.throttlingStatus, temperature.getStatus()); TemperatureThreshold threshold = mThresholdFuture.get(100, TimeUnit.MILLISECONDS); assertEquals(halThreshold.name, threshold.name); assertEquals(halThreshold.type, threshold.type); assertArrayEquals(halThreshold.hotThrottlingThresholds, threshold.hotThrottlingThresholds, 0.01f); } @Test @DisableFlags({Flags.FLAG_ALLOW_THERMAL_THRESHOLDS_CALLBACK}) public void setCallback_aidl_allow_thermal_thresholds_callback_false() throws Exception { Mockito.verify(mAidlHalMock, Mockito.times(1)).registerThermalChangedCallback( mAidlCallbackCaptor.capture()); android.hardware.thermal.TemperatureThreshold halThreshold = new android.hardware.thermal.TemperatureThreshold(); halThreshold.type = TemperatureType.SOC; halThreshold.name = "test"; halThreshold.hotThrottlingThresholds = new float[ThrottlingSeverity.SHUTDOWN + 1]; Arrays.fill(halThreshold.hotThrottlingThresholds, Float.NaN); halThreshold.hotThrottlingThresholds[ThrottlingSeverity.SEVERE] = 44.0f; mAidlCallbackCaptor.getValue().notifyThresholdChanged(halThreshold); Thread.sleep(1000); assertFalse(mThresholdFuture.isDone()); } @Test Loading