Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e3336d5c authored by Dmitri Plotnikov's avatar Dmitri Plotnikov Committed by Android (Google) Code Review
Browse files

Merge changes I55d25393,I5dcef0c5 into main

* changes:
  Introduce PowerStatsProcessor for Bluetooth
  Introduce PowerStatsCollector for Bluetooth
parents 4bbcccde c4dfcb6c
Loading
Loading
Loading
Loading
+18 −0
Original line number Diff line number Diff line
@@ -124,6 +124,7 @@ import com.android.server.power.stats.BatteryExternalStatsWorker;
import com.android.server.power.stats.BatteryStatsDumpHelperImpl;
import com.android.server.power.stats.BatteryStatsImpl;
import com.android.server.power.stats.BatteryUsageStatsProvider;
import com.android.server.power.stats.BluetoothPowerStatsProcessor;
import com.android.server.power.stats.CpuPowerStatsProcessor;
import com.android.server.power.stats.MobileRadioPowerStatsProcessor;
import com.android.server.power.stats.PhoneCallPowerStatsProcessor;
@@ -502,6 +503,17 @@ public final class BatteryStatsService extends IBatteryStats.Stub
                        AggregatedPowerStatsConfig.STATE_PROCESS_STATE)
                .setProcessor(
                        new WifiPowerStatsProcessor(mPowerProfile));

        config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_BLUETOOTH)
                .trackDeviceStates(
                        AggregatedPowerStatsConfig.STATE_POWER,
                        AggregatedPowerStatsConfig.STATE_SCREEN)
                .trackUidStates(
                        AggregatedPowerStatsConfig.STATE_POWER,
                        AggregatedPowerStatsConfig.STATE_SCREEN,
                        AggregatedPowerStatsConfig.STATE_PROCESS_STATE)
                .setProcessor(
                        new BluetoothPowerStatsProcessor(mPowerProfile));
        return config;
    }

@@ -563,6 +575,12 @@ public final class BatteryStatsService extends IBatteryStats.Stub
                BatteryConsumer.POWER_COMPONENT_WIFI,
                Flags.streamlinedConnectivityBatteryStats());

        mStats.setPowerStatsCollectorEnabled(BatteryConsumer.POWER_COMPONENT_BLUETOOTH,
                Flags.streamlinedConnectivityBatteryStats());
        mBatteryUsageStatsProvider.setPowerStatsExporterEnabled(
                BatteryConsumer.POWER_COMPONENT_BLUETOOTH,
                Flags.streamlinedConnectivityBatteryStats());

        mWorker.systemServicesReady();
        mStats.systemServicesReady(mContext);
        mCpuWakeupStats.systemServicesReady();
+33 −26
Original line number Diff line number Diff line
@@ -572,6 +572,12 @@ public class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStat
        }

        if ((updateFlags & BatteryStatsImpl.ExternalStatsSync.UPDATE_BT) != 0) {
            @SuppressWarnings("GuardedBy")
            PowerStatsCollector collector = mStats.getPowerStatsCollector(
                    BatteryConsumer.POWER_COMPONENT_BLUETOOTH);
            if (collector.isEnabled()) {
                collector.schedule();
            } else {
                // We were asked to fetch Bluetooth data.
                final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
                if (adapter != null) {
@@ -602,6 +608,7 @@ public class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStat
                    bluetoothReceiver = resultReceiver;
                }
            }
        }

        if ((updateFlags & BatteryStatsImpl.ExternalStatsSync.UPDATE_RADIO) != 0) {
            @SuppressWarnings("GuardedBy")
+81 −2
Original line number Diff line number Diff line
@@ -32,6 +32,8 @@ import android.app.ActivityManager;
import android.app.AlarmManager;
import android.app.usage.NetworkStatsManager;
import android.bluetooth.BluetoothActivityEnergyInfo;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothManager;
import android.bluetooth.UidTraffic;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
@@ -172,6 +174,7 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.Executor;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
@@ -294,6 +297,7 @@ public class BatteryStatsImpl extends BatteryStats {
    private final CpuPowerStatsCollector mCpuPowerStatsCollector;
    private final MobileRadioPowerStatsCollector mMobileRadioPowerStatsCollector;
    private final WifiPowerStatsCollector mWifiPowerStatsCollector;
    private final BluetoothPowerStatsCollector mBluetoothPowerStatsCollector;
    private final SparseBooleanArray mPowerStatsCollectorEnabled = new SparseBooleanArray();
    private final WifiPowerStatsCollector.WifiStatsRetriever mWifiStatsRetriever =
            new WifiPowerStatsCollector.WifiStatsRetriever() {
@@ -313,6 +317,38 @@ public class BatteryStatsImpl extends BatteryStats {
                }
            };
    private class BluetoothStatsRetrieverImpl implements
            BluetoothPowerStatsCollector.BluetoothStatsRetriever {
        private final BluetoothManager mBluetoothManager;
        BluetoothStatsRetrieverImpl(BluetoothManager bluetoothManager) {
            mBluetoothManager = bluetoothManager;
        }
        @Override
        public void retrieveBluetoothScanTimes(Callback callback) {
            synchronized (BatteryStatsImpl.this) {
                retrieveBluetoothScanTimesLocked(callback);
            }
        }
        @Override
        public boolean requestControllerActivityEnergyInfo(Executor executor,
                BluetoothAdapter.OnBluetoothActivityEnergyInfoCallback callback) {
            if (mBluetoothManager == null) {
                return false;
            }
            BluetoothAdapter adapter = mBluetoothManager.getAdapter();
            if (adapter == null) {
                return false;
            }
            adapter.requestControllerActivityEnergyInfo(executor, callback);
            return true;
        }
    }
    public LongSparseArray<SamplingTimer> getKernelMemoryStats() {
        return mKernelMemoryStats;
    }
@@ -1926,12 +1962,14 @@ public class BatteryStatsImpl extends BatteryStats {
    }
    private class PowerStatsCollectorInjector implements CpuPowerStatsCollector.Injector,
            MobileRadioPowerStatsCollector.Injector, WifiPowerStatsCollector.Injector {
            MobileRadioPowerStatsCollector.Injector, WifiPowerStatsCollector.Injector,
            BluetoothPowerStatsCollector.Injector {
        private PackageManager mPackageManager;
        private PowerStatsCollector.ConsumedEnergyRetriever mConsumedEnergyRetriever;
        private NetworkStatsManager mNetworkStatsManager;
        private TelephonyManager mTelephonyManager;
        private WifiManager mWifiManager;
        private BluetoothPowerStatsCollector.BluetoothStatsRetriever mBluetoothStatsRetriever;
        void setContext(Context context) {
            mPackageManager = context.getPackageManager();
@@ -1940,6 +1978,8 @@ public class BatteryStatsImpl extends BatteryStats {
            mNetworkStatsManager = context.getSystemService(NetworkStatsManager.class);
            mTelephonyManager = context.getSystemService(TelephonyManager.class);
            mWifiManager = context.getSystemService(WifiManager.class);
            mBluetoothStatsRetriever = new BluetoothStatsRetrieverImpl(
                    context.getSystemService(BluetoothManager.class));
        }
        @Override
@@ -2017,6 +2057,11 @@ public class BatteryStatsImpl extends BatteryStats {
            return mWifiManager;
        }
        @Override
        public BluetoothPowerStatsCollector.BluetoothStatsRetriever getBluetoothStatsRetriever() {
            return mBluetoothStatsRetriever;
        }
        @Override
        public LongSupplier getCallDurationSupplier() {
            return () -> mPhoneOnTimer.getTotalTimeLocked(mClock.elapsedRealtime() * 1000,
@@ -6774,6 +6819,24 @@ public class BatteryStatsImpl extends BatteryStats {
        }
    }
    private void retrieveBluetoothScanTimesLocked(
            BluetoothPowerStatsCollector.BluetoothStatsRetriever.Callback callback) {
        long elapsedTimeUs = mClock.elapsedRealtime() * 1000;
        for (int i = mUidStats.size() - 1; i >= 0; i--) {
            Uid uidStats = mUidStats.valueAt(i);
            if (uidStats.mBluetoothScanTimer == null) {
                continue;
            }
            long scanTimeUs = mBluetoothScanTimer.getTotalTimeLocked(elapsedTimeUs,
                    STATS_SINCE_CHARGED);
            if (scanTimeUs != 0) {
                int uid = mUidStats.keyAt(i);
                callback.onBluetoothScanTime(uid, (scanTimeUs + 500) / 1000);
            }
        }
    }
    @GuardedBy("this")
    private void noteWifiRadioApWakeupLocked(final long elapsedRealtimeMillis,
            final long uptimeMillis, int uid) {
@@ -11202,6 +11265,10 @@ public class BatteryStatsImpl extends BatteryStats {
        mWifiPowerStatsCollector = new WifiPowerStatsCollector(mPowerStatsCollectorInjector);
        mWifiPowerStatsCollector.addConsumer(this::recordPowerStats);
        mBluetoothPowerStatsCollector = new BluetoothPowerStatsCollector(
                mPowerStatsCollectorInjector);
        mBluetoothPowerStatsCollector.addConsumer(this::recordPowerStats);
        mStartCount++;
        initTimersAndCounters();
        mOnBattery = mOnBatteryInternal = false;
@@ -13146,6 +13213,10 @@ public class BatteryStatsImpl extends BatteryStats {
    @GuardedBy("this")
    public void updateBluetoothStateLocked(@Nullable final BluetoothActivityEnergyInfo info,
            final long consumedChargeUC, long elapsedRealtimeMs, long uptimeMs) {
        if (mBluetoothPowerStatsCollector.isEnabled()) {
            return;
        }
        if (DEBUG_ENERGY) {
            Slog.d(TAG, "Updating bluetooth stats: " + info);
        }
@@ -13153,6 +13224,7 @@ public class BatteryStatsImpl extends BatteryStats {
        if (info == null) {
            return;
        }
        if (!mOnBatteryInternal || mIgnoreNextExternalStats) {
            mLastBluetoothActivityInfo.set(info);
            return;
@@ -13187,7 +13259,6 @@ public class BatteryStatsImpl extends BatteryStats {
                (mGlobalEnergyConsumerStats != null
                        && mBluetoothPowerCalculator != null && consumedChargeUC > 0) ?
                        new SparseDoubleArray() : null;
        long totalScanTimeMs = 0;
        final int uidCount = mUidStats.size();
@@ -14616,6 +14687,10 @@ public class BatteryStatsImpl extends BatteryStats {
                mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_WIFI));
        mWifiPowerStatsCollector.schedule();
        mBluetoothPowerStatsCollector.setEnabled(
                mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_BLUETOOTH));
        mBluetoothPowerStatsCollector.schedule();
        mSystemReady = true;
    }
@@ -14632,6 +14707,8 @@ public class BatteryStatsImpl extends BatteryStats {
                return mMobileRadioPowerStatsCollector;
            case BatteryConsumer.POWER_COMPONENT_WIFI:
                return mWifiPowerStatsCollector;
            case BatteryConsumer.POWER_COMPONENT_BLUETOOTH:
                return mBluetoothPowerStatsCollector;
        }
        return null;
    }
@@ -16168,6 +16245,7 @@ public class BatteryStatsImpl extends BatteryStats {
        mCpuPowerStatsCollector.forceSchedule();
        mMobileRadioPowerStatsCollector.forceSchedule();
        mWifiPowerStatsCollector.forceSchedule();
        mBluetoothPowerStatsCollector.forceSchedule();
    }
    /**
@@ -16187,6 +16265,7 @@ public class BatteryStatsImpl extends BatteryStats {
        mCpuPowerStatsCollector.collectAndDump(pw);
        mMobileRadioPowerStatsCollector.collectAndDump(pw);
        mWifiPowerStatsCollector.collectAndDump(pw);
        mBluetoothPowerStatsCollector.collectAndDump(pw);
    }
    private final Runnable mWriteAsyncRunnable = () -> {
+3 −1
Original line number Diff line number Diff line
@@ -90,7 +90,9 @@ public class BatteryUsageStatsProvider {
                if (!mPowerStatsExporterEnabled.get(BatteryConsumer.POWER_COMPONENT_WIFI)) {
                    mPowerCalculators.add(new WifiPowerCalculator(mPowerProfile));
                }
                if (!mPowerStatsExporterEnabled.get(BatteryConsumer.POWER_COMPONENT_BLUETOOTH)) {
                    mPowerCalculators.add(new BluetoothPowerCalculator(mPowerProfile));
                }
                mPowerCalculators.add(new SensorPowerCalculator(
                        mContext.getSystemService(SensorManager.class)));
                mPowerCalculators.add(new GnssPowerCalculator(mPowerProfile));
+332 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 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.stats;

import android.bluetooth.BluetoothActivityEnergyInfo;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.UidTraffic;
import android.content.pm.PackageManager;
import android.hardware.power.stats.EnergyConsumerType;
import android.os.BatteryConsumer;
import android.os.Handler;
import android.os.PersistableBundle;
import android.util.Slog;
import android.util.SparseArray;

import com.android.internal.os.Clock;
import com.android.internal.os.PowerStats;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
import java.util.function.IntSupplier;

public class BluetoothPowerStatsCollector extends PowerStatsCollector {
    private static final String TAG = "BluetoothPowerStatsCollector";

    private static final long BLUETOOTH_ACTIVITY_REQUEST_TIMEOUT = 20000;

    private static final long ENERGY_UNSPECIFIED = -1;

    interface BluetoothStatsRetriever {
        interface Callback {
            void onBluetoothScanTime(int uid, long scanTimeMs);
        }

        void retrieveBluetoothScanTimes(Callback callback);

        boolean requestControllerActivityEnergyInfo(Executor executor,
                BluetoothAdapter.OnBluetoothActivityEnergyInfoCallback callback);
    }

    interface Injector {
        Handler getHandler();
        Clock getClock();
        PowerStatsUidResolver getUidResolver();
        long getPowerStatsCollectionThrottlePeriod(String powerComponentName);
        PackageManager getPackageManager();
        ConsumedEnergyRetriever getConsumedEnergyRetriever();
        IntSupplier getVoltageSupplier();
        BluetoothStatsRetriever getBluetoothStatsRetriever();
    }

    private final Injector mInjector;

    private BluetoothPowerStatsLayout mLayout;
    private boolean mIsInitialized;
    private PowerStats mPowerStats;
    private long[] mDeviceStats;
    private BluetoothStatsRetriever mBluetoothStatsRetriever;
    private ConsumedEnergyRetriever mConsumedEnergyRetriever;
    private IntSupplier mVoltageSupplier;
    private int[] mEnergyConsumerIds = new int[0];
    private long[] mLastConsumedEnergyUws;
    private int mLastVoltageMv;

    private long mLastRxTime;
    private long mLastTxTime;
    private long mLastIdleTime;

    private static class UidStats {
        public long rxCount;
        public long lastRxCount;
        public long txCount;
        public long lastTxCount;
        public long scanTime;
        public long lastScanTime;
    }

    private final SparseArray<UidStats> mUidStats = new SparseArray<>();

    BluetoothPowerStatsCollector(Injector injector) {
        super(injector.getHandler(),  injector.getPowerStatsCollectionThrottlePeriod(
                        BatteryConsumer.powerComponentIdToString(
                                BatteryConsumer.POWER_COMPONENT_BLUETOOTH)),
                injector.getUidResolver(),
                injector.getClock());
        mInjector = injector;
    }

    @Override
    public void setEnabled(boolean enabled) {
        if (enabled) {
            PackageManager packageManager = mInjector.getPackageManager();
            super.setEnabled(packageManager != null
                    && packageManager.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH));
        } else {
            super.setEnabled(false);
        }
    }

    private boolean ensureInitialized() {
        if (mIsInitialized) {
            return true;
        }

        if (!isEnabled()) {
            return false;
        }

        mConsumedEnergyRetriever = mInjector.getConsumedEnergyRetriever();
        mVoltageSupplier = mInjector.getVoltageSupplier();
        mBluetoothStatsRetriever = mInjector.getBluetoothStatsRetriever();
        mEnergyConsumerIds =
                mConsumedEnergyRetriever.getEnergyConsumerIds(EnergyConsumerType.BLUETOOTH);
        mLastConsumedEnergyUws = new long[mEnergyConsumerIds.length];
        Arrays.fill(mLastConsumedEnergyUws, ENERGY_UNSPECIFIED);

        mLayout = new BluetoothPowerStatsLayout();
        mLayout.addDeviceBluetoothControllerActivity();
        mLayout.addDeviceSectionEnergyConsumers(mEnergyConsumerIds.length);
        mLayout.addDeviceSectionUsageDuration();
        mLayout.addDeviceSectionPowerEstimate();
        mLayout.addUidTrafficStats();
        mLayout.addUidSectionPowerEstimate();

        PersistableBundle extras = new PersistableBundle();
        mLayout.toExtras(extras);
        PowerStats.Descriptor powerStatsDescriptor = new PowerStats.Descriptor(
                BatteryConsumer.POWER_COMPONENT_BLUETOOTH, mLayout.getDeviceStatsArrayLength(),
                null, 0, mLayout.getUidStatsArrayLength(),
                extras);
        mPowerStats = new PowerStats(powerStatsDescriptor);
        mDeviceStats = mPowerStats.stats;

        mIsInitialized = true;
        return true;
    }

    @Override
    protected PowerStats collectStats() {
        if (!ensureInitialized()) {
            return null;
        }

        mPowerStats.uidStats.clear();

        collectBluetoothActivityInfo();
        collectBluetoothScanStats();

        if (mEnergyConsumerIds.length != 0) {
            collectEnergyConsumers();
        }

        return mPowerStats;
    }

    private void collectBluetoothActivityInfo() {
        CompletableFuture<BluetoothActivityEnergyInfo> immediateFuture = new CompletableFuture<>();
        boolean success = mBluetoothStatsRetriever.requestControllerActivityEnergyInfo(
                Runnable::run,
                new BluetoothAdapter.OnBluetoothActivityEnergyInfoCallback() {
                    @Override
                    public void onBluetoothActivityEnergyInfoAvailable(
                            BluetoothActivityEnergyInfo info) {
                        immediateFuture.complete(info);
                    }

                    @Override
                    public void onBluetoothActivityEnergyInfoError(int error) {
                        immediateFuture.completeExceptionally(
                                new RuntimeException("error: " + error));
                    }
                });

        if (!success) {
            return;
        }

        BluetoothActivityEnergyInfo activityInfo;
        try {
            activityInfo = immediateFuture.get(BLUETOOTH_ACTIVITY_REQUEST_TIMEOUT,
                    TimeUnit.MILLISECONDS);
        } catch (Exception e) {
            Slog.e(TAG, "Cannot acquire BluetoothActivityEnergyInfo", e);
            activityInfo = null;
        }

        if (activityInfo == null) {
            return;
        }

        long rxTime = activityInfo.getControllerRxTimeMillis();
        long rxTimeDelta = Math.max(0, rxTime - mLastRxTime);
        mLayout.setDeviceRxTime(mDeviceStats, rxTimeDelta);
        mLastRxTime = rxTime;

        long txTime = activityInfo.getControllerTxTimeMillis();
        long txTimeDelta = Math.max(0, txTime - mLastTxTime);
        mLayout.setDeviceTxTime(mDeviceStats, txTimeDelta);
        mLastTxTime = txTime;

        long idleTime = activityInfo.getControllerIdleTimeMillis();
        long idleTimeDelta = Math.max(0, idleTime - mLastIdleTime);
        mLayout.setDeviceIdleTime(mDeviceStats, idleTimeDelta);
        mLastIdleTime = idleTime;

        mPowerStats.durationMs = rxTimeDelta + txTimeDelta + idleTimeDelta;

        List<UidTraffic> uidTraffic = activityInfo.getUidTraffic();
        for (int i = uidTraffic.size() - 1; i >= 0; i--) {
            UidTraffic ut = uidTraffic.get(i);
            int uid = mUidResolver.mapUid(ut.getUid());
            UidStats counts = mUidStats.get(uid);
            if (counts == null) {
                counts = new UidStats();
                mUidStats.put(uid, counts);
            }
            counts.rxCount += ut.getRxBytes();
            counts.txCount += ut.getTxBytes();
        }

        for (int i = mUidStats.size() - 1; i >= 0; i--) {
            UidStats counts = mUidStats.valueAt(i);
            long rxDelta = Math.max(0, counts.rxCount - counts.lastRxCount);
            counts.lastRxCount = counts.rxCount;
            counts.rxCount = 0;

            long txDelta = Math.max(0, counts.txCount - counts.lastTxCount);
            counts.lastTxCount = counts.txCount;
            counts.txCount = 0;

            if (rxDelta != 0 || txDelta != 0) {
                int uid = mUidStats.keyAt(i);
                long[] stats = mPowerStats.uidStats.get(uid);
                if (stats == null) {
                    stats = new long[mLayout.getUidStatsArrayLength()];
                    mPowerStats.uidStats.put(uid, stats);
                }

                mLayout.setUidRxBytes(stats, rxDelta);
                mLayout.setUidTxBytes(stats, txDelta);
            }
        }
    }

    private void collectBluetoothScanStats() {
        mBluetoothStatsRetriever.retrieveBluetoothScanTimes((uid, scanTimeMs) -> {
            uid = mUidResolver.mapUid(uid);
            UidStats uidStats = mUidStats.get(uid);
            if (uidStats == null) {
                uidStats = new UidStats();
                mUidStats.put(uid, uidStats);
            }
            uidStats.scanTime += scanTimeMs;
        });

        long totalScanTime = 0;
        for (int i = mUidStats.size() - 1; i >= 0; i--) {
            UidStats counts = mUidStats.valueAt(i);
            if (counts.scanTime == 0) {
                continue;
            }

            long delta = Math.max(0, counts.scanTime - counts.lastScanTime);
            counts.lastScanTime = counts.scanTime;
            counts.scanTime = 0;

            if (delta != 0) {
                int uid = mUidStats.keyAt(i);
                long[] stats = mPowerStats.uidStats.get(uid);
                if (stats == null) {
                    stats = new long[mLayout.getUidStatsArrayLength()];
                    mPowerStats.uidStats.put(uid, stats);
                }

                mLayout.setUidScanTime(stats, delta);
                totalScanTime += delta;
            }
        }

        mLayout.setDeviceScanTime(mDeviceStats, totalScanTime);
    }

    private void collectEnergyConsumers() {
        int voltageMv = mVoltageSupplier.getAsInt();
        if (voltageMv <= 0) {
            Slog.wtf(TAG, "Unexpected battery voltage (" + voltageMv
                    + " mV) when querying energy consumers");
            return;
        }

        int averageVoltage = mLastVoltageMv != 0 ? (mLastVoltageMv + voltageMv) / 2 : voltageMv;
        mLastVoltageMv = voltageMv;

        long[] energyUws = mConsumedEnergyRetriever.getConsumedEnergyUws(mEnergyConsumerIds);
        if (energyUws == null) {
            return;
        }

        for (int i = energyUws.length - 1; i >= 0; i--) {
            long energyDelta = mLastConsumedEnergyUws[i] != ENERGY_UNSPECIFIED
                    ? energyUws[i] - mLastConsumedEnergyUws[i] : 0;
            if (energyDelta < 0) {
                // Likely, restart of powerstats HAL
                energyDelta = 0;
            }
            mLayout.setConsumedEnergy(mPowerStats.stats, i, uJtoUc(energyDelta, averageVoltage));
            mLastConsumedEnergyUws[i] = energyUws[i];
        }
    }

    @Override
    protected void onUidRemoved(int uid) {
        super.onUidRemoved(uid);
        mUidStats.remove(uid);
    }
}
Loading