14b0212c1b3576f4174c292bbcdd72815584ff075keunyoung/*
24b0212c1b3576f4174c292bbcdd72815584ff075keunyoung * Copyright (C) 2015 The Android Open Source Project
34b0212c1b3576f4174c292bbcdd72815584ff075keunyoung *
44b0212c1b3576f4174c292bbcdd72815584ff075keunyoung * Licensed under the Apache License, Version 2.0 (the "License");
54b0212c1b3576f4174c292bbcdd72815584ff075keunyoung * you may not use this file except in compliance with the License.
64b0212c1b3576f4174c292bbcdd72815584ff075keunyoung * You may obtain a copy of the License at
74b0212c1b3576f4174c292bbcdd72815584ff075keunyoung *
84b0212c1b3576f4174c292bbcdd72815584ff075keunyoung *      http://www.apache.org/licenses/LICENSE-2.0
94b0212c1b3576f4174c292bbcdd72815584ff075keunyoung *
104b0212c1b3576f4174c292bbcdd72815584ff075keunyoung * Unless required by applicable law or agreed to in writing, software
114b0212c1b3576f4174c292bbcdd72815584ff075keunyoung * distributed under the License is distributed on an "AS IS" BASIS,
124b0212c1b3576f4174c292bbcdd72815584ff075keunyoung * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134b0212c1b3576f4174c292bbcdd72815584ff075keunyoung * See the License for the specific language governing permissions and
144b0212c1b3576f4174c292bbcdd72815584ff075keunyoung * limitations under the License.
154b0212c1b3576f4174c292bbcdd72815584ff075keunyoung */
164b0212c1b3576f4174c292bbcdd72815584ff075keunyoungpackage com.android.car;
174b0212c1b3576f4174c292bbcdd72815584ff075keunyoung
184b0212c1b3576f4174c292bbcdd72815584ff075keunyoungimport android.os.Handler;
194b0212c1b3576f4174c292bbcdd72815584ff075keunyoungimport android.os.HandlerThread;
204b0212c1b3576f4174c292bbcdd72815584ff075keunyoungimport android.os.Looper;
214b0212c1b3576f4174c292bbcdd72815584ff075keunyoungimport android.os.Message;
224b0212c1b3576f4174c292bbcdd72815584ff075keunyoungimport android.os.SystemClock;
234b0212c1b3576f4174c292bbcdd72815584ff075keunyoungimport android.util.Log;
244b0212c1b3576f4174c292bbcdd72815584ff075keunyoung
254b0212c1b3576f4174c292bbcdd72815584ff075keunyoungimport com.android.car.hal.PowerHalService;
264b0212c1b3576f4174c292bbcdd72815584ff075keunyoungimport com.android.car.hal.PowerHalService.PowerState;
274b0212c1b3576f4174c292bbcdd72815584ff075keunyoungimport com.android.internal.annotations.GuardedBy;
28dacd724892d2d502127248685e15254905cbf0f6Yao Chenimport com.android.internal.annotations.VisibleForTesting;
294b0212c1b3576f4174c292bbcdd72815584ff075keunyoung
304b0212c1b3576f4174c292bbcdd72815584ff075keunyoungimport java.io.PrintWriter;
31fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Parkimport java.util.LinkedList;
324b0212c1b3576f4174c292bbcdd72815584ff075keunyoungimport java.util.Timer;
334b0212c1b3576f4174c292bbcdd72815584ff075keunyoungimport java.util.TimerTask;
344b0212c1b3576f4174c292bbcdd72815584ff075keunyoungimport java.util.concurrent.CopyOnWriteArrayList;
354b0212c1b3576f4174c292bbcdd72815584ff075keunyoung
364b0212c1b3576f4174c292bbcdd72815584ff075keunyoungpublic class CarPowerManagementService implements CarServiceBase,
374b0212c1b3576f4174c292bbcdd72815584ff075keunyoung    PowerHalService.PowerEventListener {
384b0212c1b3576f4174c292bbcdd72815584ff075keunyoung
394b0212c1b3576f4174c292bbcdd72815584ff075keunyoung    /**
404b0212c1b3576f4174c292bbcdd72815584ff075keunyoung     * Listener for other services to monitor power events.
414b0212c1b3576f4174c292bbcdd72815584ff075keunyoung     */
424b0212c1b3576f4174c292bbcdd72815584ff075keunyoung    public interface PowerServiceEventListener {
434b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        /**
444b0212c1b3576f4174c292bbcdd72815584ff075keunyoung         * Shutdown is happening
454b0212c1b3576f4174c292bbcdd72815584ff075keunyoung         */
464b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        void onShutdown();
474b0212c1b3576f4174c292bbcdd72815584ff075keunyoung
484b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        /**
494b0212c1b3576f4174c292bbcdd72815584ff075keunyoung         * Entering deep sleep.
504b0212c1b3576f4174c292bbcdd72815584ff075keunyoung         */
514b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        void onSleepEntry();
524b0212c1b3576f4174c292bbcdd72815584ff075keunyoung
534b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        /**
544b0212c1b3576f4174c292bbcdd72815584ff075keunyoung         * Got out of deep sleep.
554b0212c1b3576f4174c292bbcdd72815584ff075keunyoung         */
564b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        void onSleepExit();
574b0212c1b3576f4174c292bbcdd72815584ff075keunyoung    }
584b0212c1b3576f4174c292bbcdd72815584ff075keunyoung
594b0212c1b3576f4174c292bbcdd72815584ff075keunyoung    /**
604b0212c1b3576f4174c292bbcdd72815584ff075keunyoung     * Interface for components requiring processing time before shutting-down or
614b0212c1b3576f4174c292bbcdd72815584ff075keunyoung     * entering sleep, and wake-up after shut-down.
624b0212c1b3576f4174c292bbcdd72815584ff075keunyoung     */
634b0212c1b3576f4174c292bbcdd72815584ff075keunyoung    public interface PowerEventProcessingHandler {
644b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        /**
654b0212c1b3576f4174c292bbcdd72815584ff075keunyoung         * Called before shutdown or sleep entry to allow running some processing. This call
664b0212c1b3576f4174c292bbcdd72815584ff075keunyoung         * should only queue such task in different thread and should return quickly.
674b0212c1b3576f4174c292bbcdd72815584ff075keunyoung         * Blocking inside this call can trigger watchdog timer which can terminate the
684b0212c1b3576f4174c292bbcdd72815584ff075keunyoung         * whole system.
694b0212c1b3576f4174c292bbcdd72815584ff075keunyoung         * @param shuttingDown whether system is shutting down or not (= sleep entry).
704b0212c1b3576f4174c292bbcdd72815584ff075keunyoung         * @return time necessary to run processing in ms. should return 0 if there is no
714b0212c1b3576f4174c292bbcdd72815584ff075keunyoung         *         processing necessary.
724b0212c1b3576f4174c292bbcdd72815584ff075keunyoung         */
73303ea1da65548f363a98cd49a9de58d510073c8cKeun-young Park        long onPrepareShutdown(boolean shuttingDown);
74303ea1da65548f363a98cd49a9de58d510073c8cKeun-young Park
75303ea1da65548f363a98cd49a9de58d510073c8cKeun-young Park        /**
76303ea1da65548f363a98cd49a9de58d510073c8cKeun-young Park         * Called when power state is changed to ON state. Display can be either on or off.
77303ea1da65548f363a98cd49a9de58d510073c8cKeun-young Park         * @param displayOn
78303ea1da65548f363a98cd49a9de58d510073c8cKeun-young Park         */
79303ea1da65548f363a98cd49a9de58d510073c8cKeun-young Park        void onPowerOn(boolean displayOn);
804b0212c1b3576f4174c292bbcdd72815584ff075keunyoung
814b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        /**
824b0212c1b3576f4174c292bbcdd72815584ff075keunyoung         * Returns wake up time after system is fully shutdown. Power controller will power on
834b0212c1b3576f4174c292bbcdd72815584ff075keunyoung         * the system after this time. This power on is meant for regular maintenance kind of
844b0212c1b3576f4174c292bbcdd72815584ff075keunyoung         * operation.
854b0212c1b3576f4174c292bbcdd72815584ff075keunyoung         * @return 0 of wake up is not necessary.
864b0212c1b3576f4174c292bbcdd72815584ff075keunyoung         */
874b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        int getWakeupTime();
884b0212c1b3576f4174c292bbcdd72815584ff075keunyoung    }
894b0212c1b3576f4174c292bbcdd72815584ff075keunyoung
904b0212c1b3576f4174c292bbcdd72815584ff075keunyoung    private final PowerHalService mHal;
910d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev    private final SystemInterface mSystemInterface;
92fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park
934b0212c1b3576f4174c292bbcdd72815584ff075keunyoung    private final CopyOnWriteArrayList<PowerServiceEventListener> mListeners =
944b0212c1b3576f4174c292bbcdd72815584ff075keunyoung            new CopyOnWriteArrayList<>();
95fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park    private final CopyOnWriteArrayList<PowerEventProcessingHandlerWrapper>
96fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            mPowerEventProcessingHandlers = new CopyOnWriteArrayList<>();
97fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park
98fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park    @GuardedBy("this")
994b0212c1b3576f4174c292bbcdd72815584ff075keunyoung    private PowerState mCurrentState;
100fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park    @GuardedBy("this")
1014b0212c1b3576f4174c292bbcdd72815584ff075keunyoung    private Timer mTimer;
102fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park    @GuardedBy("this")
103fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park    private long mProcessingStartTime;
104fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park    @GuardedBy("this")
105fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park    private long mLastSleepEntryTime;
106fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park    @GuardedBy("this")
107fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park    private final LinkedList<PowerState> mPendingPowerStates = new LinkedList<>();
108ddbff98a7c62b2c02dd0849ff8d6d54015a6f944Pavel Maltsev    @GuardedBy("this")
109ddbff98a7c62b2c02dd0849ff8d6d54015a6f944Pavel Maltsev    private HandlerThread mHandlerThread;
110ddbff98a7c62b2c02dd0849ff8d6d54015a6f944Pavel Maltsev    @GuardedBy("this")
111ddbff98a7c62b2c02dd0849ff8d6d54015a6f944Pavel Maltsev    private PowerHandler mHandler;
1124b0212c1b3576f4174c292bbcdd72815584ff075keunyoung
1130d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev    private final static int SHUTDOWN_POLLING_INTERVAL_MS = 2000;
1140d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev    private final static int SHUTDOWN_EXTEND_MAX_MS = 5000;
115fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park
1160d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev    public CarPowerManagementService(PowerHalService powerHal, SystemInterface systemInterface) {
117fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        mHal = powerHal;
118fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        mSystemInterface = systemInterface;
1194b0212c1b3576f4174c292bbcdd72815584ff075keunyoung    }
1204b0212c1b3576f4174c292bbcdd72815584ff075keunyoung
121dacd724892d2d502127248685e15254905cbf0f6Yao Chen    /**
122fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park     * Create a dummy instance for unit testing purpose only. Instance constructed in this way
123fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park     * is not safe as members expected to be non-null are null.
124dacd724892d2d502127248685e15254905cbf0f6Yao Chen     */
125dacd724892d2d502127248685e15254905cbf0f6Yao Chen    @VisibleForTesting
126dacd724892d2d502127248685e15254905cbf0f6Yao Chen    protected CarPowerManagementService() {
127dacd724892d2d502127248685e15254905cbf0f6Yao Chen        mHal = null;
128fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        mSystemInterface = null;
129dacd724892d2d502127248685e15254905cbf0f6Yao Chen        mHandlerThread = null;
130ca013ae5c9881fa078387c3ee97760f81d163e5cKeun-young Park        mHandler = new PowerHandler(Looper.getMainLooper());
131dacd724892d2d502127248685e15254905cbf0f6Yao Chen    }
132dacd724892d2d502127248685e15254905cbf0f6Yao Chen
1334b0212c1b3576f4174c292bbcdd72815584ff075keunyoung    @Override
1344b0212c1b3576f4174c292bbcdd72815584ff075keunyoung    public void init() {
135ddbff98a7c62b2c02dd0849ff8d6d54015a6f944Pavel Maltsev        synchronized (this) {
136ddbff98a7c62b2c02dd0849ff8d6d54015a6f944Pavel Maltsev            mHandlerThread = new HandlerThread(CarLog.TAG_POWER);
137ddbff98a7c62b2c02dd0849ff8d6d54015a6f944Pavel Maltsev            mHandlerThread.start();
138ddbff98a7c62b2c02dd0849ff8d6d54015a6f944Pavel Maltsev            mHandler = new PowerHandler(mHandlerThread.getLooper());
139ddbff98a7c62b2c02dd0849ff8d6d54015a6f944Pavel Maltsev        }
140ddbff98a7c62b2c02dd0849ff8d6d54015a6f944Pavel Maltsev
1414b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        mHal.setListener(this);
1424b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        if (mHal.isPowerStateSupported()) {
1434b0212c1b3576f4174c292bbcdd72815584ff075keunyoung            mHal.sendBootComplete();
1444b0212c1b3576f4174c292bbcdd72815584ff075keunyoung            PowerState currentState = mHal.getCurrentPowerState();
1450d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev            if (currentState != null) {
1460d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev                onApPowerStateChange(currentState);
1470d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev            } else {
1480d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev                Log.w(CarLog.TAG_POWER, "Unable to get get current power state during "
1490d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev                        + "initialization");
1500d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev            }
1514b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        } else {
1524b0212c1b3576f4174c292bbcdd72815584ff075keunyoung            Log.w(CarLog.TAG_POWER, "Vehicle hal does not support power state yet.");
153fad5792e3c083e9e370ad8999ea2176be65841e2Keun-young Park            onApPowerStateChange(new PowerState(PowerHalService.STATE_ON_FULL, 0));
154fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            mSystemInterface.switchToFullWakeLock();
1554b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        }
156fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        mSystemInterface.startDisplayStateMonitoring(this);
1574b0212c1b3576f4174c292bbcdd72815584ff075keunyoung    }
1584b0212c1b3576f4174c292bbcdd72815584ff075keunyoung
1594b0212c1b3576f4174c292bbcdd72815584ff075keunyoung    @Override
1604b0212c1b3576f4174c292bbcdd72815584ff075keunyoung    public void release() {
161ddbff98a7c62b2c02dd0849ff8d6d54015a6f944Pavel Maltsev        HandlerThread handlerThread;
162fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        synchronized (this) {
1634b0212c1b3576f4174c292bbcdd72815584ff075keunyoung            releaseTimerLocked();
1644b0212c1b3576f4174c292bbcdd72815584ff075keunyoung            mCurrentState = null;
165ddbff98a7c62b2c02dd0849ff8d6d54015a6f944Pavel Maltsev            mHandler.cancelAll();
166ddbff98a7c62b2c02dd0849ff8d6d54015a6f944Pavel Maltsev            handlerThread = mHandlerThread;
167ddbff98a7c62b2c02dd0849ff8d6d54015a6f944Pavel Maltsev        }
168ddbff98a7c62b2c02dd0849ff8d6d54015a6f944Pavel Maltsev        handlerThread.quitSafely();
169ddbff98a7c62b2c02dd0849ff8d6d54015a6f944Pavel Maltsev        try {
170ddbff98a7c62b2c02dd0849ff8d6d54015a6f944Pavel Maltsev            handlerThread.join(1000);
171ddbff98a7c62b2c02dd0849ff8d6d54015a6f944Pavel Maltsev        } catch (InterruptedException e) {
172ddbff98a7c62b2c02dd0849ff8d6d54015a6f944Pavel Maltsev            Log.e(CarLog.TAG_POWER, "Timeout while joining for handler thread to join.");
1734b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        }
174fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        mSystemInterface.stopDisplayStateMonitoring();
1754b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        mListeners.clear();
176303ea1da65548f363a98cd49a9de58d510073c8cKeun-young Park        mPowerEventProcessingHandlers.clear();
177fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        mSystemInterface.releaseAllWakeLocks();
1784b0212c1b3576f4174c292bbcdd72815584ff075keunyoung    }
1794b0212c1b3576f4174c292bbcdd72815584ff075keunyoung
1804b0212c1b3576f4174c292bbcdd72815584ff075keunyoung    /**
1814b0212c1b3576f4174c292bbcdd72815584ff075keunyoung     * Register listener to monitor power event. There is no unregister counter-part and the list
1824b0212c1b3576f4174c292bbcdd72815584ff075keunyoung     * will be cleared when the service is released.
1834b0212c1b3576f4174c292bbcdd72815584ff075keunyoung     * @param listener
1844b0212c1b3576f4174c292bbcdd72815584ff075keunyoung     */
185fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park    public synchronized void registerPowerEventListener(PowerServiceEventListener listener) {
1864b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        mListeners.add(listener);
1874b0212c1b3576f4174c292bbcdd72815584ff075keunyoung    }
1884b0212c1b3576f4174c292bbcdd72815584ff075keunyoung
1894b0212c1b3576f4174c292bbcdd72815584ff075keunyoung    /**
1904b0212c1b3576f4174c292bbcdd72815584ff075keunyoung     * Register PowerEventPreprocessingHandler to run pre-processing before shutdown or
1914b0212c1b3576f4174c292bbcdd72815584ff075keunyoung     * sleep entry. There is no unregister counter-part and the list
1924b0212c1b3576f4174c292bbcdd72815584ff075keunyoung     * will be cleared when the service is released.
1934b0212c1b3576f4174c292bbcdd72815584ff075keunyoung     * @param handler
1944b0212c1b3576f4174c292bbcdd72815584ff075keunyoung     */
195fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park    public synchronized void registerPowerEventProcessingHandler(
196fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            PowerEventProcessingHandler handler) {
197fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        mPowerEventProcessingHandlers.add(new PowerEventProcessingHandlerWrapper(handler));
198fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        // onPowerOn will not be called if power on notification is already done inside the
199fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        // handler thread. So request it once again here. Wrapper will have its own
200fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        // gatekeeping to prevent calling onPowerOn twice.
201fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        mHandler.handlePowerOn();
2024b0212c1b3576f4174c292bbcdd72815584ff075keunyoung    }
2034b0212c1b3576f4174c292bbcdd72815584ff075keunyoung
2044b0212c1b3576f4174c292bbcdd72815584ff075keunyoung    /**
2054b0212c1b3576f4174c292bbcdd72815584ff075keunyoung     * Notifies earlier completion of power event processing. PowerEventProcessingHandler quotes
2064b0212c1b3576f4174c292bbcdd72815584ff075keunyoung     * time necessary from onPrePowerEvent() call, but actual processing can finish earlier than
2074b0212c1b3576f4174c292bbcdd72815584ff075keunyoung     * that, and this call can be called in such case to trigger shutdown without waiting further.
2084b0212c1b3576f4174c292bbcdd72815584ff075keunyoung     *
2094b0212c1b3576f4174c292bbcdd72815584ff075keunyoung     * @param handler PowerEventProcessingHandler that was already registered with
2104b0212c1b3576f4174c292bbcdd72815584ff075keunyoung     *        {@link #registerPowerEventListener(PowerServiceEventListener)} call. If it was not
2114b0212c1b3576f4174c292bbcdd72815584ff075keunyoung     *        registered before, this call will be ignored.
2124b0212c1b3576f4174c292bbcdd72815584ff075keunyoung     */
2134b0212c1b3576f4174c292bbcdd72815584ff075keunyoung    public void notifyPowerEventProcessingCompletion(PowerEventProcessingHandler handler) {
214fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        long processingTime = 0;
215fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        for (PowerEventProcessingHandlerWrapper wrapper : mPowerEventProcessingHandlers) {
216fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            if (wrapper.handler == handler) {
217fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park                wrapper.markProcessingDone();
218fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            } else if (!wrapper.isProcessingDone()) {
219fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park                processingTime = Math.max(processingTime, wrapper.getProcessingTime());
220fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            }
221fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        }
222fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        long now = SystemClock.elapsedRealtime();
223fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        long startTime;
224fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        boolean shouldShutdown = true;
225ddbff98a7c62b2c02dd0849ff8d6d54015a6f944Pavel Maltsev        PowerHandler powerHandler;
226fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        synchronized (this) {
227fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            startTime = mProcessingStartTime;
228fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            if (mCurrentState == null) {
229fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park                return;
230fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            }
2310d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev            if (mCurrentState.mState != PowerHalService.STATE_SHUTDOWN_PREPARE) {
232fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park                return;
233fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            }
234fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            if (mCurrentState.canEnterDeepSleep()) {
235fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park                shouldShutdown = false;
236fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park                if (mLastSleepEntryTime > mProcessingStartTime && mLastSleepEntryTime < now) {
237fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park                    // already slept
238fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park                    return;
239fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park                }
240fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            }
241ddbff98a7c62b2c02dd0849ff8d6d54015a6f944Pavel Maltsev            powerHandler = mHandler;
242fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        }
243fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        if ((startTime + processingTime) <= now) {
244fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            Log.i(CarLog.TAG_POWER, "Processing all done");
245ddbff98a7c62b2c02dd0849ff8d6d54015a6f944Pavel Maltsev            powerHandler.handleProcessingComplete(shouldShutdown);
246fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        }
2474b0212c1b3576f4174c292bbcdd72815584ff075keunyoung    }
2484b0212c1b3576f4174c292bbcdd72815584ff075keunyoung
2494b0212c1b3576f4174c292bbcdd72815584ff075keunyoung    @Override
2504b0212c1b3576f4174c292bbcdd72815584ff075keunyoung    public void dump(PrintWriter writer) {
2514b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        writer.println("*PowerManagementService*");
252fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        writer.print("mCurrentState:" + mCurrentState);
253fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        writer.print(",mProcessingStartTime:" + mProcessingStartTime);
254fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        writer.println(",mLastSleepEntryTime:" + mLastSleepEntryTime);
255fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        writer.println("**PowerEventProcessingHandlers");
256fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        for (PowerEventProcessingHandlerWrapper wrapper : mPowerEventProcessingHandlers) {
257fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            writer.println(wrapper.toString());
258fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        }
2594b0212c1b3576f4174c292bbcdd72815584ff075keunyoung    }
2604b0212c1b3576f4174c292bbcdd72815584ff075keunyoung
2614b0212c1b3576f4174c292bbcdd72815584ff075keunyoung    @Override
2624b0212c1b3576f4174c292bbcdd72815584ff075keunyoung    public void onApPowerStateChange(PowerState state) {
263ddbff98a7c62b2c02dd0849ff8d6d54015a6f944Pavel Maltsev        PowerHandler handler;
264fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        synchronized (this) {
265fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            mPendingPowerStates.addFirst(state);
266ddbff98a7c62b2c02dd0849ff8d6d54015a6f944Pavel Maltsev            handler = mHandler;
267fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        }
268ddbff98a7c62b2c02dd0849ff8d6d54015a6f944Pavel Maltsev        handler.handlePowerStateChange();
2694b0212c1b3576f4174c292bbcdd72815584ff075keunyoung    }
2704b0212c1b3576f4174c292bbcdd72815584ff075keunyoung
271fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park    private void doHandlePowerStateChange() {
272fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        PowerState state = null;
273ddbff98a7c62b2c02dd0849ff8d6d54015a6f944Pavel Maltsev        PowerHandler handler;
274fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        synchronized (this) {
275fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            state = mPendingPowerStates.peekFirst();
276fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            mPendingPowerStates.clear();
277fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            if (state == null) {
278fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park                return;
279fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            }
280fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            if (!needPowerStateChange(state)) {
281fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park                return;
282fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            }
283fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            // now real power change happens. Whatever was queued before should be all cancelled.
284fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            releaseTimerLocked();
285ddbff98a7c62b2c02dd0849ff8d6d54015a6f944Pavel Maltsev            handler = mHandler;
2864b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        }
287ddbff98a7c62b2c02dd0849ff8d6d54015a6f944Pavel Maltsev        handler.cancelProcessingComplete();
288fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park
2894b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        Log.i(CarLog.TAG_POWER, "Power state change:" + state);
2900d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        switch (state.mState) {
2914b0212c1b3576f4174c292bbcdd72815584ff075keunyoung            case PowerHalService.STATE_ON_DISP_OFF:
2924b0212c1b3576f4174c292bbcdd72815584ff075keunyoung                handleDisplayOff(state);
293303ea1da65548f363a98cd49a9de58d510073c8cKeun-young Park                notifyPowerOn(false);
2944b0212c1b3576f4174c292bbcdd72815584ff075keunyoung                break;
2954b0212c1b3576f4174c292bbcdd72815584ff075keunyoung            case PowerHalService.STATE_ON_FULL:
2961f4d6a7b960e66116de0c1ccb90f900275cff207Keun-young Park                handleFullOn(state);
2971f4d6a7b960e66116de0c1ccb90f900275cff207Keun-young Park                notifyPowerOn(true);
2984b0212c1b3576f4174c292bbcdd72815584ff075keunyoung                break;
2994b0212c1b3576f4174c292bbcdd72815584ff075keunyoung            case PowerHalService.STATE_SHUTDOWN_PREPARE:
3004b0212c1b3576f4174c292bbcdd72815584ff075keunyoung                handleShutdownPrepare(state);
3014b0212c1b3576f4174c292bbcdd72815584ff075keunyoung                break;
3024b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        }
3034b0212c1b3576f4174c292bbcdd72815584ff075keunyoung    }
3044b0212c1b3576f4174c292bbcdd72815584ff075keunyoung
3054b0212c1b3576f4174c292bbcdd72815584ff075keunyoung    private void handleDisplayOff(PowerState newState) {
3064b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        setCurrentState(newState);
307fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        mSystemInterface.setDisplayState(false);
3084b0212c1b3576f4174c292bbcdd72815584ff075keunyoung    }
3094b0212c1b3576f4174c292bbcdd72815584ff075keunyoung
3104b0212c1b3576f4174c292bbcdd72815584ff075keunyoung    private void handleFullOn(PowerState newState) {
3114b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        setCurrentState(newState);
312fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        mSystemInterface.setDisplayState(true);
3134b0212c1b3576f4174c292bbcdd72815584ff075keunyoung    }
3144b0212c1b3576f4174c292bbcdd72815584ff075keunyoung
315dacd724892d2d502127248685e15254905cbf0f6Yao Chen    @VisibleForTesting
316dacd724892d2d502127248685e15254905cbf0f6Yao Chen    protected void notifyPowerOn(boolean displayOn) {
317fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        for (PowerEventProcessingHandlerWrapper wrapper : mPowerEventProcessingHandlers) {
318fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            wrapper.callOnPowerOn(displayOn);
319fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        }
320fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park    }
321fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park
322fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park    @VisibleForTesting
323fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park    protected long notifyPrepareShutdown(boolean shuttingDown) {
324fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        long processingTimeMs = 0;
325fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        for (PowerEventProcessingHandlerWrapper wrapper : mPowerEventProcessingHandlers) {
326fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            long handlerProcessingTime = wrapper.handler.onPrepareShutdown(shuttingDown);
327fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            if (handlerProcessingTime > processingTimeMs) {
328fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park                processingTimeMs = handlerProcessingTime;
329fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            }
330303ea1da65548f363a98cd49a9de58d510073c8cKeun-young Park        }
331fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        return processingTimeMs;
332303ea1da65548f363a98cd49a9de58d510073c8cKeun-young Park    }
333303ea1da65548f363a98cd49a9de58d510073c8cKeun-young Park
3344b0212c1b3576f4174c292bbcdd72815584ff075keunyoung    private void handleShutdownPrepare(PowerState newState) {
3354b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        setCurrentState(newState);
336fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        mSystemInterface.setDisplayState(false);;
3374b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        boolean shouldShutdown = true;
338fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        if (mHal.isDeepSleepAllowed() && mSystemInterface.isSystemSupportingDeepSleep() &&
3394b0212c1b3576f4174c292bbcdd72815584ff075keunyoung                newState.canEnterDeepSleep()) {
3404b0212c1b3576f4174c292bbcdd72815584ff075keunyoung            Log.i(CarLog.TAG_POWER, "starting sleep");
3414b0212c1b3576f4174c292bbcdd72815584ff075keunyoung            shouldShutdown = false;
3424b0212c1b3576f4174c292bbcdd72815584ff075keunyoung            doHandlePreprocessing(shouldShutdown);
3434b0212c1b3576f4174c292bbcdd72815584ff075keunyoung            return;
3444b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        } else if (newState.canPostponeShutdown()) {
3454b0212c1b3576f4174c292bbcdd72815584ff075keunyoung            Log.i(CarLog.TAG_POWER, "starting shutdown with processing");
3464b0212c1b3576f4174c292bbcdd72815584ff075keunyoung            doHandlePreprocessing(shouldShutdown);
3474b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        } else {
3484b0212c1b3576f4174c292bbcdd72815584ff075keunyoung            Log.i(CarLog.TAG_POWER, "starting shutdown immediately");
349fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            synchronized (this) {
3504b0212c1b3576f4174c292bbcdd72815584ff075keunyoung                releaseTimerLocked();
3514b0212c1b3576f4174c292bbcdd72815584ff075keunyoung            }
3524b0212c1b3576f4174c292bbcdd72815584ff075keunyoung            doHandleShutdown();
3534b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        }
3544b0212c1b3576f4174c292bbcdd72815584ff075keunyoung    }
3554b0212c1b3576f4174c292bbcdd72815584ff075keunyoung
3564b0212c1b3576f4174c292bbcdd72815584ff075keunyoung    private void releaseTimerLocked() {
3574b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        if (mTimer != null) {
3584b0212c1b3576f4174c292bbcdd72815584ff075keunyoung            mTimer.cancel();
3594b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        }
3604b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        mTimer = null;
3614b0212c1b3576f4174c292bbcdd72815584ff075keunyoung    }
3624b0212c1b3576f4174c292bbcdd72815584ff075keunyoung
3634b0212c1b3576f4174c292bbcdd72815584ff075keunyoung    private void doHandlePreprocessing(boolean shuttingDown) {
3644b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        long processingTimeMs = 0;
365fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        for (PowerEventProcessingHandlerWrapper wrapper : mPowerEventProcessingHandlers) {
366fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            long handlerProcessingTime = wrapper.handler.onPrepareShutdown(shuttingDown);
367fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            if (handlerProcessingTime > 0) {
368fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park                wrapper.setProcessingTimeAndResetProcessingDone(handlerProcessingTime);
369fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            }
3704b0212c1b3576f4174c292bbcdd72815584ff075keunyoung            if (handlerProcessingTime > processingTimeMs) {
3714b0212c1b3576f4174c292bbcdd72815584ff075keunyoung                processingTimeMs = handlerProcessingTime;
3724b0212c1b3576f4174c292bbcdd72815584ff075keunyoung            }
3734b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        }
3744b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        if (processingTimeMs > 0) {
375fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            int pollingCount = (int)(processingTimeMs / SHUTDOWN_POLLING_INTERVAL_MS) + 1;
3764b0212c1b3576f4174c292bbcdd72815584ff075keunyoung            Log.i(CarLog.TAG_POWER, "processing before shutdown expected for :" + processingTimeMs +
3774b0212c1b3576f4174c292bbcdd72815584ff075keunyoung                    " ms, adding polling:" + pollingCount);
3784b0212c1b3576f4174c292bbcdd72815584ff075keunyoung            synchronized (this) {
379fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park                mProcessingStartTime = SystemClock.elapsedRealtime();
3804b0212c1b3576f4174c292bbcdd72815584ff075keunyoung                releaseTimerLocked();
3814b0212c1b3576f4174c292bbcdd72815584ff075keunyoung                mTimer = new Timer();
3824b0212c1b3576f4174c292bbcdd72815584ff075keunyoung                mTimer.scheduleAtFixedRate(new ShutdownProcessingTimerTask(shuttingDown,
3834b0212c1b3576f4174c292bbcdd72815584ff075keunyoung                        pollingCount),
3844b0212c1b3576f4174c292bbcdd72815584ff075keunyoung                        0 /*delay*/,
3854b0212c1b3576f4174c292bbcdd72815584ff075keunyoung                        SHUTDOWN_POLLING_INTERVAL_MS);
3864b0212c1b3576f4174c292bbcdd72815584ff075keunyoung            }
3874b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        } else {
388ddbff98a7c62b2c02dd0849ff8d6d54015a6f944Pavel Maltsev            PowerHandler handler;
389ddbff98a7c62b2c02dd0849ff8d6d54015a6f944Pavel Maltsev            synchronized (this) {
390ddbff98a7c62b2c02dd0849ff8d6d54015a6f944Pavel Maltsev                handler = mHandler;
391ddbff98a7c62b2c02dd0849ff8d6d54015a6f944Pavel Maltsev            }
392ddbff98a7c62b2c02dd0849ff8d6d54015a6f944Pavel Maltsev            handler.handleProcessingComplete(shuttingDown);
3934b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        }
3944b0212c1b3576f4174c292bbcdd72815584ff075keunyoung    }
3954b0212c1b3576f4174c292bbcdd72815584ff075keunyoung
3964b0212c1b3576f4174c292bbcdd72815584ff075keunyoung    private void doHandleDeepSleep() {
3979d4cf620be374c0d68c2b2abb8a2a11869ed1c9eKeun-young Park        // keep holding partial wakelock to prevent entering sleep before enterDeepSleep call
3989d4cf620be374c0d68c2b2abb8a2a11869ed1c9eKeun-young Park        // enterDeepSleep should force sleep entry even if wake lock is kept.
3999d4cf620be374c0d68c2b2abb8a2a11869ed1c9eKeun-young Park        mSystemInterface.switchToPartialWakeLock();
400ddbff98a7c62b2c02dd0849ff8d6d54015a6f944Pavel Maltsev        PowerHandler handler;
401ddbff98a7c62b2c02dd0849ff8d6d54015a6f944Pavel Maltsev        synchronized (this) {
402ddbff98a7c62b2c02dd0849ff8d6d54015a6f944Pavel Maltsev            handler = mHandler;
403ddbff98a7c62b2c02dd0849ff8d6d54015a6f944Pavel Maltsev        }
404ddbff98a7c62b2c02dd0849ff8d6d54015a6f944Pavel Maltsev        handler.cancelProcessingComplete();
4054b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        for (PowerServiceEventListener listener : mListeners) {
4064b0212c1b3576f4174c292bbcdd72815584ff075keunyoung            listener.onSleepEntry();
4074b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        }
4084b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        int wakeupTimeSec = getWakeupTime();
4094b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        mHal.sendSleepEntry();
410fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        synchronized (this) {
411fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            mLastSleepEntryTime = SystemClock.elapsedRealtime();
412fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        }
4130d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        mSystemInterface.enterDeepSleep(wakeupTimeSec);
4144b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        mHal.sendSleepExit();
4154b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        for (PowerServiceEventListener listener : mListeners) {
4164b0212c1b3576f4174c292bbcdd72815584ff075keunyoung            listener.onSleepExit();
4174b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        }
418fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        if (mSystemInterface.isWakeupCausedByTimer()) {
4194b0212c1b3576f4174c292bbcdd72815584ff075keunyoung            doHandlePreprocessing(false /*shuttingDown*/);
4204b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        } else {
4214b0212c1b3576f4174c292bbcdd72815584ff075keunyoung            PowerState currentState = mHal.getCurrentPowerState();
4220d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev            if (currentState != null && needPowerStateChange(currentState)) {
423fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park                onApPowerStateChange(currentState);
4244b0212c1b3576f4174c292bbcdd72815584ff075keunyoung            } else { // power controller woke-up but no power state change. Just shutdown.
425fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park                Log.w(CarLog.TAG_POWER, "external sleep wake up, but no power state change:" +
4264b0212c1b3576f4174c292bbcdd72815584ff075keunyoung                        currentState);
4274b0212c1b3576f4174c292bbcdd72815584ff075keunyoung                doHandleShutdown();
4284b0212c1b3576f4174c292bbcdd72815584ff075keunyoung            }
4294b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        }
4304b0212c1b3576f4174c292bbcdd72815584ff075keunyoung    }
4314b0212c1b3576f4174c292bbcdd72815584ff075keunyoung
432fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park    private void doHandleNotifyPowerOn() {
433fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        boolean displayOn = false;
434fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        synchronized (this) {
4350d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev            if (mCurrentState != null && mCurrentState.mState == PowerHalService.STATE_ON_FULL) {
436fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park                displayOn = true;
437fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            }
438fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        }
439fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        for (PowerEventProcessingHandlerWrapper wrapper : mPowerEventProcessingHandlers) {
440fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            // wrapper will not send it forward if it is already called.
441fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            wrapper.callOnPowerOn(displayOn);
442fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        }
443fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park    }
444fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park
445fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park    private boolean needPowerStateChange(PowerState newState) {
446fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        synchronized (this) {
4474b0212c1b3576f4174c292bbcdd72815584ff075keunyoung            if (mCurrentState != null && mCurrentState.equals(newState)) {
4484b0212c1b3576f4174c292bbcdd72815584ff075keunyoung                return false;
4494b0212c1b3576f4174c292bbcdd72815584ff075keunyoung            }
4504b0212c1b3576f4174c292bbcdd72815584ff075keunyoung            return true;
4514b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        }
4524b0212c1b3576f4174c292bbcdd72815584ff075keunyoung    }
4534b0212c1b3576f4174c292bbcdd72815584ff075keunyoung
4544b0212c1b3576f4174c292bbcdd72815584ff075keunyoung    private void doHandleShutdown() {
4554b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        // now shutdown
4564b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        for (PowerServiceEventListener listener : mListeners) {
4574b0212c1b3576f4174c292bbcdd72815584ff075keunyoung            listener.onShutdown();
4584b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        }
4594b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        int wakeupTimeSec = 0;
4604b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        if (mHal.isTimedWakeupAllowed()) {
4614b0212c1b3576f4174c292bbcdd72815584ff075keunyoung            wakeupTimeSec = getWakeupTime();
4624b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        }
4634b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        mHal.sendShutdownStart(wakeupTimeSec);
4640d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        mSystemInterface.shutdown();
4654b0212c1b3576f4174c292bbcdd72815584ff075keunyoung    }
4664b0212c1b3576f4174c292bbcdd72815584ff075keunyoung
4674b0212c1b3576f4174c292bbcdd72815584ff075keunyoung    private int getWakeupTime() {
4684b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        int wakeupTimeSec = 0;
469fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        for (PowerEventProcessingHandlerWrapper wrapper : mPowerEventProcessingHandlers) {
470fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            int t = wrapper.handler.getWakeupTime();
4714b0212c1b3576f4174c292bbcdd72815584ff075keunyoung            if (t > wakeupTimeSec) {
4724b0212c1b3576f4174c292bbcdd72815584ff075keunyoung                wakeupTimeSec = t;
4734b0212c1b3576f4174c292bbcdd72815584ff075keunyoung            }
4744b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        }
4754b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        return wakeupTimeSec;
4764b0212c1b3576f4174c292bbcdd72815584ff075keunyoung    }
4774b0212c1b3576f4174c292bbcdd72815584ff075keunyoung
4784b0212c1b3576f4174c292bbcdd72815584ff075keunyoung    private void doHandleProcessingComplete(boolean shutdownWhenCompleted) {
479fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        synchronized (this) {
4804b0212c1b3576f4174c292bbcdd72815584ff075keunyoung            releaseTimerLocked();
481fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            if (!shutdownWhenCompleted && mLastSleepEntryTime > mProcessingStartTime) {
482fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park                // entered sleep after processing start. So this could be duplicate request.
483fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park                Log.w(CarLog.TAG_POWER, "Duplicate sleep entry request, ignore");
484fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park                return;
485fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            }
4864b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        }
4874b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        if (shutdownWhenCompleted) {
4884b0212c1b3576f4174c292bbcdd72815584ff075keunyoung            doHandleShutdown();
4894b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        } else {
4904b0212c1b3576f4174c292bbcdd72815584ff075keunyoung            doHandleDeepSleep();
4914b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        }
4924b0212c1b3576f4174c292bbcdd72815584ff075keunyoung    }
4934b0212c1b3576f4174c292bbcdd72815584ff075keunyoung
4944b0212c1b3576f4174c292bbcdd72815584ff075keunyoung    private synchronized void setCurrentState(PowerState state) {
4954b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        mCurrentState = state;
4964b0212c1b3576f4174c292bbcdd72815584ff075keunyoung    }
4974b0212c1b3576f4174c292bbcdd72815584ff075keunyoung
4984b0212c1b3576f4174c292bbcdd72815584ff075keunyoung    @Override
4994b0212c1b3576f4174c292bbcdd72815584ff075keunyoung    public void onDisplayBrightnessChange(int brightness) {
500f9215209e0f425d2fc570bef37dad959c82d2e9eKeun-young Park        // TODO bug: 32065231
5014b0212c1b3576f4174c292bbcdd72815584ff075keunyoung    }
5024b0212c1b3576f4174c292bbcdd72815584ff075keunyoung
5034b0212c1b3576f4174c292bbcdd72815584ff075keunyoung    private void doHandleDisplayBrightnessChange(int brightness) {
504f9215209e0f425d2fc570bef37dad959c82d2e9eKeun-young Park        //TODO bug: 32065231
5054b0212c1b3576f4174c292bbcdd72815584ff075keunyoung    }
5064b0212c1b3576f4174c292bbcdd72815584ff075keunyoung
507fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park    private void doHandleMainDisplayStateChange(boolean on) {
508f9215209e0f425d2fc570bef37dad959c82d2e9eKeun-young Park        //TODO bug: 32065231
5094b0212c1b3576f4174c292bbcdd72815584ff075keunyoung    }
5104b0212c1b3576f4174c292bbcdd72815584ff075keunyoung
511fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park    public void handleMainDisplayChanged(boolean on) {
512ddbff98a7c62b2c02dd0849ff8d6d54015a6f944Pavel Maltsev        PowerHandler handler;
513ddbff98a7c62b2c02dd0849ff8d6d54015a6f944Pavel Maltsev        synchronized (this) {
514ddbff98a7c62b2c02dd0849ff8d6d54015a6f944Pavel Maltsev            handler = mHandler;
515ddbff98a7c62b2c02dd0849ff8d6d54015a6f944Pavel Maltsev        }
516ddbff98a7c62b2c02dd0849ff8d6d54015a6f944Pavel Maltsev        handler.handleMainDisplayStateChange(on);
517fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park    }
518fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park
519ddbff98a7c62b2c02dd0849ff8d6d54015a6f944Pavel Maltsev    public synchronized Handler getHandler() {
520fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        return mHandler;
521fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park    }
522fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park
5234b0212c1b3576f4174c292bbcdd72815584ff075keunyoung    private class PowerHandler extends Handler {
5244b0212c1b3576f4174c292bbcdd72815584ff075keunyoung
5254b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        private final int MSG_POWER_STATE_CHANGE = 0;
5264b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        private final int MSG_DISPLAY_BRIGHTNESS_CHANGE = 1;
5274b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        private final int MSG_MAIN_DISPLAY_STATE_CHANGE = 2;
5284b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        private final int MSG_PROCESSING_COMPLETE = 3;
529fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        private final int MSG_NOTIFY_POWER_ON = 4;
5304b0212c1b3576f4174c292bbcdd72815584ff075keunyoung
5314b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        // Do not handle this immediately but with some delay as there can be a race between
5324b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        // display off due to rear view camera and delivery to here.
5334b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        private final long MAIN_DISPLAY_EVENT_DELAY_MS = 500;
5344b0212c1b3576f4174c292bbcdd72815584ff075keunyoung
5354b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        private PowerHandler(Looper looper) {
5364b0212c1b3576f4174c292bbcdd72815584ff075keunyoung            super(looper);
5374b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        }
5384b0212c1b3576f4174c292bbcdd72815584ff075keunyoung
539fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        private void handlePowerStateChange() {
540fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            Message msg = obtainMessage(MSG_POWER_STATE_CHANGE);
5414b0212c1b3576f4174c292bbcdd72815584ff075keunyoung            sendMessage(msg);
5424b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        }
5434b0212c1b3576f4174c292bbcdd72815584ff075keunyoung
5444b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        private void handleDisplayBrightnessChange(int brightness) {
5454b0212c1b3576f4174c292bbcdd72815584ff075keunyoung            Message msg = obtainMessage(MSG_DISPLAY_BRIGHTNESS_CHANGE, brightness, 0);
5464b0212c1b3576f4174c292bbcdd72815584ff075keunyoung            sendMessage(msg);
5474b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        }
5484b0212c1b3576f4174c292bbcdd72815584ff075keunyoung
549fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        private void handleMainDisplayStateChange(boolean on) {
5504b0212c1b3576f4174c292bbcdd72815584ff075keunyoung            removeMessages(MSG_MAIN_DISPLAY_STATE_CHANGE);
551fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            Message msg = obtainMessage(MSG_MAIN_DISPLAY_STATE_CHANGE, Boolean.valueOf(on));
5524b0212c1b3576f4174c292bbcdd72815584ff075keunyoung            sendMessageDelayed(msg, MAIN_DISPLAY_EVENT_DELAY_MS);
5534b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        }
5544b0212c1b3576f4174c292bbcdd72815584ff075keunyoung
5554b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        private void handleProcessingComplete(boolean shutdownWhenCompleted) {
556fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            removeMessages(MSG_PROCESSING_COMPLETE);
5574b0212c1b3576f4174c292bbcdd72815584ff075keunyoung            Message msg = obtainMessage(MSG_PROCESSING_COMPLETE, shutdownWhenCompleted ? 1 : 0, 0);
5584b0212c1b3576f4174c292bbcdd72815584ff075keunyoung            sendMessage(msg);
5594b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        }
5604b0212c1b3576f4174c292bbcdd72815584ff075keunyoung
561fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        private void handlePowerOn() {
562fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            Message msg = obtainMessage(MSG_NOTIFY_POWER_ON);
563fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            sendMessage(msg);
564fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        }
565fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park
566fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        private void cancelProcessingComplete() {
567fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            removeMessages(MSG_PROCESSING_COMPLETE);
568fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        }
569fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park
5704b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        private void cancelAll() {
5714b0212c1b3576f4174c292bbcdd72815584ff075keunyoung            removeMessages(MSG_POWER_STATE_CHANGE);
5724b0212c1b3576f4174c292bbcdd72815584ff075keunyoung            removeMessages(MSG_DISPLAY_BRIGHTNESS_CHANGE);
5734b0212c1b3576f4174c292bbcdd72815584ff075keunyoung            removeMessages(MSG_MAIN_DISPLAY_STATE_CHANGE);
5744b0212c1b3576f4174c292bbcdd72815584ff075keunyoung            removeMessages(MSG_PROCESSING_COMPLETE);
575fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            removeMessages(MSG_NOTIFY_POWER_ON);
5764b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        }
5774b0212c1b3576f4174c292bbcdd72815584ff075keunyoung
5784b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        @Override
5794b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        public void handleMessage(Message msg) {
5804b0212c1b3576f4174c292bbcdd72815584ff075keunyoung            switch (msg.what) {
5814b0212c1b3576f4174c292bbcdd72815584ff075keunyoung                case MSG_POWER_STATE_CHANGE:
582fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park                    doHandlePowerStateChange();
5834b0212c1b3576f4174c292bbcdd72815584ff075keunyoung                    break;
5844b0212c1b3576f4174c292bbcdd72815584ff075keunyoung                case MSG_DISPLAY_BRIGHTNESS_CHANGE:
5854b0212c1b3576f4174c292bbcdd72815584ff075keunyoung                    doHandleDisplayBrightnessChange(msg.arg1);
5864b0212c1b3576f4174c292bbcdd72815584ff075keunyoung                    break;
5874b0212c1b3576f4174c292bbcdd72815584ff075keunyoung                case MSG_MAIN_DISPLAY_STATE_CHANGE:
588fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park                    doHandleMainDisplayStateChange((Boolean) msg.obj);
5891f4d6a7b960e66116de0c1ccb90f900275cff207Keun-young Park                    break;
5904b0212c1b3576f4174c292bbcdd72815584ff075keunyoung                case MSG_PROCESSING_COMPLETE:
5914b0212c1b3576f4174c292bbcdd72815584ff075keunyoung                    doHandleProcessingComplete(msg.arg1 == 1);
5924b0212c1b3576f4174c292bbcdd72815584ff075keunyoung                    break;
593fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park                case MSG_NOTIFY_POWER_ON:
594fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park                    doHandleNotifyPowerOn();
595fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park                    break;
5964b0212c1b3576f4174c292bbcdd72815584ff075keunyoung            }
5974b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        }
5984b0212c1b3576f4174c292bbcdd72815584ff075keunyoung    }
5994b0212c1b3576f4174c292bbcdd72815584ff075keunyoung
6004b0212c1b3576f4174c292bbcdd72815584ff075keunyoung    private class ShutdownProcessingTimerTask extends TimerTask {
6014b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        private final boolean mShutdownWhenCompleted;
6024b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        private final int mExpirationCount;
6034b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        private int mCurrentCount;
6044b0212c1b3576f4174c292bbcdd72815584ff075keunyoung
6054b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        private ShutdownProcessingTimerTask(boolean shutdownWhenCompleted, int expirationCount) {
6064b0212c1b3576f4174c292bbcdd72815584ff075keunyoung            mShutdownWhenCompleted = shutdownWhenCompleted;
6074b0212c1b3576f4174c292bbcdd72815584ff075keunyoung            mExpirationCount = expirationCount;
6084b0212c1b3576f4174c292bbcdd72815584ff075keunyoung            mCurrentCount = 0;
6094b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        }
6104b0212c1b3576f4174c292bbcdd72815584ff075keunyoung
6114b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        @Override
6124b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        public void run() {
6134b0212c1b3576f4174c292bbcdd72815584ff075keunyoung            mCurrentCount++;
6144b0212c1b3576f4174c292bbcdd72815584ff075keunyoung            if (mCurrentCount > mExpirationCount) {
615ddbff98a7c62b2c02dd0849ff8d6d54015a6f944Pavel Maltsev                PowerHandler handler;
616fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park                synchronized (CarPowerManagementService.this) {
6174b0212c1b3576f4174c292bbcdd72815584ff075keunyoung                    releaseTimerLocked();
618ddbff98a7c62b2c02dd0849ff8d6d54015a6f944Pavel Maltsev                    handler = mHandler;
6194b0212c1b3576f4174c292bbcdd72815584ff075keunyoung                }
620ddbff98a7c62b2c02dd0849ff8d6d54015a6f944Pavel Maltsev                handler.handleProcessingComplete(mShutdownWhenCompleted);
6214b0212c1b3576f4174c292bbcdd72815584ff075keunyoung            } else {
6224b0212c1b3576f4174c292bbcdd72815584ff075keunyoung                mHal.sendShutdownPostpone(SHUTDOWN_EXTEND_MAX_MS);
6234b0212c1b3576f4174c292bbcdd72815584ff075keunyoung            }
6244b0212c1b3576f4174c292bbcdd72815584ff075keunyoung        }
6254b0212c1b3576f4174c292bbcdd72815584ff075keunyoung    }
626fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park
627fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park    private static class PowerEventProcessingHandlerWrapper {
628fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        public final PowerEventProcessingHandler handler;
629fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        private long mProcessingTime = 0;
630fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        private boolean mProcessingDone = true;
631fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        private boolean mPowerOnSent = false;
632d73afaeb1c4c64ddad94e696a0fd88147888dee1Keun-young Park        private int mLastDisplayState = -1;
633fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park
634fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        public PowerEventProcessingHandlerWrapper(PowerEventProcessingHandler handler) {
635fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            this.handler = handler;
636fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        }
637fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park
638fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        public synchronized void setProcessingTimeAndResetProcessingDone(long processingTime) {
639fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            mProcessingTime = processingTime;
640fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            mProcessingDone = false;
641fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        }
642fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park
643fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        public synchronized long getProcessingTime() {
644fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            return mProcessingTime;
645fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        }
646fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park
647fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        public synchronized void markProcessingDone() {
648fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            mProcessingDone = true;
649fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        }
650fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park
651fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        public synchronized boolean isProcessingDone() {
652fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            return mProcessingDone;
653fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        }
654fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park
655fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        public void callOnPowerOn(boolean displayOn) {
656d73afaeb1c4c64ddad94e696a0fd88147888dee1Keun-young Park            int newDisplayState = displayOn ? 1 : 0;
657fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            boolean shouldCall = false;
658fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            synchronized (this) {
659d73afaeb1c4c64ddad94e696a0fd88147888dee1Keun-young Park                if (!mPowerOnSent || (mLastDisplayState != newDisplayState)) {
660fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park                    shouldCall = true;
661fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park                    mPowerOnSent = true;
662d73afaeb1c4c64ddad94e696a0fd88147888dee1Keun-young Park                    mLastDisplayState = newDisplayState;
663fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park                }
664fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            }
665fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            if (shouldCall) {
666fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park                handler.onPowerOn(displayOn);
667fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            }
668fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        }
669fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park
670fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        @Override
671fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        public String toString() {
672fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park            return "PowerEventProcessingHandlerWrapper [handler=" + handler + ", mProcessingTime="
673fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park                    + mProcessingTime + ", mProcessingDone=" + mProcessingDone + "]";
674fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park        }
675fd3fbf7875685aa59330fac32d45e3fff414f6d0Keun-young Park    }
6764b0212c1b3576f4174c292bbcdd72815584ff075keunyoung}
677