/*
 * Copyright (C) 2015 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.car;

import android.annotation.NonNull;
import android.car.Car;
import android.content.Context;
import android.hardware.display.DisplayManager;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.os.SystemClock;
import android.util.Log;
import android.view.Display;

import com.android.car.hal.PowerHalService;
import com.android.car.hal.PowerHalService.PowerState;
import com.android.car.hal.VehicleHal;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;

import java.io.PrintWriter;
import java.util.LinkedList;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.CopyOnWriteArrayList;

public class CarPowerManagementService implements CarServiceBase,
    PowerHalService.PowerEventListener {

    /**
     * Listener for other services to monitor power events.
     */
    public interface PowerServiceEventListener {
        /**
         * Shutdown is happening
         */
        void onShutdown();

        /**
         * Entering deep sleep.
         */
        void onSleepEntry();

        /**
         * Got out of deep sleep.
         */
        void onSleepExit();
    }

    /**
     * Interface for components requiring processing time before shutting-down or
     * entering sleep, and wake-up after shut-down.
     */
    public interface PowerEventProcessingHandler {
        /**
         * Called before shutdown or sleep entry to allow running some processing. This call
         * should only queue such task in different thread and should return quickly.
         * Blocking inside this call can trigger watchdog timer which can terminate the
         * whole system.
         * @param shuttingDown whether system is shutting down or not (= sleep entry).
         * @return time necessary to run processing in ms. should return 0 if there is no
         *         processing necessary.
         */
        long onPrepareShutdown(boolean shuttingDown);

        /**
         * Called when power state is changed to ON state. Display can be either on or off.
         * @param displayOn
         */
        void onPowerOn(boolean displayOn);

        /**
         * Returns wake up time after system is fully shutdown. Power controller will power on
         * the system after this time. This power on is meant for regular maintenance kind of
         * operation.
         * @return 0 of wake up is not necessary.
         */
        int getWakeupTime();
    }

    /** Interface to abstract all system interaction. Separated for testing. */
    public interface SystemInteface {
        void setDisplayState(boolean on);
        void releaseAllWakeLocks();
        void shutdown();
        void enterDeepSleep(int wakeupTimeSec);
        void switchToPartialWakeLock();
        void switchToFullWakeLock();
        void startDisplayStateMonitoring(CarPowerManagementService service);
        void stopDisplayStateMonitoring();
        boolean isSystemSupportingDeepSleep();
        boolean isWakeupCausedByTimer();
    }

    private final Context mContext;
    private final PowerHalService mHal;
    private final SystemInteface mSystemInterface;
    private final HandlerThread mHandlerThread;
    private final PowerHandler mHandler;

    private final CopyOnWriteArrayList<PowerServiceEventListener> mListeners =
            new CopyOnWriteArrayList<>();
    private final CopyOnWriteArrayList<PowerEventProcessingHandlerWrapper>
            mPowerEventProcessingHandlers = new CopyOnWriteArrayList<>();

    @GuardedBy("this")
    private PowerState mCurrentState;
    @GuardedBy("this")
    private Timer mTimer;
    @GuardedBy("this")
    private long mProcessingStartTime;
    @GuardedBy("this")
    private long mLastSleepEntryTime;
    @GuardedBy("this")
    private final LinkedList<PowerState> mPendingPowerStates = new LinkedList<>();

    private final int SHUTDOWN_POLLING_INTERVAL_MS = 2000;
    private final int SHUTDOWN_EXTEND_MAX_MS = 5000;

    /**
     * Constructor for full functionality.
     */
    public CarPowerManagementService(@NonNull Context context) {
        this(context, VehicleHal.getInstance().getPowerHal(),
                new SystemIntefaceImpl(context));
    }

    /**
     * Constructor for full functionality. Can inject external interfaces
     */
    public CarPowerManagementService(@NonNull Context context, @NonNull PowerHalService powerHal,
            @NonNull SystemInteface systemInterface) {
        mContext = context;
        mHal = powerHal;
        mSystemInterface = systemInterface;
        mHandlerThread = new HandlerThread(CarLog.TAG_POWER);
        mHandlerThread.start();
        mHandler = new PowerHandler(mHandlerThread.getLooper());
    }

    /**
     * Create a dummy instance for unit testing purpose only. Instance constructed in this way
     * is not safe as members expected to be non-null are null.
     */
    @VisibleForTesting
    protected CarPowerManagementService() {
        mContext = null;
        mHal = null;
        mSystemInterface = null;
        mHandlerThread = null;
        mHandler = new PowerHandler(Looper.getMainLooper());
    }

    @Override
    public void init() {
        mHal.setListener(this);
        if (mHal.isPowerStateSupported()) {
            mHal.sendBootComplete();
            PowerState currentState = mHal.getCurrentPowerState();
            onApPowerStateChange(currentState);
        } else {
            Log.w(CarLog.TAG_POWER, "Vehicle hal does not support power state yet.");
            onApPowerStateChange(new PowerState(PowerHalService.STATE_ON_FULL, 0));
            mSystemInterface.switchToFullWakeLock();
        }
        mSystemInterface.startDisplayStateMonitoring(this);
    }

    @Override
    public void release() {
        synchronized (this) {
            releaseTimerLocked();
            mCurrentState = null;
        }
        mSystemInterface.stopDisplayStateMonitoring();
        mHandler.cancelAll();
        mListeners.clear();
        mPowerEventProcessingHandlers.clear();
        mSystemInterface.releaseAllWakeLocks();
    }

    /**
     * Register listener to monitor power event. There is no unregister counter-part and the list
     * will be cleared when the service is released.
     * @param listener
     */
    public synchronized void registerPowerEventListener(PowerServiceEventListener listener) {
        mListeners.add(listener);
    }

    /**
     * Register PowerEventPreprocessingHandler to run pre-processing before shutdown or
     * sleep entry. There is no unregister counter-part and the list
     * will be cleared when the service is released.
     * @param handler
     */
    public synchronized void registerPowerEventProcessingHandler(
            PowerEventProcessingHandler handler) {
        mPowerEventProcessingHandlers.add(new PowerEventProcessingHandlerWrapper(handler));
        // onPowerOn will not be called if power on notification is already done inside the
        // handler thread. So request it once again here. Wrapper will have its own
        // gatekeeping to prevent calling onPowerOn twice.
        mHandler.handlePowerOn();
    }

    /**
     * Notifies earlier completion of power event processing. PowerEventProcessingHandler quotes
     * time necessary from onPrePowerEvent() call, but actual processing can finish earlier than
     * that, and this call can be called in such case to trigger shutdown without waiting further.
     *
     * @param handler PowerEventProcessingHandler that was already registered with
     *        {@link #registerPowerEventListener(PowerServiceEventListener)} call. If it was not
     *        registered before, this call will be ignored.
     */
    public void notifyPowerEventProcessingCompletion(PowerEventProcessingHandler handler) {
        long processingTime = 0;
        for (PowerEventProcessingHandlerWrapper wrapper : mPowerEventProcessingHandlers) {
            if (wrapper.handler == handler) {
                wrapper.markProcessingDone();
            } else if (!wrapper.isProcessingDone()) {
                processingTime = Math.max(processingTime, wrapper.getProcessingTime());
            }
        }
        long now = SystemClock.elapsedRealtime();
        long startTime;
        boolean shouldShutdown = true;
        synchronized (this) {
            startTime = mProcessingStartTime;
            if (mCurrentState == null) {
                return;
            }
            if (mCurrentState.state != PowerHalService.STATE_SHUTDOWN_PREPARE) {
                return;
            }
            if (mCurrentState.canEnterDeepSleep()) {
                shouldShutdown = false;
                if (mLastSleepEntryTime > mProcessingStartTime && mLastSleepEntryTime < now) {
                    // already slept
                    return;
                }
            }
        }
        if ((startTime + processingTime) <= now) {
            Log.i(CarLog.TAG_POWER, "Processing all done");
            mHandler.handleProcessingComplete(shouldShutdown);
        }
    }

    @Override
    public void dump(PrintWriter writer) {
        writer.println("*PowerManagementService*");
        writer.print("mCurrentState:" + mCurrentState);
        writer.print(",mProcessingStartTime:" + mProcessingStartTime);
        writer.println(",mLastSleepEntryTime:" + mLastSleepEntryTime);
        writer.println("**PowerEventProcessingHandlers");
        for (PowerEventProcessingHandlerWrapper wrapper : mPowerEventProcessingHandlers) {
            writer.println(wrapper.toString());
        }
    }

    @Override
    public void onApPowerStateChange(PowerState state) {
        synchronized (this) {
            mPendingPowerStates.addFirst(state);
        }
        mHandler.handlePowerStateChange();
    }

    private void doHandlePowerStateChange() {
        PowerState state = null;
        synchronized (this) {
            state = mPendingPowerStates.peekFirst();
            mPendingPowerStates.clear();
            if (state == null) {
                return;
            }
            if (!needPowerStateChange(state)) {
                return;
            }
            // now real power change happens. Whatever was queued before should be all cancelled.
            releaseTimerLocked();
            mHandler.cancelProcessingComplete();
        }

        Log.i(CarLog.TAG_POWER, "Power state change:" + state);
        switch (state.state) {
            case PowerHalService.STATE_ON_DISP_OFF:
                handleDisplayOff(state);
                notifyPowerOn(false);
                break;
            case PowerHalService.STATE_ON_FULL:
                handleFullOn(state);
                notifyPowerOn(true);
                break;
            case PowerHalService.STATE_SHUTDOWN_PREPARE:
                handleShutdownPrepare(state);
                break;
        }
    }

    private void handleDisplayOff(PowerState newState) {
        setCurrentState(newState);
        mSystemInterface.setDisplayState(false);
    }

    private void handleFullOn(PowerState newState) {
        setCurrentState(newState);
        mSystemInterface.setDisplayState(true);
    }

    @VisibleForTesting
    protected void notifyPowerOn(boolean displayOn) {
        for (PowerEventProcessingHandlerWrapper wrapper : mPowerEventProcessingHandlers) {
            wrapper.callOnPowerOn(displayOn);
        }
    }

    @VisibleForTesting
    protected long notifyPrepareShutdown(boolean shuttingDown) {
        long processingTimeMs = 0;
        for (PowerEventProcessingHandlerWrapper wrapper : mPowerEventProcessingHandlers) {
            long handlerProcessingTime = wrapper.handler.onPrepareShutdown(shuttingDown);
            if (handlerProcessingTime > processingTimeMs) {
                processingTimeMs = handlerProcessingTime;
            }
        }
        return processingTimeMs;
    }

    private void handleShutdownPrepare(PowerState newState) {
        setCurrentState(newState);
        mSystemInterface.setDisplayState(false);;
        boolean shouldShutdown = true;
        if (mHal.isDeepSleepAllowed() && mSystemInterface.isSystemSupportingDeepSleep() &&
                newState.canEnterDeepSleep()) {
            Log.i(CarLog.TAG_POWER, "starting sleep");
            shouldShutdown = false;
            doHandlePreprocessing(shouldShutdown);
            return;
        } else if (newState.canPostponeShutdown()) {
            Log.i(CarLog.TAG_POWER, "starting shutdown with processing");
            doHandlePreprocessing(shouldShutdown);
        } else {
            Log.i(CarLog.TAG_POWER, "starting shutdown immediately");
            synchronized (this) {
                releaseTimerLocked();
            }
            doHandleShutdown();
        }
    }

    private void releaseTimerLocked() {
        if (mTimer != null) {
            mTimer.cancel();
        }
        mTimer = null;
    }

    private void doHandlePreprocessing(boolean shuttingDown) {
        long processingTimeMs = 0;
        for (PowerEventProcessingHandlerWrapper wrapper : mPowerEventProcessingHandlers) {
            long handlerProcessingTime = wrapper.handler.onPrepareShutdown(shuttingDown);
            if (handlerProcessingTime > 0) {
                wrapper.setProcessingTimeAndResetProcessingDone(handlerProcessingTime);
            }
            if (handlerProcessingTime > processingTimeMs) {
                processingTimeMs = handlerProcessingTime;
            }
        }
        if (processingTimeMs > 0) {
            int pollingCount = (int)(processingTimeMs / SHUTDOWN_POLLING_INTERVAL_MS) + 1;
            Log.i(CarLog.TAG_POWER, "processing before shutdown expected for :" + processingTimeMs +
                    " ms, adding polling:" + pollingCount);
            synchronized (this) {
                mProcessingStartTime = SystemClock.elapsedRealtime();
                releaseTimerLocked();
                mTimer = new Timer();
                mTimer.scheduleAtFixedRate(new ShutdownProcessingTimerTask(shuttingDown,
                        pollingCount),
                        0 /*delay*/,
                        SHUTDOWN_POLLING_INTERVAL_MS);
            }
        } else {
            mHandler.handleProcessingComplete(shuttingDown);
        }
    }

    private void doHandleDeepSleep() {
        // keep holding partial wakelock to prevent entering sleep before enterDeepSleep call
        // enterDeepSleep should force sleep entry even if wake lock is kept.
        mSystemInterface.switchToPartialWakeLock();
        mHandler.cancelProcessingComplete();
        for (PowerServiceEventListener listener : mListeners) {
            listener.onSleepEntry();
        }
        int wakeupTimeSec = getWakeupTime();
        mHal.sendSleepEntry();
        synchronized (this) {
            mLastSleepEntryTime = SystemClock.elapsedRealtime();
        }
        if (!shouldDoFakeShutdown()) { // if it is mocked, do not enter sleep.
            mSystemInterface.enterDeepSleep(wakeupTimeSec);
        }
        mHal.sendSleepExit();
        for (PowerServiceEventListener listener : mListeners) {
            listener.onSleepExit();
        }
        if (mSystemInterface.isWakeupCausedByTimer()) {
            doHandlePreprocessing(false /*shuttingDown*/);
        } else {
            PowerState currentState = mHal.getCurrentPowerState();
            if (needPowerStateChange(currentState)) {
                onApPowerStateChange(currentState);
            } else { // power controller woke-up but no power state change. Just shutdown.
                Log.w(CarLog.TAG_POWER, "external sleep wake up, but no power state change:" +
                        currentState);
                doHandleShutdown();
            }
        }
    }

    private void doHandleNotifyPowerOn() {
        boolean displayOn = false;
        synchronized (this) {
            if (mCurrentState != null && mCurrentState.state == PowerHalService.STATE_ON_FULL) {
                displayOn = true;
            }
        }
        for (PowerEventProcessingHandlerWrapper wrapper : mPowerEventProcessingHandlers) {
            // wrapper will not send it forward if it is already called.
            wrapper.callOnPowerOn(displayOn);
        }
    }

    private boolean needPowerStateChange(PowerState newState) {
        synchronized (this) {
            if (mCurrentState != null && mCurrentState.equals(newState)) {
                return false;
            }
            return true;
        }
    }

    private void doHandleShutdown() {
        // now shutdown
        for (PowerServiceEventListener listener : mListeners) {
            listener.onShutdown();
        }
        int wakeupTimeSec = 0;
        if (mHal.isTimedWakeupAllowed()) {
            wakeupTimeSec = getWakeupTime();
        }
        mHal.sendShutdownStart(wakeupTimeSec);
        if (!shouldDoFakeShutdown()) {
            mSystemInterface.shutdown();
        }
    }

    private int getWakeupTime() {
        int wakeupTimeSec = 0;
        for (PowerEventProcessingHandlerWrapper wrapper : mPowerEventProcessingHandlers) {
            int t = wrapper.handler.getWakeupTime();
            if (t > wakeupTimeSec) {
                wakeupTimeSec = t;
            }
        }
        return wakeupTimeSec;
    }

    private void doHandleProcessingComplete(boolean shutdownWhenCompleted) {
        synchronized (this) {
            releaseTimerLocked();
            if (!shutdownWhenCompleted && mLastSleepEntryTime > mProcessingStartTime) {
                // entered sleep after processing start. So this could be duplicate request.
                Log.w(CarLog.TAG_POWER, "Duplicate sleep entry request, ignore");
                return;
            }
        }
        if (shutdownWhenCompleted) {
            doHandleShutdown();
        } else {
            doHandleDeepSleep();
        }
    }

    private synchronized void setCurrentState(PowerState state) {
        mCurrentState = state;
    }

    @Override
    public void onDisplayBrightnessChange(int brightness) {
        // TODO
    }

    private void doHandleDisplayBrightnessChange(int brightness) {
        //TODO
    }

    private void doHandleMainDisplayStateChange(boolean on) {
        //TODO
    }

    private boolean shouldDoFakeShutdown() {
        ICarImpl carImpl = ICarImpl.getInstance(mContext);
        if (!carImpl.isInMocking()) {
            return false;
        }
        CarTestService testService = (CarTestService) carImpl.getCarService(Car.TEST_SERVICE);
        return !testService.shouldDoRealShutdownInMocking();
    }

    public void handleMainDisplayChanged(boolean on) {
        mHandler.handleMainDisplayStateChange(on);
    }

    public Handler getHandler() {
        return mHandler;
    }

    private class PowerHandler extends Handler {

        private final int MSG_POWER_STATE_CHANGE = 0;
        private final int MSG_DISPLAY_BRIGHTNESS_CHANGE = 1;
        private final int MSG_MAIN_DISPLAY_STATE_CHANGE = 2;
        private final int MSG_PROCESSING_COMPLETE = 3;
        private final int MSG_NOTIFY_POWER_ON = 4;

        // Do not handle this immediately but with some delay as there can be a race between
        // display off due to rear view camera and delivery to here.
        private final long MAIN_DISPLAY_EVENT_DELAY_MS = 500;

        private PowerHandler(Looper looper) {
            super(looper);
        }

        private void handlePowerStateChange() {
            Message msg = obtainMessage(MSG_POWER_STATE_CHANGE);
            sendMessage(msg);
        }

        private void handleDisplayBrightnessChange(int brightness) {
            Message msg = obtainMessage(MSG_DISPLAY_BRIGHTNESS_CHANGE, brightness, 0);
            sendMessage(msg);
        }

        private void handleMainDisplayStateChange(boolean on) {
            removeMessages(MSG_MAIN_DISPLAY_STATE_CHANGE);
            Message msg = obtainMessage(MSG_MAIN_DISPLAY_STATE_CHANGE, Boolean.valueOf(on));
            sendMessageDelayed(msg, MAIN_DISPLAY_EVENT_DELAY_MS);
        }

        private void handleProcessingComplete(boolean shutdownWhenCompleted) {
            removeMessages(MSG_PROCESSING_COMPLETE);
            Message msg = obtainMessage(MSG_PROCESSING_COMPLETE, shutdownWhenCompleted ? 1 : 0, 0);
            sendMessage(msg);
        }

        private void handlePowerOn() {
            Message msg = obtainMessage(MSG_NOTIFY_POWER_ON);
            sendMessage(msg);
        }

        private void cancelProcessingComplete() {
            removeMessages(MSG_PROCESSING_COMPLETE);
        }

        private void cancelAll() {
            removeMessages(MSG_POWER_STATE_CHANGE);
            removeMessages(MSG_DISPLAY_BRIGHTNESS_CHANGE);
            removeMessages(MSG_MAIN_DISPLAY_STATE_CHANGE);
            removeMessages(MSG_PROCESSING_COMPLETE);
            removeMessages(MSG_NOTIFY_POWER_ON);
        }

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_POWER_STATE_CHANGE:
                    doHandlePowerStateChange();
                    break;
                case MSG_DISPLAY_BRIGHTNESS_CHANGE:
                    doHandleDisplayBrightnessChange(msg.arg1);
                    break;
                case MSG_MAIN_DISPLAY_STATE_CHANGE:
                    doHandleMainDisplayStateChange((Boolean) msg.obj);
                    break;
                case MSG_PROCESSING_COMPLETE:
                    doHandleProcessingComplete(msg.arg1 == 1);
                    break;
                case MSG_NOTIFY_POWER_ON:
                    doHandleNotifyPowerOn();
                    break;
            }
        }
    }

    private static class SystemIntefaceImpl implements SystemInteface {

        private final PowerManager mPowerManager;
        private final DisplayManager mDisplayManager;
        private final WakeLock mFullWakeLock;
        private final WakeLock mPartialWakeLock;
        private final DisplayStateListener mDisplayListener;
        private CarPowerManagementService mService;
        private boolean mDisplayStateSet;

        private SystemIntefaceImpl(Context context) {
            mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
            mDisplayManager = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
            mFullWakeLock = mPowerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, CarLog.TAG_POWER);
            mPartialWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
                    CarLog.TAG_POWER);
            mDisplayListener = new DisplayStateListener();
        }

        @Override
        public void startDisplayStateMonitoring(CarPowerManagementService service) {
            synchronized (this) {
                mService = service;
                mDisplayStateSet = isMainDisplayOn();
            }
            mDisplayManager.registerDisplayListener(mDisplayListener, service.getHandler());
        }

        @Override
        public void stopDisplayStateMonitoring() {
            mDisplayManager.unregisterDisplayListener(mDisplayListener);
        }

        @Override
        public void setDisplayState(boolean on) {
            synchronized (this) {
                mDisplayStateSet = on;
            }
            if (on) {
                switchToFullWakeLock();
                Log.i(CarLog.TAG_POWER, "on display");
                mPowerManager.wakeUp(SystemClock.uptimeMillis());
            } else {
                switchToPartialWakeLock();
                Log.i(CarLog.TAG_POWER, "off display");
                mPowerManager.goToSleep(SystemClock.uptimeMillis());
            }
        }

        private boolean isMainDisplayOn() {
            Display disp = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY);
            return disp.getState() == Display.STATE_ON;
        }

        @Override
        public void shutdown() {
            mPowerManager.shutdown(false /* no confirm*/, null, true /* true */);
        }

        @Override
        public void enterDeepSleep(int wakeupTimeSec) {
            //TODO set wake up time
            mPowerManager.goToSleep(SystemClock.uptimeMillis(),
                    PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN,
                    PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
        }

        @Override
        public boolean isSystemSupportingDeepSleep() {
            //TODO should return by checking some kernel suspend control sysfs
            return false;
        }

        @Override
        public void switchToPartialWakeLock() {
            if (!mPartialWakeLock.isHeld()) {
                mPartialWakeLock.acquire();
            }
            if (mFullWakeLock.isHeld()) {
                mFullWakeLock.release();
            }
        }

        @Override
        public void switchToFullWakeLock() {
            if (!mFullWakeLock.isHeld()) {
                mFullWakeLock.acquire();
            }
            if (mPartialWakeLock.isHeld()) {
                mPartialWakeLock.release();
            }
        }

        @Override
        public void releaseAllWakeLocks() {
            if (mPartialWakeLock.isHeld()) {
                mPartialWakeLock.release();
            }
            if (mFullWakeLock.isHeld()) {
                mFullWakeLock.release();
            }
        }

        @Override
        public boolean isWakeupCausedByTimer() {
            //TODO check wake up reason and do necessary operation information should come from
            // kernel. it can be either power on or wake up for maintenance
            // power on will involve GPIO trigger from power controller
            // its own wakeup will involve timer expiration.
            return false;
        }

        private void handleMainDisplayChanged() {
            boolean isOn = isMainDisplayOn();
            CarPowerManagementService service;
            synchronized (this) {
                if (mDisplayStateSet == isOn) { // same as what is set
                    return;
                }
                service = mService;
            }
            service.handleMainDisplayChanged(isOn);
        }

        private class DisplayStateListener implements DisplayManager.DisplayListener {

            @Override
            public void onDisplayAdded(int displayId) {
                //ignore
            }

            @Override
            public void onDisplayChanged(int displayId) {
                if (displayId == Display.DEFAULT_DISPLAY) {
                    handleMainDisplayChanged();
                }
            }

            @Override
            public void onDisplayRemoved(int displayId) {
                //ignore
            }
        }
    }

    private class ShutdownProcessingTimerTask extends TimerTask {
        private final boolean mShutdownWhenCompleted;
        private final int mExpirationCount;
        private int mCurrentCount;

        private ShutdownProcessingTimerTask(boolean shutdownWhenCompleted, int expirationCount) {
            mShutdownWhenCompleted = shutdownWhenCompleted;
            mExpirationCount = expirationCount;
            mCurrentCount = 0;
        }

        @Override
        public void run() {
            mCurrentCount++;
            if (mCurrentCount > mExpirationCount) {
                synchronized (CarPowerManagementService.this) {
                    releaseTimerLocked();
                }
                mHandler.handleProcessingComplete(mShutdownWhenCompleted);
            } else {
                mHal.sendShutdownPostpone(SHUTDOWN_EXTEND_MAX_MS);
            }
        }
    }

    private static class PowerEventProcessingHandlerWrapper {
        public final PowerEventProcessingHandler handler;
        private long mProcessingTime = 0;
        private boolean mProcessingDone = true;
        private boolean mPowerOnSent = false;
        private int mLastDisplayState = -1;

        public PowerEventProcessingHandlerWrapper(PowerEventProcessingHandler handler) {
            this.handler = handler;
        }

        public synchronized void setProcessingTimeAndResetProcessingDone(long processingTime) {
            mProcessingTime = processingTime;
            mProcessingDone = false;
        }

        public synchronized long getProcessingTime() {
            return mProcessingTime;
        }

        public synchronized void markProcessingDone() {
            mProcessingDone = true;
        }

        public synchronized boolean isProcessingDone() {
            return mProcessingDone;
        }

        public void callOnPowerOn(boolean displayOn) {
            int newDisplayState = displayOn ? 1 : 0;
            boolean shouldCall = false;
            synchronized (this) {
                if (!mPowerOnSent || (mLastDisplayState != newDisplayState)) {
                    shouldCall = true;
                    mPowerOnSent = true;
                    mLastDisplayState = newDisplayState;
                }
            }
            if (shouldCall) {
                handler.onPowerOn(displayOn);
            }
        }

        @Override
        public String toString() {
            return "PowerEventProcessingHandlerWrapper [handler=" + handler + ", mProcessingTime="
                    + mProcessingTime + ", mProcessingDone=" + mProcessingDone + "]";
        }
    }
}
