blob: 8b9d3bea72759119ace010cd741a20d23dc3216e [file] [log] [blame]
keunyoung4b0212c2015-10-29 17:11:57 -07001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package com.android.car;
17
keunyoung4b0212c2015-10-29 17:11:57 -070018import android.os.Handler;
19import android.os.HandlerThread;
20import android.os.Looper;
21import android.os.Message;
keunyoung4b0212c2015-10-29 17:11:57 -070022import android.os.SystemClock;
keunyoung4b0212c2015-10-29 17:11:57 -070023import android.util.Log;
keunyoung4b0212c2015-10-29 17:11:57 -070024
25import com.android.car.hal.PowerHalService;
26import com.android.car.hal.PowerHalService.PowerState;
Enrico Granatab19bc322017-10-12 12:25:06 -070027import com.android.car.systeminterface.SystemInterface;
keunyoung4b0212c2015-10-29 17:11:57 -070028import com.android.internal.annotations.GuardedBy;
Yao Chendacd7242016-01-26 14:42:42 -080029import com.android.internal.annotations.VisibleForTesting;
keunyoung4b0212c2015-10-29 17:11:57 -070030
31import java.io.PrintWriter;
Keun-young Parkfd3fbf72016-01-22 17:00:17 -080032import java.util.LinkedList;
keunyoung4b0212c2015-10-29 17:11:57 -070033import java.util.Timer;
34import java.util.TimerTask;
35import java.util.concurrent.CopyOnWriteArrayList;
36
37public class CarPowerManagementService implements CarServiceBase,
38 PowerHalService.PowerEventListener {
39
40 /**
41 * Listener for other services to monitor power events.
42 */
43 public interface PowerServiceEventListener {
44 /**
45 * Shutdown is happening
46 */
47 void onShutdown();
48
49 /**
50 * Entering deep sleep.
51 */
52 void onSleepEntry();
53
54 /**
55 * Got out of deep sleep.
56 */
57 void onSleepExit();
58 }
59
60 /**
61 * Interface for components requiring processing time before shutting-down or
62 * entering sleep, and wake-up after shut-down.
63 */
64 public interface PowerEventProcessingHandler {
65 /**
66 * Called before shutdown or sleep entry to allow running some processing. This call
67 * should only queue such task in different thread and should return quickly.
68 * Blocking inside this call can trigger watchdog timer which can terminate the
69 * whole system.
70 * @param shuttingDown whether system is shutting down or not (= sleep entry).
71 * @return time necessary to run processing in ms. should return 0 if there is no
72 * processing necessary.
73 */
Keun-young Park303ea1d2016-01-21 11:26:16 -080074 long onPrepareShutdown(boolean shuttingDown);
75
76 /**
77 * Called when power state is changed to ON state. Display can be either on or off.
78 * @param displayOn
79 */
80 void onPowerOn(boolean displayOn);
keunyoung4b0212c2015-10-29 17:11:57 -070081
82 /**
83 * Returns wake up time after system is fully shutdown. Power controller will power on
84 * the system after this time. This power on is meant for regular maintenance kind of
85 * operation.
86 * @return 0 of wake up is not necessary.
87 */
88 int getWakeupTime();
89 }
90
keunyoung4b0212c2015-10-29 17:11:57 -070091 private final PowerHalService mHal;
Pavel Maltsev0d07c762016-11-03 16:40:15 -070092 private final SystemInterface mSystemInterface;
Keun-young Parkfd3fbf72016-01-22 17:00:17 -080093
keunyoung4b0212c2015-10-29 17:11:57 -070094 private final CopyOnWriteArrayList<PowerServiceEventListener> mListeners =
95 new CopyOnWriteArrayList<>();
Keun-young Parkfd3fbf72016-01-22 17:00:17 -080096 private final CopyOnWriteArrayList<PowerEventProcessingHandlerWrapper>
97 mPowerEventProcessingHandlers = new CopyOnWriteArrayList<>();
98
99 @GuardedBy("this")
keunyoung4b0212c2015-10-29 17:11:57 -0700100 private PowerState mCurrentState;
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800101 @GuardedBy("this")
keunyoung4b0212c2015-10-29 17:11:57 -0700102 private Timer mTimer;
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800103 @GuardedBy("this")
104 private long mProcessingStartTime;
105 @GuardedBy("this")
106 private long mLastSleepEntryTime;
107 @GuardedBy("this")
108 private final LinkedList<PowerState> mPendingPowerStates = new LinkedList<>();
Pavel Maltsevddbff982017-03-22 14:49:02 -0700109 @GuardedBy("this")
110 private HandlerThread mHandlerThread;
111 @GuardedBy("this")
112 private PowerHandler mHandler;
keunyoung4b0212c2015-10-29 17:11:57 -0700113
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700114 private final static int SHUTDOWN_POLLING_INTERVAL_MS = 2000;
115 private final static int SHUTDOWN_EXTEND_MAX_MS = 5000;
keunyoung4b0212c2015-10-29 17:11:57 -0700116
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700117 public CarPowerManagementService(PowerHalService powerHal, SystemInterface systemInterface) {
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800118 mHal = powerHal;
119 mSystemInterface = systemInterface;
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800120 }
121
122 /**
123 * Create a dummy instance for unit testing purpose only. Instance constructed in this way
124 * is not safe as members expected to be non-null are null.
Yao Chendacd7242016-01-26 14:42:42 -0800125 */
126 @VisibleForTesting
127 protected CarPowerManagementService() {
Yao Chendacd7242016-01-26 14:42:42 -0800128 mHal = null;
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800129 mSystemInterface = null;
Yao Chendacd7242016-01-26 14:42:42 -0800130 mHandlerThread = null;
Keun-young Parkca013ae2016-02-10 16:22:25 -0800131 mHandler = new PowerHandler(Looper.getMainLooper());
Yao Chendacd7242016-01-26 14:42:42 -0800132 }
133
keunyoung4b0212c2015-10-29 17:11:57 -0700134 @Override
135 public void init() {
Pavel Maltsevddbff982017-03-22 14:49:02 -0700136 synchronized (this) {
137 mHandlerThread = new HandlerThread(CarLog.TAG_POWER);
138 mHandlerThread.start();
139 mHandler = new PowerHandler(mHandlerThread.getLooper());
140 }
141
keunyoung4b0212c2015-10-29 17:11:57 -0700142 mHal.setListener(this);
143 if (mHal.isPowerStateSupported()) {
144 mHal.sendBootComplete();
145 PowerState currentState = mHal.getCurrentPowerState();
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700146 if (currentState != null) {
147 onApPowerStateChange(currentState);
148 } else {
149 Log.w(CarLog.TAG_POWER, "Unable to get get current power state during "
150 + "initialization");
151 }
keunyoung4b0212c2015-10-29 17:11:57 -0700152 } else {
153 Log.w(CarLog.TAG_POWER, "Vehicle hal does not support power state yet.");
Keun-young Parkfad57922016-04-21 11:00:45 -0700154 onApPowerStateChange(new PowerState(PowerHalService.STATE_ON_FULL, 0));
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800155 mSystemInterface.switchToFullWakeLock();
keunyoung4b0212c2015-10-29 17:11:57 -0700156 }
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800157 mSystemInterface.startDisplayStateMonitoring(this);
keunyoung4b0212c2015-10-29 17:11:57 -0700158 }
159
160 @Override
161 public void release() {
Pavel Maltsevddbff982017-03-22 14:49:02 -0700162 HandlerThread handlerThread;
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800163 synchronized (this) {
keunyoung4b0212c2015-10-29 17:11:57 -0700164 releaseTimerLocked();
165 mCurrentState = null;
Pavel Maltsevddbff982017-03-22 14:49:02 -0700166 mHandler.cancelAll();
167 handlerThread = mHandlerThread;
168 }
169 handlerThread.quitSafely();
170 try {
171 handlerThread.join(1000);
172 } catch (InterruptedException e) {
173 Log.e(CarLog.TAG_POWER, "Timeout while joining for handler thread to join.");
keunyoung4b0212c2015-10-29 17:11:57 -0700174 }
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800175 mSystemInterface.stopDisplayStateMonitoring();
keunyoung4b0212c2015-10-29 17:11:57 -0700176 mListeners.clear();
Keun-young Park303ea1d2016-01-21 11:26:16 -0800177 mPowerEventProcessingHandlers.clear();
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800178 mSystemInterface.releaseAllWakeLocks();
keunyoung4b0212c2015-10-29 17:11:57 -0700179 }
180
181 /**
182 * Register listener to monitor power event. There is no unregister counter-part and the list
183 * will be cleared when the service is released.
184 * @param listener
185 */
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800186 public synchronized void registerPowerEventListener(PowerServiceEventListener listener) {
keunyoung4b0212c2015-10-29 17:11:57 -0700187 mListeners.add(listener);
188 }
189
190 /**
191 * Register PowerEventPreprocessingHandler to run pre-processing before shutdown or
192 * sleep entry. There is no unregister counter-part and the list
193 * will be cleared when the service is released.
194 * @param handler
195 */
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800196 public synchronized void registerPowerEventProcessingHandler(
197 PowerEventProcessingHandler handler) {
198 mPowerEventProcessingHandlers.add(new PowerEventProcessingHandlerWrapper(handler));
199 // onPowerOn will not be called if power on notification is already done inside the
200 // handler thread. So request it once again here. Wrapper will have its own
201 // gatekeeping to prevent calling onPowerOn twice.
202 mHandler.handlePowerOn();
keunyoung4b0212c2015-10-29 17:11:57 -0700203 }
204
205 /**
206 * Notifies earlier completion of power event processing. PowerEventProcessingHandler quotes
207 * time necessary from onPrePowerEvent() call, but actual processing can finish earlier than
208 * that, and this call can be called in such case to trigger shutdown without waiting further.
209 *
210 * @param handler PowerEventProcessingHandler that was already registered with
211 * {@link #registerPowerEventListener(PowerServiceEventListener)} call. If it was not
212 * registered before, this call will be ignored.
213 */
214 public void notifyPowerEventProcessingCompletion(PowerEventProcessingHandler handler) {
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800215 long processingTime = 0;
216 for (PowerEventProcessingHandlerWrapper wrapper : mPowerEventProcessingHandlers) {
217 if (wrapper.handler == handler) {
218 wrapper.markProcessingDone();
219 } else if (!wrapper.isProcessingDone()) {
220 processingTime = Math.max(processingTime, wrapper.getProcessingTime());
221 }
222 }
223 long now = SystemClock.elapsedRealtime();
224 long startTime;
225 boolean shouldShutdown = true;
Pavel Maltsevddbff982017-03-22 14:49:02 -0700226 PowerHandler powerHandler;
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800227 synchronized (this) {
228 startTime = mProcessingStartTime;
229 if (mCurrentState == null) {
230 return;
231 }
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700232 if (mCurrentState.mState != PowerHalService.STATE_SHUTDOWN_PREPARE) {
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800233 return;
234 }
235 if (mCurrentState.canEnterDeepSleep()) {
236 shouldShutdown = false;
237 if (mLastSleepEntryTime > mProcessingStartTime && mLastSleepEntryTime < now) {
238 // already slept
239 return;
240 }
241 }
Pavel Maltsevddbff982017-03-22 14:49:02 -0700242 powerHandler = mHandler;
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800243 }
244 if ((startTime + processingTime) <= now) {
245 Log.i(CarLog.TAG_POWER, "Processing all done");
Pavel Maltsevddbff982017-03-22 14:49:02 -0700246 powerHandler.handleProcessingComplete(shouldShutdown);
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800247 }
keunyoung4b0212c2015-10-29 17:11:57 -0700248 }
249
250 @Override
251 public void dump(PrintWriter writer) {
252 writer.println("*PowerManagementService*");
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800253 writer.print("mCurrentState:" + mCurrentState);
254 writer.print(",mProcessingStartTime:" + mProcessingStartTime);
255 writer.println(",mLastSleepEntryTime:" + mLastSleepEntryTime);
256 writer.println("**PowerEventProcessingHandlers");
257 for (PowerEventProcessingHandlerWrapper wrapper : mPowerEventProcessingHandlers) {
258 writer.println(wrapper.toString());
259 }
keunyoung4b0212c2015-10-29 17:11:57 -0700260 }
261
262 @Override
Steve Paik110f95f2017-11-22 14:44:05 -0800263 public void onBootReasonReceived(int bootReason) {
264 // TODO: Implement me
265 }
266
267 @Override
keunyoung4b0212c2015-10-29 17:11:57 -0700268 public void onApPowerStateChange(PowerState state) {
Pavel Maltsevddbff982017-03-22 14:49:02 -0700269 PowerHandler handler;
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800270 synchronized (this) {
271 mPendingPowerStates.addFirst(state);
Pavel Maltsevddbff982017-03-22 14:49:02 -0700272 handler = mHandler;
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800273 }
Pavel Maltsevddbff982017-03-22 14:49:02 -0700274 handler.handlePowerStateChange();
keunyoung4b0212c2015-10-29 17:11:57 -0700275 }
276
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800277 private void doHandlePowerStateChange() {
278 PowerState state = null;
Pavel Maltsevddbff982017-03-22 14:49:02 -0700279 PowerHandler handler;
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800280 synchronized (this) {
281 state = mPendingPowerStates.peekFirst();
282 mPendingPowerStates.clear();
283 if (state == null) {
284 return;
285 }
286 if (!needPowerStateChange(state)) {
287 return;
288 }
289 // now real power change happens. Whatever was queued before should be all cancelled.
290 releaseTimerLocked();
Pavel Maltsevddbff982017-03-22 14:49:02 -0700291 handler = mHandler;
keunyoung4b0212c2015-10-29 17:11:57 -0700292 }
Pavel Maltsevddbff982017-03-22 14:49:02 -0700293 handler.cancelProcessingComplete();
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800294
keunyoung4b0212c2015-10-29 17:11:57 -0700295 Log.i(CarLog.TAG_POWER, "Power state change:" + state);
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700296 switch (state.mState) {
keunyoung4b0212c2015-10-29 17:11:57 -0700297 case PowerHalService.STATE_ON_DISP_OFF:
298 handleDisplayOff(state);
Keun-young Park303ea1d2016-01-21 11:26:16 -0800299 notifyPowerOn(false);
keunyoung4b0212c2015-10-29 17:11:57 -0700300 break;
301 case PowerHalService.STATE_ON_FULL:
Keun-young Park1f4d6a72016-02-11 09:49:47 -0800302 handleFullOn(state);
303 notifyPowerOn(true);
keunyoung4b0212c2015-10-29 17:11:57 -0700304 break;
305 case PowerHalService.STATE_SHUTDOWN_PREPARE:
306 handleShutdownPrepare(state);
307 break;
308 }
309 }
310
311 private void handleDisplayOff(PowerState newState) {
312 setCurrentState(newState);
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800313 mSystemInterface.setDisplayState(false);
keunyoung4b0212c2015-10-29 17:11:57 -0700314 }
315
316 private void handleFullOn(PowerState newState) {
317 setCurrentState(newState);
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800318 mSystemInterface.setDisplayState(true);
keunyoung4b0212c2015-10-29 17:11:57 -0700319 }
320
Yao Chendacd7242016-01-26 14:42:42 -0800321 @VisibleForTesting
322 protected void notifyPowerOn(boolean displayOn) {
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800323 for (PowerEventProcessingHandlerWrapper wrapper : mPowerEventProcessingHandlers) {
324 wrapper.callOnPowerOn(displayOn);
Keun-young Park303ea1d2016-01-21 11:26:16 -0800325 }
326 }
327
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800328 @VisibleForTesting
329 protected long notifyPrepareShutdown(boolean shuttingDown) {
330 long processingTimeMs = 0;
331 for (PowerEventProcessingHandlerWrapper wrapper : mPowerEventProcessingHandlers) {
332 long handlerProcessingTime = wrapper.handler.onPrepareShutdown(shuttingDown);
333 if (handlerProcessingTime > processingTimeMs) {
334 processingTimeMs = handlerProcessingTime;
335 }
336 }
337 return processingTimeMs;
338 }
339
keunyoung4b0212c2015-10-29 17:11:57 -0700340 private void handleShutdownPrepare(PowerState newState) {
341 setCurrentState(newState);
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800342 mSystemInterface.setDisplayState(false);;
keunyoung4b0212c2015-10-29 17:11:57 -0700343 boolean shouldShutdown = true;
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800344 if (mHal.isDeepSleepAllowed() && mSystemInterface.isSystemSupportingDeepSleep() &&
keunyoung4b0212c2015-10-29 17:11:57 -0700345 newState.canEnterDeepSleep()) {
346 Log.i(CarLog.TAG_POWER, "starting sleep");
347 shouldShutdown = false;
348 doHandlePreprocessing(shouldShutdown);
349 return;
350 } else if (newState.canPostponeShutdown()) {
351 Log.i(CarLog.TAG_POWER, "starting shutdown with processing");
352 doHandlePreprocessing(shouldShutdown);
353 } else {
354 Log.i(CarLog.TAG_POWER, "starting shutdown immediately");
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800355 synchronized (this) {
keunyoung4b0212c2015-10-29 17:11:57 -0700356 releaseTimerLocked();
357 }
358 doHandleShutdown();
359 }
360 }
361
Andreas Gampe985ca2f2018-02-09 12:57:54 -0800362 @GuardedBy("this")
keunyoung4b0212c2015-10-29 17:11:57 -0700363 private void releaseTimerLocked() {
364 if (mTimer != null) {
365 mTimer.cancel();
366 }
367 mTimer = null;
368 }
369
370 private void doHandlePreprocessing(boolean shuttingDown) {
371 long processingTimeMs = 0;
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800372 for (PowerEventProcessingHandlerWrapper wrapper : mPowerEventProcessingHandlers) {
373 long handlerProcessingTime = wrapper.handler.onPrepareShutdown(shuttingDown);
374 if (handlerProcessingTime > 0) {
375 wrapper.setProcessingTimeAndResetProcessingDone(handlerProcessingTime);
376 }
keunyoung4b0212c2015-10-29 17:11:57 -0700377 if (handlerProcessingTime > processingTimeMs) {
378 processingTimeMs = handlerProcessingTime;
379 }
380 }
381 if (processingTimeMs > 0) {
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800382 int pollingCount = (int)(processingTimeMs / SHUTDOWN_POLLING_INTERVAL_MS) + 1;
keunyoung4b0212c2015-10-29 17:11:57 -0700383 Log.i(CarLog.TAG_POWER, "processing before shutdown expected for :" + processingTimeMs +
384 " ms, adding polling:" + pollingCount);
385 synchronized (this) {
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800386 mProcessingStartTime = SystemClock.elapsedRealtime();
keunyoung4b0212c2015-10-29 17:11:57 -0700387 releaseTimerLocked();
388 mTimer = new Timer();
389 mTimer.scheduleAtFixedRate(new ShutdownProcessingTimerTask(shuttingDown,
390 pollingCount),
391 0 /*delay*/,
392 SHUTDOWN_POLLING_INTERVAL_MS);
393 }
394 } else {
Pavel Maltsevddbff982017-03-22 14:49:02 -0700395 PowerHandler handler;
396 synchronized (this) {
397 handler = mHandler;
398 }
399 handler.handleProcessingComplete(shuttingDown);
keunyoung4b0212c2015-10-29 17:11:57 -0700400 }
401 }
402
403 private void doHandleDeepSleep() {
Keun-young Park9d4cf622016-08-04 13:24:28 -0700404 // keep holding partial wakelock to prevent entering sleep before enterDeepSleep call
405 // enterDeepSleep should force sleep entry even if wake lock is kept.
406 mSystemInterface.switchToPartialWakeLock();
Pavel Maltsevddbff982017-03-22 14:49:02 -0700407 PowerHandler handler;
408 synchronized (this) {
409 handler = mHandler;
410 }
411 handler.cancelProcessingComplete();
keunyoung4b0212c2015-10-29 17:11:57 -0700412 for (PowerServiceEventListener listener : mListeners) {
413 listener.onSleepEntry();
414 }
415 int wakeupTimeSec = getWakeupTime();
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800416 mHal.sendSleepEntry();
417 synchronized (this) {
418 mLastSleepEntryTime = SystemClock.elapsedRealtime();
419 }
Steve Paik0f9fc002018-02-09 17:42:00 -0800420 if (mSystemInterface.enterDeepSleep(wakeupTimeSec) == false) {
421 // System did not suspend. Need to shutdown
422 // TODO: Shutdown gracefully
423 }
keunyoung4b0212c2015-10-29 17:11:57 -0700424 mHal.sendSleepExit();
425 for (PowerServiceEventListener listener : mListeners) {
426 listener.onSleepExit();
427 }
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800428 if (mSystemInterface.isWakeupCausedByTimer()) {
keunyoung4b0212c2015-10-29 17:11:57 -0700429 doHandlePreprocessing(false /*shuttingDown*/);
430 } else {
431 PowerState currentState = mHal.getCurrentPowerState();
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700432 if (currentState != null && needPowerStateChange(currentState)) {
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800433 onApPowerStateChange(currentState);
keunyoung4b0212c2015-10-29 17:11:57 -0700434 } else { // power controller woke-up but no power state change. Just shutdown.
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800435 Log.w(CarLog.TAG_POWER, "external sleep wake up, but no power state change:" +
keunyoung4b0212c2015-10-29 17:11:57 -0700436 currentState);
437 doHandleShutdown();
438 }
439 }
440 }
441
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800442 private void doHandleNotifyPowerOn() {
443 boolean displayOn = false;
444 synchronized (this) {
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700445 if (mCurrentState != null && mCurrentState.mState == PowerHalService.STATE_ON_FULL) {
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800446 displayOn = true;
447 }
448 }
449 for (PowerEventProcessingHandlerWrapper wrapper : mPowerEventProcessingHandlers) {
450 // wrapper will not send it forward if it is already called.
451 wrapper.callOnPowerOn(displayOn);
452 }
453 }
454
455 private boolean needPowerStateChange(PowerState newState) {
456 synchronized (this) {
keunyoung4b0212c2015-10-29 17:11:57 -0700457 if (mCurrentState != null && mCurrentState.equals(newState)) {
458 return false;
459 }
460 return true;
461 }
462 }
463
keunyoung4b0212c2015-10-29 17:11:57 -0700464 private void doHandleShutdown() {
465 // now shutdown
466 for (PowerServiceEventListener listener : mListeners) {
467 listener.onShutdown();
468 }
469 int wakeupTimeSec = 0;
470 if (mHal.isTimedWakeupAllowed()) {
471 wakeupTimeSec = getWakeupTime();
472 }
473 mHal.sendShutdownStart(wakeupTimeSec);
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700474 mSystemInterface.shutdown();
keunyoung4b0212c2015-10-29 17:11:57 -0700475 }
476
477 private int getWakeupTime() {
478 int wakeupTimeSec = 0;
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800479 for (PowerEventProcessingHandlerWrapper wrapper : mPowerEventProcessingHandlers) {
480 int t = wrapper.handler.getWakeupTime();
keunyoung4b0212c2015-10-29 17:11:57 -0700481 if (t > wakeupTimeSec) {
482 wakeupTimeSec = t;
483 }
484 }
485 return wakeupTimeSec;
486 }
487
488 private void doHandleProcessingComplete(boolean shutdownWhenCompleted) {
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800489 synchronized (this) {
keunyoung4b0212c2015-10-29 17:11:57 -0700490 releaseTimerLocked();
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800491 if (!shutdownWhenCompleted && mLastSleepEntryTime > mProcessingStartTime) {
492 // entered sleep after processing start. So this could be duplicate request.
493 Log.w(CarLog.TAG_POWER, "Duplicate sleep entry request, ignore");
494 return;
495 }
keunyoung4b0212c2015-10-29 17:11:57 -0700496 }
497 if (shutdownWhenCompleted) {
498 doHandleShutdown();
499 } else {
500 doHandleDeepSleep();
501 }
502 }
503
keunyoung4b0212c2015-10-29 17:11:57 -0700504 private synchronized void setCurrentState(PowerState state) {
505 mCurrentState = state;
506 }
507
508 @Override
509 public void onDisplayBrightnessChange(int brightness) {
Keun-young Parkf9215202016-10-10 12:34:08 -0700510 // TODO bug: 32065231
keunyoung4b0212c2015-10-29 17:11:57 -0700511 }
512
513 private void doHandleDisplayBrightnessChange(int brightness) {
Keun-young Parkf9215202016-10-10 12:34:08 -0700514 //TODO bug: 32065231
keunyoung4b0212c2015-10-29 17:11:57 -0700515 }
516
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800517 private void doHandleMainDisplayStateChange(boolean on) {
Keun-young Parkf9215202016-10-10 12:34:08 -0700518 //TODO bug: 32065231
keunyoung4b0212c2015-10-29 17:11:57 -0700519 }
520
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800521 public void handleMainDisplayChanged(boolean on) {
Pavel Maltsevddbff982017-03-22 14:49:02 -0700522 PowerHandler handler;
523 synchronized (this) {
524 handler = mHandler;
525 }
526 handler.handleMainDisplayStateChange(on);
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800527 }
528
Pavel Maltsevddbff982017-03-22 14:49:02 -0700529 public synchronized Handler getHandler() {
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800530 return mHandler;
531 }
532
keunyoung4b0212c2015-10-29 17:11:57 -0700533 private class PowerHandler extends Handler {
534
535 private final int MSG_POWER_STATE_CHANGE = 0;
536 private final int MSG_DISPLAY_BRIGHTNESS_CHANGE = 1;
537 private final int MSG_MAIN_DISPLAY_STATE_CHANGE = 2;
538 private final int MSG_PROCESSING_COMPLETE = 3;
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800539 private final int MSG_NOTIFY_POWER_ON = 4;
keunyoung4b0212c2015-10-29 17:11:57 -0700540
541 // Do not handle this immediately but with some delay as there can be a race between
542 // display off due to rear view camera and delivery to here.
543 private final long MAIN_DISPLAY_EVENT_DELAY_MS = 500;
544
545 private PowerHandler(Looper looper) {
546 super(looper);
547 }
548
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800549 private void handlePowerStateChange() {
550 Message msg = obtainMessage(MSG_POWER_STATE_CHANGE);
keunyoung4b0212c2015-10-29 17:11:57 -0700551 sendMessage(msg);
552 }
553
554 private void handleDisplayBrightnessChange(int brightness) {
555 Message msg = obtainMessage(MSG_DISPLAY_BRIGHTNESS_CHANGE, brightness, 0);
556 sendMessage(msg);
557 }
558
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800559 private void handleMainDisplayStateChange(boolean on) {
keunyoung4b0212c2015-10-29 17:11:57 -0700560 removeMessages(MSG_MAIN_DISPLAY_STATE_CHANGE);
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800561 Message msg = obtainMessage(MSG_MAIN_DISPLAY_STATE_CHANGE, Boolean.valueOf(on));
keunyoung4b0212c2015-10-29 17:11:57 -0700562 sendMessageDelayed(msg, MAIN_DISPLAY_EVENT_DELAY_MS);
563 }
564
565 private void handleProcessingComplete(boolean shutdownWhenCompleted) {
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800566 removeMessages(MSG_PROCESSING_COMPLETE);
keunyoung4b0212c2015-10-29 17:11:57 -0700567 Message msg = obtainMessage(MSG_PROCESSING_COMPLETE, shutdownWhenCompleted ? 1 : 0, 0);
568 sendMessage(msg);
569 }
570
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800571 private void handlePowerOn() {
572 Message msg = obtainMessage(MSG_NOTIFY_POWER_ON);
573 sendMessage(msg);
574 }
575
576 private void cancelProcessingComplete() {
577 removeMessages(MSG_PROCESSING_COMPLETE);
578 }
579
keunyoung4b0212c2015-10-29 17:11:57 -0700580 private void cancelAll() {
581 removeMessages(MSG_POWER_STATE_CHANGE);
582 removeMessages(MSG_DISPLAY_BRIGHTNESS_CHANGE);
583 removeMessages(MSG_MAIN_DISPLAY_STATE_CHANGE);
584 removeMessages(MSG_PROCESSING_COMPLETE);
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800585 removeMessages(MSG_NOTIFY_POWER_ON);
keunyoung4b0212c2015-10-29 17:11:57 -0700586 }
587
588 @Override
589 public void handleMessage(Message msg) {
590 switch (msg.what) {
591 case MSG_POWER_STATE_CHANGE:
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800592 doHandlePowerStateChange();
keunyoung4b0212c2015-10-29 17:11:57 -0700593 break;
594 case MSG_DISPLAY_BRIGHTNESS_CHANGE:
595 doHandleDisplayBrightnessChange(msg.arg1);
596 break;
597 case MSG_MAIN_DISPLAY_STATE_CHANGE:
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800598 doHandleMainDisplayStateChange((Boolean) msg.obj);
Keun-young Park1f4d6a72016-02-11 09:49:47 -0800599 break;
keunyoung4b0212c2015-10-29 17:11:57 -0700600 case MSG_PROCESSING_COMPLETE:
601 doHandleProcessingComplete(msg.arg1 == 1);
602 break;
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800603 case MSG_NOTIFY_POWER_ON:
604 doHandleNotifyPowerOn();
605 break;
keunyoung4b0212c2015-10-29 17:11:57 -0700606 }
607 }
608 }
609
keunyoung4b0212c2015-10-29 17:11:57 -0700610 private class ShutdownProcessingTimerTask extends TimerTask {
611 private final boolean mShutdownWhenCompleted;
612 private final int mExpirationCount;
613 private int mCurrentCount;
614
615 private ShutdownProcessingTimerTask(boolean shutdownWhenCompleted, int expirationCount) {
616 mShutdownWhenCompleted = shutdownWhenCompleted;
617 mExpirationCount = expirationCount;
618 mCurrentCount = 0;
619 }
620
621 @Override
622 public void run() {
623 mCurrentCount++;
624 if (mCurrentCount > mExpirationCount) {
Pavel Maltsevddbff982017-03-22 14:49:02 -0700625 PowerHandler handler;
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800626 synchronized (CarPowerManagementService.this) {
keunyoung4b0212c2015-10-29 17:11:57 -0700627 releaseTimerLocked();
Pavel Maltsevddbff982017-03-22 14:49:02 -0700628 handler = mHandler;
keunyoung4b0212c2015-10-29 17:11:57 -0700629 }
Pavel Maltsevddbff982017-03-22 14:49:02 -0700630 handler.handleProcessingComplete(mShutdownWhenCompleted);
keunyoung4b0212c2015-10-29 17:11:57 -0700631 } else {
632 mHal.sendShutdownPostpone(SHUTDOWN_EXTEND_MAX_MS);
633 }
634 }
635 }
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800636
637 private static class PowerEventProcessingHandlerWrapper {
638 public final PowerEventProcessingHandler handler;
639 private long mProcessingTime = 0;
640 private boolean mProcessingDone = true;
641 private boolean mPowerOnSent = false;
Keun-young Parkd73afae2016-04-08 20:03:32 -0700642 private int mLastDisplayState = -1;
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800643
644 public PowerEventProcessingHandlerWrapper(PowerEventProcessingHandler handler) {
645 this.handler = handler;
646 }
647
648 public synchronized void setProcessingTimeAndResetProcessingDone(long processingTime) {
649 mProcessingTime = processingTime;
650 mProcessingDone = false;
651 }
652
653 public synchronized long getProcessingTime() {
654 return mProcessingTime;
655 }
656
657 public synchronized void markProcessingDone() {
658 mProcessingDone = true;
659 }
660
661 public synchronized boolean isProcessingDone() {
662 return mProcessingDone;
663 }
664
665 public void callOnPowerOn(boolean displayOn) {
Keun-young Parkd73afae2016-04-08 20:03:32 -0700666 int newDisplayState = displayOn ? 1 : 0;
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800667 boolean shouldCall = false;
668 synchronized (this) {
Keun-young Parkd73afae2016-04-08 20:03:32 -0700669 if (!mPowerOnSent || (mLastDisplayState != newDisplayState)) {
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800670 shouldCall = true;
671 mPowerOnSent = true;
Keun-young Parkd73afae2016-04-08 20:03:32 -0700672 mLastDisplayState = newDisplayState;
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800673 }
674 }
675 if (shouldCall) {
676 handler.onPowerOn(displayOn);
677 }
678 }
679
Keun-young Parkfd3fbf72016-01-22 17:00:17 -0800680 @Override
681 public String toString() {
682 return "PowerEventProcessingHandlerWrapper [handler=" + handler + ", mProcessingTime="
683 + mProcessingTime + ", mProcessingDone=" + mProcessingDone + "]";
684 }
685 }
keunyoung4b0212c2015-10-29 17:11:57 -0700686}