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

Commit 0acdb31c authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "[hbm] Separate HBM times for multi-display devices." into tm-qpr-dev

parents 00020dbd ac86b481
Loading
Loading
Loading
Loading
+61 −3
Original line number Diff line number Diff line
@@ -104,6 +104,7 @@ import android.os.UserManager;
import android.provider.Settings;
import android.sysprop.DisplayProperties;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.EventLog;
import android.util.IntArray;
@@ -256,6 +257,13 @@ public final class DisplayManagerService extends SystemService {
    final SparseArray<Pair<IVirtualDevice, DisplayWindowPolicyController>>
            mDisplayWindowPolicyControllers = new SparseArray<>();

    /**
     *  Map of every internal primary display device {@link HighBrightnessModeMetadata}s indexed by
     *  {@link DisplayDevice#mUniqueId}.
     */
    public final ArrayMap<String, HighBrightnessModeMetadata> mHighBrightnessModeMetadataMap =
            new ArrayMap<>();

    // List of all currently registered display adapters.
    private final ArrayList<DisplayAdapter> mDisplayAdapters = new ArrayList<DisplayAdapter>();

@@ -1570,7 +1578,16 @@ public final class DisplayManagerService extends SystemService {

        DisplayPowerController dpc = mDisplayPowerControllers.get(displayId);
        if (dpc != null) {
            dpc.onDisplayChanged();
            final DisplayDevice device = display.getPrimaryDisplayDeviceLocked();
            if (device == null) {
                Slog.wtf(TAG, "Display Device is null in DisplayManagerService for display: "
                        + display.getDisplayIdLocked());
                return;
            }

            final String uniqueId = device.getUniqueId();
            HighBrightnessModeMetadata hbmMetadata = mHighBrightnessModeMetadataMap.get(uniqueId);
            dpc.onDisplayChanged(hbmMetadata);
        }
    }

@@ -1627,7 +1644,15 @@ public final class DisplayManagerService extends SystemService {
        final int displayId = display.getDisplayIdLocked();
        final DisplayPowerController dpc = mDisplayPowerControllers.get(displayId);
        if (dpc != null) {
            dpc.onDisplayChanged();
            final DisplayDevice device = display.getPrimaryDisplayDeviceLocked();
            if (device == null) {
                Slog.wtf(TAG, "Display Device is null in DisplayManagerService for display: "
                        + display.getDisplayIdLocked());
                return;
            }
            final String uniqueId = device.getUniqueId();
            HighBrightnessModeMetadata hbmMetadata = mHighBrightnessModeMetadataMap.get(uniqueId);
            dpc.onDisplayChanged(hbmMetadata);
        }
    }

@@ -2611,6 +2636,31 @@ public final class DisplayManagerService extends SystemService {
        mLogicalDisplayMapper.forEachLocked(this::addDisplayPowerControllerLocked);
    }

    private HighBrightnessModeMetadata getHighBrightnessModeMetadata(LogicalDisplay display) {
        final DisplayDevice device = display.getPrimaryDisplayDeviceLocked();
        if (device == null) {
            Slog.wtf(TAG, "Display Device is null in DisplayPowerController for display: "
                    + display.getDisplayIdLocked());
            return null;
        }

        // HBM brightness mode is only applicable to internal physical displays.
        if (display.getDisplayInfoLocked().type != Display.TYPE_INTERNAL) {
            return null;
        }

        final String uniqueId = device.getUniqueId();

        if (mHighBrightnessModeMetadataMap.containsKey(uniqueId)) {
            return mHighBrightnessModeMetadataMap.get(uniqueId);
        }

        // HBM Time info not present. Create a new one for this physical display.
        HighBrightnessModeMetadata hbmInfo = new HighBrightnessModeMetadata();
        mHighBrightnessModeMetadataMap.put(uniqueId, hbmInfo);
        return hbmInfo;
    }

    private void addDisplayPowerControllerLocked(LogicalDisplay display) {
        if (mPowerHandler == null) {
            // initPowerManagement has not yet been called.
@@ -2622,10 +2672,18 @@ public final class DisplayManagerService extends SystemService {

        final BrightnessSetting brightnessSetting = new BrightnessSetting(mPersistentDataStore,
                display, mSyncRoot);

        // If display is internal and has a HighBrightnessModeMetadata mapping, use that.
        // Or create a new one and use that.
        // We also need to pass a mapping of the HighBrightnessModeTimeInfoMap to
        // displayPowerController, so the hbm info can be correctly associated
        // with the corresponding displaydevice.
        HighBrightnessModeMetadata hbmMetadata = getHighBrightnessModeMetadata(display);

        final DisplayPowerController displayPowerController = new DisplayPowerController(
                mContext, mDisplayPowerCallbacks, mPowerHandler, mSensorManager,
                mDisplayBlanker, display, mBrightnessTracker, brightnessSetting,
                () -> handleBrightnessChange(display));
                () -> handleBrightnessChange(display), hbmMetadata);
        mDisplayPowerControllers.append(display.getDisplayIdLocked(), displayPowerController);
    }

+9 −5
Original line number Diff line number Diff line
@@ -391,6 +391,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
    private float[] mNitsRange;

    private final HighBrightnessModeController mHbmController;
    private final HighBrightnessModeMetadata mHighBrightnessModeMetadata;

    private final BrightnessThrottler mBrightnessThrottler;

@@ -511,7 +512,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
            DisplayPowerCallbacks callbacks, Handler handler,
            SensorManager sensorManager, DisplayBlanker blanker, LogicalDisplay logicalDisplay,
            BrightnessTracker brightnessTracker, BrightnessSetting brightnessSetting,
            Runnable onBrightnessChangeRunnable) {
            Runnable onBrightnessChangeRunnable, HighBrightnessModeMetadata hbmMetadata) {
        mLogicalDisplay = logicalDisplay;
        mDisplayId = mLogicalDisplay.getDisplayIdLocked();
        final String displayIdStr = "[" + mDisplayId + "]";
@@ -521,6 +522,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
        mSuspendBlockerIdProxPositive = displayIdStr + "prox positive";
        mSuspendBlockerIdProxNegative = displayIdStr + "prox negative";
        mSuspendBlockerIdProxDebounce = displayIdStr + "prox debounce";
        mHighBrightnessModeMetadata = hbmMetadata;

        mDisplayDevice = mLogicalDisplay.getPrimaryDisplayDeviceLocked();
        mUniqueDisplayId = logicalDisplay.getPrimaryDisplayDeviceLocked().getUniqueId();
@@ -793,7 +795,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
     * of each display need to be properly reflected in AutomaticBrightnessController.
     */
    @GuardedBy("DisplayManagerService.mSyncRoot")
    public void onDisplayChanged() {
    public void onDisplayChanged(HighBrightnessModeMetadata hbmMetadata) {
        final DisplayDevice device = mLogicalDisplay.getPrimaryDisplayDeviceLocked();
        if (device == null) {
            Slog.wtf(TAG, "Display Device is null in DisplayPowerController for display: "
@@ -815,7 +817,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
                mUniqueDisplayId = uniqueId;
                mDisplayStatsId = mUniqueDisplayId.hashCode();
                mDisplayDeviceConfig = config;
                loadFromDisplayDeviceConfig(token, info);
                loadFromDisplayDeviceConfig(token, info, hbmMetadata);

                /// Since the underlying display-device changed, we really don't know the
                // last command that was sent to change it's state. Lets assume it is unknown so
@@ -872,7 +874,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
        }
    }

    private void loadFromDisplayDeviceConfig(IBinder token, DisplayDeviceInfo info) {
    private void loadFromDisplayDeviceConfig(IBinder token, DisplayDeviceInfo info,
                                             HighBrightnessModeMetadata hbmMetadata) {
        // All properties that depend on the associated DisplayDevice and the DDC must be
        // updated here.
        loadBrightnessRampRates();
@@ -885,6 +888,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
                    mBrightnessRampIncreaseMaxTimeMillis,
                    mBrightnessRampDecreaseMaxTimeMillis);
        }
        mHbmController.setHighBrightnessModeMetadata(hbmMetadata);
        mHbmController.resetHbmData(info.width, info.height, token, info.uniqueId,
                mDisplayDeviceConfig.getHighBrightnessModeData(),
                new HighBrightnessModeController.HdrBrightnessDeviceConfig() {
@@ -1965,7 +1969,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
                    if (mAutomaticBrightnessController != null) {
                        mAutomaticBrightnessController.update();
                    }
                }, mContext);
                }, mHighBrightnessModeMetadata, mContext);
    }

    private BrightnessThrottler createBrightnessThrottlerLocked() {
+46 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 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.display;


/**
 * Represents an event in which High Brightness Mode was enabled.
 */
class HbmEvent {
    private long mStartTimeMillis;
    private long mEndTimeMillis;

    HbmEvent(long startTimeMillis, long endTimeMillis) {
        this.mStartTimeMillis = startTimeMillis;
        this.mEndTimeMillis = endTimeMillis;
    }

    public long getStartTimeMillis() {
        return mStartTimeMillis;
    }

    public long getEndTimeMillis() {
        return mEndTimeMillis;
    }

    @Override
    public String toString() {
        return "HbmEvent: {startTimeMillis:" + mStartTimeMillis + ", endTimeMillis: "
                + mEndTimeMillis + "}, total: "
                + ((mEndTimeMillis - mStartTimeMillis) / 1000) + "]";
    }
}
+51 −61
Original line number Diff line number Diff line
@@ -42,8 +42,8 @@ import com.android.server.display.DisplayDeviceConfig.HighBrightnessModeData;
import com.android.server.display.DisplayManagerService.Clock;

import java.io.PrintWriter;
import java.util.ArrayDeque;
import java.util.Iterator;
import java.util.LinkedList;

/**
 * Controls the status of high-brightness mode for devices that support it. This class assumes that
@@ -105,30 +105,24 @@ class HighBrightnessModeController {
    private int mHbmStatsState = FrameworkStatsLog.DISPLAY_HBM_STATE_CHANGED__STATE__HBM_OFF;

    /**
     * If HBM is currently running, this is the start time for the current HBM session.
     * If HBM is currently running, this is the start time and set of all events,
     * for the current HBM session.
     */
    private long mRunningStartTimeMillis = -1;

    /**
     * List of previous HBM-events ordered from most recent to least recent.
     * Meant to store only the events that fall into the most recent
     * {@link mHbmData.timeWindowMillis}.
     */
    private LinkedList<HbmEvent> mEvents = new LinkedList<>();
    private HighBrightnessModeMetadata mHighBrightnessModeMetadata = null;

    HighBrightnessModeController(Handler handler, int width, int height, IBinder displayToken,
            String displayUniqueId, float brightnessMin, float brightnessMax,
            HighBrightnessModeData hbmData, HdrBrightnessDeviceConfig hdrBrightnessCfg,
            Runnable hbmChangeCallback, Context context) {
            Runnable hbmChangeCallback, HighBrightnessModeMetadata hbmMetadata, Context context) {
        this(new Injector(), handler, width, height, displayToken, displayUniqueId, brightnessMin,
            brightnessMax, hbmData, hdrBrightnessCfg, hbmChangeCallback, context);
            brightnessMax, hbmData, hdrBrightnessCfg, hbmChangeCallback, hbmMetadata, context);
    }

    @VisibleForTesting
    HighBrightnessModeController(Injector injector, Handler handler, int width, int height,
            IBinder displayToken, String displayUniqueId, float brightnessMin, float brightnessMax,
            HighBrightnessModeData hbmData, HdrBrightnessDeviceConfig hdrBrightnessCfg,
            Runnable hbmChangeCallback, Context context) {
            Runnable hbmChangeCallback, HighBrightnessModeMetadata hbmMetadata, Context context) {
        mInjector = injector;
        mContext = context;
        mClock = injector.getClock();
@@ -137,6 +131,7 @@ class HighBrightnessModeController {
        mBrightnessMin = brightnessMin;
        mBrightnessMax = brightnessMax;
        mHbmChangeCallback = hbmChangeCallback;
        mHighBrightnessModeMetadata = hbmMetadata;
        mSkinThermalStatusObserver = new SkinThermalStatusObserver(mInjector, mHandler);
        mSettingsObserver = new SettingsObserver(mHandler);
        mRecalcRunnable = this::recalculateTimeAllowance;
@@ -222,19 +217,22 @@ class HighBrightnessModeController {

        // If we are starting or ending a high brightness mode session, store the current
        // session in mRunningStartTimeMillis, or the old one in mEvents.
        final boolean wasHbmDrainingAvailableTime = mRunningStartTimeMillis != -1;
        final long runningStartTime = mHighBrightnessModeMetadata.getRunningStartTimeMillis();
        final boolean wasHbmDrainingAvailableTime = runningStartTime != -1;
        final boolean shouldHbmDrainAvailableTime = mBrightness > mHbmData.transitionPoint
                && !mIsHdrLayerPresent;
        if (wasHbmDrainingAvailableTime != shouldHbmDrainAvailableTime) {
            final long currentTime = mClock.uptimeMillis();
            if (shouldHbmDrainAvailableTime) {
                mRunningStartTimeMillis = currentTime;
                mHighBrightnessModeMetadata.setRunningStartTimeMillis(currentTime);
            } else {
                mEvents.addFirst(new HbmEvent(mRunningStartTimeMillis, currentTime));
                mRunningStartTimeMillis = -1;
                final HbmEvent hbmEvent = new HbmEvent(runningStartTime, currentTime);
                mHighBrightnessModeMetadata.addHbmEvent(hbmEvent);
                mHighBrightnessModeMetadata.setRunningStartTimeMillis(-1);

                if (DEBUG) {
                    Slog.d(TAG, "New HBM event: " + mEvents.getFirst());
                    Slog.d(TAG, "New HBM event: "
                            + mHighBrightnessModeMetadata.getHbmEventQueue().peekFirst());
                }
            }
        }
@@ -260,6 +258,10 @@ class HighBrightnessModeController {
        mSettingsObserver.stopObserving();
    }

    void setHighBrightnessModeMetadata(HighBrightnessModeMetadata hbmInfo) {
        mHighBrightnessModeMetadata = hbmInfo;
    }

    void resetHbmData(int width, int height, IBinder displayToken, String displayUniqueId,
            HighBrightnessModeData hbmData, HdrBrightnessDeviceConfig hdrBrightnessCfg) {
        mWidth = width;
@@ -316,20 +318,22 @@ class HighBrightnessModeController {
        pw.println("  mBrightnessMax=" + mBrightnessMax);
        pw.println("  remainingTime=" + calculateRemainingTime(mClock.uptimeMillis()));
        pw.println("  mIsTimeAvailable= " + mIsTimeAvailable);
        pw.println("  mRunningStartTimeMillis=" + TimeUtils.formatUptime(mRunningStartTimeMillis));
        pw.println("  mRunningStartTimeMillis="
                + TimeUtils.formatUptime(mHighBrightnessModeMetadata.getRunningStartTimeMillis()));
        pw.println("  mIsThermalStatusWithinLimit=" + mIsThermalStatusWithinLimit);
        pw.println("  mIsBlockedByLowPowerMode=" + mIsBlockedByLowPowerMode);
        pw.println("  width*height=" + mWidth + "*" + mHeight);
        pw.println("  mEvents=");
        final long currentTime = mClock.uptimeMillis();
        long lastStartTime = currentTime;
        if (mRunningStartTimeMillis != -1) {
            lastStartTime = dumpHbmEvent(pw, new HbmEvent(mRunningStartTimeMillis, currentTime));
        long runningStartTimeMillis = mHighBrightnessModeMetadata.getRunningStartTimeMillis();
        if (runningStartTimeMillis != -1) {
            lastStartTime = dumpHbmEvent(pw, new HbmEvent(runningStartTimeMillis, currentTime));
        }
        for (HbmEvent event : mEvents) {
            if (lastStartTime > event.endTimeMillis) {
        for (HbmEvent event : mHighBrightnessModeMetadata.getHbmEventQueue()) {
            if (lastStartTime > event.getEndTimeMillis()) {
                pw.println("    event: [normal brightness]: "
                        + TimeUtils.formatDuration(lastStartTime - event.endTimeMillis));
                        + TimeUtils.formatDuration(lastStartTime - event.getEndTimeMillis()));
            }
            lastStartTime = dumpHbmEvent(pw, event);
        }
@@ -338,12 +342,12 @@ class HighBrightnessModeController {
    }

    private long dumpHbmEvent(PrintWriter pw, HbmEvent event) {
        final long duration = event.endTimeMillis - event.startTimeMillis;
        final long duration = event.getEndTimeMillis() - event.getStartTimeMillis();
        pw.println("    event: ["
                + TimeUtils.formatUptime(event.startTimeMillis) + ", "
                + TimeUtils.formatUptime(event.endTimeMillis) + "] ("
                + TimeUtils.formatUptime(event.getStartTimeMillis()) + ", "
                + TimeUtils.formatUptime(event.getEndTimeMillis()) + "] ("
                + TimeUtils.formatDuration(duration) + ")");
        return event.startTimeMillis;
        return event.getStartTimeMillis();
    }

    private boolean isCurrentlyAllowed() {
@@ -372,13 +376,15 @@ class HighBrightnessModeController {

        // First, lets see how much time we've taken for any currently running
        // session of HBM.
        if (mRunningStartTimeMillis > 0) {
            if (mRunningStartTimeMillis > currentTime) {
        long runningStartTimeMillis = mHighBrightnessModeMetadata.getRunningStartTimeMillis();
        if (runningStartTimeMillis > 0) {
            if (runningStartTimeMillis > currentTime) {
                Slog.e(TAG, "Start time set to the future. curr: " + currentTime
                        + ", start: " + mRunningStartTimeMillis);
                mRunningStartTimeMillis = currentTime;
                        + ", start: " + runningStartTimeMillis);
                mHighBrightnessModeMetadata.setRunningStartTimeMillis(currentTime);
                runningStartTimeMillis = currentTime;
            }
            timeAlreadyUsed = currentTime - mRunningStartTimeMillis;
            timeAlreadyUsed = currentTime - runningStartTimeMillis;
        }

        if (DEBUG) {
@@ -387,18 +393,19 @@ class HighBrightnessModeController {

        // Next, lets iterate through the history of previous sessions and add those times.
        final long windowstartTimeMillis = currentTime - mHbmData.timeWindowMillis;
        Iterator<HbmEvent> it = mEvents.iterator();
        Iterator<HbmEvent> it = mHighBrightnessModeMetadata.getHbmEventQueue().iterator();
        while (it.hasNext()) {
            final HbmEvent event = it.next();

            // If this event ended before the current Timing window, discard forever and ever.
            if (event.endTimeMillis < windowstartTimeMillis) {
            if (event.getEndTimeMillis() < windowstartTimeMillis) {
                it.remove();
                continue;
            }

            final long startTimeMillis = Math.max(event.startTimeMillis, windowstartTimeMillis);
            timeAlreadyUsed += event.endTimeMillis - startTimeMillis;
            final long startTimeMillis = Math.max(event.getStartTimeMillis(),
                            windowstartTimeMillis);
            timeAlreadyUsed += event.getEndTimeMillis() - startTimeMillis;
        }

        if (DEBUG) {
@@ -425,17 +432,18 @@ class HighBrightnessModeController {
        // Calculate the time at which we want to recalculate mIsTimeAvailable in case a lux or
        // brightness change doesn't happen before then.
        long nextTimeout = -1;
        final ArrayDeque<HbmEvent> hbmEvents = mHighBrightnessModeMetadata.getHbmEventQueue();
        if (mBrightness > mHbmData.transitionPoint) {
            // if we're in high-lux now, timeout when we run out of allowed time.
            nextTimeout = currentTime + remainingTime;
        } else if (!mIsTimeAvailable && mEvents.size() > 0) {
        } else if (!mIsTimeAvailable && hbmEvents.size() > 0) {
            // If we are not allowed...timeout when the oldest event moved outside of the timing
            // window by at least minTime. Basically, we're calculating the soonest time we can
            // get {@code timeMinMillis} back to us.
            final long windowstartTimeMillis = currentTime - mHbmData.timeWindowMillis;
            final HbmEvent lastEvent = mEvents.getLast();
            final HbmEvent lastEvent = hbmEvents.peekLast();
            final long startTimePlusMinMillis =
                    Math.max(windowstartTimeMillis, lastEvent.startTimeMillis)
                    Math.max(windowstartTimeMillis, lastEvent.getStartTimeMillis())
                    + mHbmData.timeMinMillis;
            final long timeWhenMinIsGainedBack =
                    currentTime + (startTimePlusMinMillis - windowstartTimeMillis) - remainingTime;
@@ -459,9 +467,10 @@ class HighBrightnessModeController {
                    + ", mUnthrottledBrightness: " + mUnthrottledBrightness
                    + ", mThrottlingReason: "
                        + BrightnessInfo.briMaxReasonToString(mThrottlingReason)
                    + ", RunningStartTimeMillis: " + mRunningStartTimeMillis
                    + ", RunningStartTimeMillis: "
                        + mHighBrightnessModeMetadata.getRunningStartTimeMillis()
                    + ", nextTimeout: " + (nextTimeout != -1 ? (nextTimeout - currentTime) : -1)
                    + ", events: " + mEvents);
                    + ", events: " + hbmEvents);
        }

        if (nextTimeout != -1) {
@@ -588,25 +597,6 @@ class HighBrightnessModeController {
        }
    }

    /**
     * Represents an event in which High Brightness Mode was enabled.
     */
    private static class HbmEvent {
        public long startTimeMillis;
        public long endTimeMillis;

        HbmEvent(long startTimeMillis, long endTimeMillis) {
            this.startTimeMillis = startTimeMillis;
            this.endTimeMillis = endTimeMillis;
        }

        @Override
        public String toString() {
            return "[Event: {" + startTimeMillis + ", " + endTimeMillis + "}, total: "
                    + ((endTimeMillis - startTimeMillis) / 1000) + "]";
        }
    }

    @VisibleForTesting
    class HdrListener extends SurfaceControlHdrLayerInfoListener {
        @Override
+58 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 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.display;

import java.util.ArrayDeque;


/**
 * Represents High Brightness Mode metadata associated
 * with a specific internal physical display.
 * Required for separately storing data like time information,
 * and related events when display was in HBM mode per
 * physical internal display.
 */
class HighBrightnessModeMetadata {
    /**
     * Queue of previous HBM-events ordered from most recent to least recent.
     * Meant to store only the events that fall into the most recent
     * {@link HighBrightnessModeData#timeWindowMillis mHbmData.timeWindowMillis}.
     */
    private final ArrayDeque<HbmEvent> mEvents = new ArrayDeque<>();

    /**
     * If HBM is currently running, this is the start time for the current HBM session.
     */
    private long mRunningStartTimeMillis = -1;

    public long getRunningStartTimeMillis() {
        return mRunningStartTimeMillis;
    }

    public void setRunningStartTimeMillis(long setTime) {
        mRunningStartTimeMillis = setTime;
    }

    public ArrayDeque<HbmEvent> getHbmEventQueue() {
        return mEvents;
    }

    public void addHbmEvent(HbmEvent hbmEvent) {
        mEvents.addFirst(hbmEvent);
    }
}
Loading