diff options
| author | 2024-08-19 12:53:40 -0700 | |
|---|---|---|
| committer | 2024-08-19 15:11:58 -0700 | |
| commit | 2fc0463bc6f7b2956ab5d47304b6b65128850a56 (patch) | |
| tree | 5d915068ee182320120e89af007d07467144ae54 | |
| parent | f28c6040e47e7682141a260982f5bc2028be2072 (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.java | 34 | ||||
| -rw-r--r-- | services/tests/powerstatstests/src/com/android/server/powerstats/PowerStatsServiceTest.java | 39 |
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); + } } |