OSDN Git Service

BatteryService: scheduleUpdate asynchronously
authorYifan Hong <elsk@google.com>
Fri, 16 Aug 2019 20:20:57 +0000 (13:20 -0700)
committerYifan Hong <elsk@google.com>
Fri, 16 Aug 2019 20:40:43 +0000 (13:40 -0700)
IBatteryPropertiesRegistrar.scheduleUpdate calls IHealth.update()
asynchronously.

BatteryStatsImpl calls scheduleUpdate while holding a lock, which
may lead to deadlocks if the remote process calls back to the
framework.

Fixes: 139503418
Test: monitor HealthScheduleUpdate trace points
Change-Id: I8168d7c4e4a0b1d31343360d2c7f6d36c7aa692a

services/core/java/com/android/server/BatteryService.java

index 3b78fda..9465617 100644 (file)
@@ -1227,14 +1227,21 @@ public final class BatteryService extends SystemService {
         }
         @Override
         public void scheduleUpdate() throws RemoteException {
-            traceBegin("HealthScheduleUpdate");
-            try {
-                IHealth service = mHealthServiceWrapper.getLastService();
-                if (service == null) throw new RemoteException("no health service");
-                service.update();
-            } finally {
-                traceEnd();
-            }
+            mHealthServiceWrapper.getHandlerThread().getThreadHandler().post(() -> {
+                traceBegin("HealthScheduleUpdate");
+                try {
+                    IHealth service = mHealthServiceWrapper.getLastService();
+                    if (service == null) {
+                        Slog.e(TAG, "no health service");
+                        return;
+                    }
+                    service.update();
+                } catch (RemoteException ex) {
+                    Slog.e(TAG, "Cannot call update on health HAL", ex);
+                } finally {
+                    traceEnd();
+                }
+            });
         }
     }
 
@@ -1311,7 +1318,7 @@ public final class BatteryService extends SystemService {
                 Arrays.asList(INSTANCE_VENDOR, INSTANCE_HEALTHD);
 
         private final IServiceNotification mNotification = new Notification();
-        private final HandlerThread mHandlerThread = new HandlerThread("HealthServiceRefresh");
+        private final HandlerThread mHandlerThread = new HandlerThread("HealthServiceHwbinder");
         // These variables are fixed after init.
         private Callback mCallback;
         private IHealthSupplier mHealthSupplier;