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