summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Dmitri Plotnikov <dplotnikov@google.com> 2024-08-19 12:53:40 -0700
committer Dmitri Plotnikov <dplotnikov@google.com> 2024-08-19 15:11:58 -0700
commit2fc0463bc6f7b2956ab5d47304b6b65128850a56 (patch)
tree5d915068ee182320120e89af007d07467144ae54
parentf28c6040e47e7682141a260982f5bc2028be2072 (diff)
Do not crash system server on powerstats HAL errors
Bug: 338340054 Test: added an explicit exception and confirmed the fix Flag: EXEMPT_bugfix Change-Id: I7a4617a55fec9d2d7742ebe1746b1a717fddfcf6
-rw-r--r--services/core/java/com/android/server/powerstats/PowerStatsService.java34
-rw-r--r--services/tests/powerstatstests/src/com/android/server/powerstats/PowerStatsServiceTest.java39
2 files changed, 68 insertions, 5 deletions
diff --git a/services/core/java/com/android/server/powerstats/PowerStatsService.java b/services/core/java/com/android/server/powerstats/PowerStatsService.java
index 1ca267e99c95..89fa9b61b745 100644
--- a/services/core/java/com/android/server/powerstats/PowerStatsService.java
+++ b/services/core/java/com/android/server/powerstats/PowerStatsService.java
@@ -304,12 +304,22 @@ public class PowerStatsService extends SystemService {
@Override
public void onStart() {
if (getPowerStatsHal().isInitialized()) {
- mPowerStatsInternal = new LocalService();
- publishLocalService(PowerStatsInternal.class, mPowerStatsInternal);
+ publishLocalService(PowerStatsInternal.class, getPowerStatsInternal());
}
publishBinderService(Context.POWER_STATS_SERVICE, mService);
}
+ /**
+ * Returns the PowerStatsInternal associated with this service, maybe creating it if needed.
+ */
+ @VisibleForTesting
+ public PowerStatsInternal getPowerStatsInternal() {
+ if (mPowerStatsInternal == null) {
+ mPowerStatsInternal = new LocalService();
+ }
+ return mPowerStatsInternal;
+ }
+
private void onSystemServicesReady() {
mPullAtomCallback = mInjector.createStatsPullerImpl(mContext, mPowerStatsInternal);
mDeviceConfigListener.startListening();
@@ -456,7 +466,13 @@ public class PowerStatsService extends SystemService {
private void getEnergyConsumedAsync(CompletableFuture<EnergyConsumerResult[]> future,
int[] energyConsumerIds) {
- EnergyConsumerResult[] results = getPowerStatsHal().getEnergyConsumed(energyConsumerIds);
+ EnergyConsumerResult[] results;
+ try {
+ results = getPowerStatsHal().getEnergyConsumed(energyConsumerIds);
+ } catch (Exception e) {
+ future.completeExceptionally(e);
+ return;
+ }
// STOPSHIP(253292374): Remove once missing EnergyConsumer results issue is resolved.
EnergyConsumer[] energyConsumers = getEnergyConsumerInfo();
@@ -523,12 +539,20 @@ public class PowerStatsService extends SystemService {
private void getStateResidencyAsync(CompletableFuture<StateResidencyResult[]> future,
int[] powerEntityIds) {
- future.complete(getPowerStatsHal().getStateResidency(powerEntityIds));
+ try {
+ future.complete(getPowerStatsHal().getStateResidency(powerEntityIds));
+ } catch (Exception e) {
+ future.completeExceptionally(e);
+ }
}
private void readEnergyMeterAsync(CompletableFuture<EnergyMeasurement[]> future,
int[] channelIds) {
- future.complete(getPowerStatsHal().readEnergyMeter(channelIds));
+ try {
+ future.complete(getPowerStatsHal().readEnergyMeter(channelIds));
+ } catch (Exception e) {
+ future.completeExceptionally(e);
+ }
}
private static class PowerMonitorState {
diff --git a/services/tests/powerstatstests/src/com/android/server/powerstats/PowerStatsServiceTest.java b/services/tests/powerstatstests/src/com/android/server/powerstats/PowerStatsServiceTest.java
index 53e31438c560..115cdf6cee63 100644
--- a/services/tests/powerstatstests/src/com/android/server/powerstats/PowerStatsServiceTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/powerstats/PowerStatsServiceTest.java
@@ -74,6 +74,8 @@ import java.nio.file.Files;
import java.util.Arrays;
import java.util.Map;
import java.util.Random;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;
/**
@@ -221,6 +223,7 @@ public class PowerStatsServiceTest {
};
public static final class TestPowerStatsHALWrapper implements IPowerStatsHALWrapper {
+ public RuntimeException exception;
public EnergyConsumerResult[] energyConsumerResults;
public EnergyMeasurement[] energyMeasurements;
@@ -243,6 +246,9 @@ public class PowerStatsServiceTest {
@Override
public StateResidencyResult[] getStateResidency(int[] powerEntityIds) {
+ if (exception != null) {
+ throw exception;
+ }
StateResidencyResult[] stateResidencyResultList =
new StateResidencyResult[POWER_ENTITY_COUNT];
for (int i = 0; i < stateResidencyResultList.length; i++) {
@@ -294,6 +300,9 @@ public class PowerStatsServiceTest {
@Override
public EnergyConsumerResult[] getEnergyConsumed(int[] energyConsumerIds) {
+ if (exception != null) {
+ throw exception;
+ }
return energyConsumerResults;
}
@@ -322,6 +331,9 @@ public class PowerStatsServiceTest {
@Override
public EnergyMeasurement[] readEnergyMeter(int[] channelIds) {
+ if (exception != null) {
+ throw exception;
+ }
return energyMeasurements;
}
@@ -1222,4 +1234,31 @@ public class PowerStatsServiceTest {
assertThrows(NullPointerException.class, () -> iPowerStatsService.getPowerMonitorReadings(
new int[] {0}, null));
}
+
+ @Test
+ public void getEnergyConsumedAsync_halException() {
+ mPowerStatsHALWrapper.exception = new IllegalArgumentException();
+ CompletableFuture<EnergyConsumerResult[]> future =
+ mService.getPowerStatsInternal().getEnergyConsumedAsync(new int[]{1});
+ ExecutionException exception = assertThrows(ExecutionException.class, future::get);
+ assertThat(exception.getCause()).isInstanceOf(IllegalArgumentException.class);
+ }
+
+ @Test
+ public void getStateResidencyAsync_halException() {
+ mPowerStatsHALWrapper.exception = new IllegalArgumentException();
+ CompletableFuture<StateResidencyResult[]> future =
+ mService.getPowerStatsInternal().getStateResidencyAsync(new int[]{1});
+ ExecutionException exception = assertThrows(ExecutionException.class, future::get);
+ assertThat(exception.getCause()).isInstanceOf(IllegalArgumentException.class);
+ }
+
+ @Test
+ public void readEnergyMeterAsync_halException() {
+ mPowerStatsHALWrapper.exception = new IllegalArgumentException();
+ CompletableFuture<EnergyMeasurement[]> future =
+ mService.getPowerStatsInternal().readEnergyMeterAsync(new int[]{1});
+ ExecutionException exception = assertThrows(ExecutionException.class, future::get);
+ assertThat(exception.getCause()).isInstanceOf(IllegalArgumentException.class);
+ }
}