Refactor CPMS
- Remove Boot Reason
- Rework state machine according to updated design document
- Update CarLocationService with new CPMS states
- Update GarageMode.Controller with new CPMS states
- Update unit tests for CarLocationManager, GarageMode, and CPMS
Bug: 112548962
Test: vhal_emulator.py
(cherry picked from pi-car-dev)
Change-Id: I0e262311626c5032695ec766c34b36f40dc931ec
diff --git a/service/src/com/android/car/CarPowerManagementService.java b/service/src/com/android/car/CarPowerManagementService.java
index 1514056..6ae33cc 100644
--- a/service/src/com/android/car/CarPowerManagementService.java
+++ b/service/src/com/android/car/CarPowerManagementService.java
@@ -20,6 +20,7 @@
import android.car.hardware.power.ICarPower;
import android.car.hardware.power.ICarPowerStateListener;
import android.content.Context;
+import android.hardware.automotive.vehicle.V2_0.VehicleApPowerStateReq;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
@@ -56,7 +57,7 @@
private final Map<IBinder, Integer> mPowerManagerListenerTokens = new ConcurrentHashMap<>();
@GuardedBy("this")
- private PowerState mCurrentState;
+ private CpmsState mCurrentState;
@GuardedBy("this")
private Timer mTimer;
@GuardedBy("this")
@@ -64,20 +65,21 @@
@GuardedBy("this")
private long mLastSleepEntryTime;
@GuardedBy("this")
- private final LinkedList<PowerState> mPendingPowerStates = new LinkedList<>();
+ private final LinkedList<CpmsState> mPendingPowerStates = new LinkedList<>();
@GuardedBy("this")
private HandlerThread mHandlerThread;
@GuardedBy("this")
private PowerHandler mHandler;
- private int mBootReason;
- private boolean mShutdownOnNextSuspend = false;
- private int mNextWakeupSec;
+ private int mNextWakeupSec = 0;
private int mTokenValue = 1;
+ private boolean mShutdownOnFinish = false;
// TODO: Make this OEM configurable.
- private static final int APP_EXTEND_MAX_MS = 86400000; // 1 day
- private final static int SHUTDOWN_POLLING_INTERVAL_MS = 2000;
- private final static int SHUTDOWN_EXTEND_MAX_MS = 5000;
+ private static final int SHUTDOWN_POLLING_INTERVAL_MS = 2000;
+ private static final int SHUTDOWN_EXTEND_MAX_MS = 5000;
+
+ // Use one hour for now
+ private static int sShutdownPrepareTimeMs = 60 * 60 * 1000;
private class PowerManagerCallbackList extends RemoteCallbackList<ICarPowerStateListener> {
/**
@@ -111,6 +113,16 @@
mHandler = new PowerHandler(Looper.getMainLooper());
}
+ @VisibleForTesting
+ protected static void setShutdownPrepareTimeout(int timeoutMs) {
+ // Override the timeout to keep testing time short
+ if (timeoutMs < SHUTDOWN_EXTEND_MAX_MS) {
+ sShutdownPrepareTimeMs = SHUTDOWN_EXTEND_MAX_MS;
+ } else {
+ sShutdownPrepareTimeMs = timeoutMs;
+ }
+ }
+
@Override
public void init() {
synchronized (this) {
@@ -121,18 +133,11 @@
mHal.setListener(this);
if (mHal.isPowerStateSupported()) {
- mHal.sendBootComplete();
- PowerState currentState = mHal.getCurrentPowerState();
- if (currentState != null) {
- onApPowerStateChange(currentState);
- } else {
- Log.w(CarLog.TAG_POWER, "Unable to get get current power state during "
- + "initialization");
- }
+ // Initialize CPMS in WAIT_FOR_VHAL state
+ onApPowerStateChange(CpmsState.WAIT_FOR_VHAL, CarPowerStateListener.WAIT_FOR_VHAL);
} else {
Log.w(CarLog.TAG_POWER, "Vehicle hal does not support power state yet.");
- onApPowerStateChange(new PowerState(PowerHalService.STATE_ON_FULL, 0));
- mSystemInterface.switchToFullWakeLock();
+ onApPowerStateChange(CpmsState.ON, CarPowerStateListener.ON);
}
mSystemInterface.startDisplayStateMonitoring(this);
}
@@ -158,71 +163,42 @@
mSystemInterface.releaseAllWakeLocks();
}
- /**
- * Notifies earlier completion of power event processing. If some user modules need pre-shutdown
- * processing time, they will get up to #APP_EXTEND_MAX_MS to complete their tasks. Modules
- * are expected to finish earlier than that, and this call can be called in such case to trigger
- * shutdown without waiting further.
- */
- public void notifyPowerEventProcessingCompletion() {
- long processingTime = 0;
- synchronized (mPowerManagerListenerTokens) {
- if (!mPowerManagerListenerTokens.isEmpty()) {
- processingTime += APP_EXTEND_MAX_MS;
- }
- }
- long now = SystemClock.elapsedRealtime();
- long startTime;
- boolean shouldShutdown = true;
- PowerHandler powerHandler;
- synchronized (this) {
- startTime = mProcessingStartTime;
- if (mCurrentState == null) {
- return;
- }
- if (mCurrentState.mState != PowerHalService.STATE_SHUTDOWN_PREPARE) {
- return;
- }
- if (mCurrentState.canEnterDeepSleep() && !mShutdownOnNextSuspend) {
- shouldShutdown = false;
- if (mLastSleepEntryTime > mProcessingStartTime && mLastSleepEntryTime < now) {
- // already slept
- return;
- }
- }
- powerHandler = mHandler;
- }
- if ((startTime + processingTime) <= now) {
- Log.i(CarLog.TAG_POWER, "Processing all done");
- powerHandler.handleProcessingComplete(shouldShutdown);
- }
- }
-
@Override
public void dump(PrintWriter writer) {
writer.println("*PowerManagementService*");
writer.print("mCurrentState:" + mCurrentState);
writer.print(",mProcessingStartTime:" + mProcessingStartTime);
- writer.println(",mLastSleepEntryTime:" + mLastSleepEntryTime);
- }
-
- @Override
- public void onBootReasonReceived(int bootReason) {
- mBootReason = bootReason;
+ writer.print(",mLastSleepEntryTime:" + mLastSleepEntryTime);
+ writer.print(",mNextWakeupSec:" + mNextWakeupSec);
+ writer.print(",mTokenValue:" + mTokenValue);
+ writer.println(",mShutdownOnFinish:" + mShutdownOnFinish);
}
@Override
public void onApPowerStateChange(PowerState state) {
PowerHandler handler;
synchronized (this) {
- mPendingPowerStates.addFirst(state);
+ mPendingPowerStates.addFirst(new CpmsState(state));
+ handler = mHandler;
+ }
+ handler.handlePowerStateChange();
+ }
+
+ /**
+ * Initiate state change from CPMS directly.
+ */
+ private void onApPowerStateChange(int apState, int carPowerStateListenerState) {
+ CpmsState newState = new CpmsState(apState, carPowerStateListenerState);
+ PowerHandler handler;
+ synchronized (this) {
+ mPendingPowerStates.addFirst(newState);
handler = mHandler;
}
handler.handlePowerStateChange();
}
private void doHandlePowerStateChange() {
- PowerState state = null;
+ CpmsState state;
PowerHandler handler;
synchronized (this) {
state = mPendingPowerStates.peekFirst();
@@ -230,7 +206,9 @@
if (state == null) {
return;
}
- if (!needPowerStateChange(state)) {
+ Log.i(CarLog.TAG_POWER, "doHandlePowerStateChange: newState=" + state.mState);
+ if (!needPowerStateChangeLocked(state)) {
+ Log.d(CarLog.TAG_POWER, "doHandlePowerStateChange no change needed");
return;
}
// now real power change happens. Whatever was queued before should be all cancelled.
@@ -238,44 +216,66 @@
handler = mHandler;
}
handler.cancelProcessingComplete();
-
- Log.i(CarLog.TAG_POWER, "Power state change:" + state);
+ Log.i(CarLog.TAG_POWER, "setCurrentState " + state.toString());
+ mCurrentState = state;
switch (state.mState) {
- case PowerHalService.STATE_ON_DISP_OFF:
- handleDisplayOff(state);
+ case CpmsState.WAIT_FOR_VHAL:
+ handleWaitForVhal(state);
break;
- case PowerHalService.STATE_ON_FULL:
- handleFullOn(state);
+ case CpmsState.ON:
+ handleOn();
break;
- case PowerHalService.STATE_SHUTDOWN_PREPARE:
+ case CpmsState.SHUTDOWN_PREPARE:
handleShutdownPrepare(state);
break;
+ case CpmsState.WAIT_FOR_FINISH:
+ handleWaitForFinish(state);
+ break;
+ case CpmsState.SUSPEND:
+ // Received FINISH from VHAL
+ handleFinish();
+ break;
+ default:
+ // Illegal state
+ // TODO: Throw exception?
+ break;
}
}
- private void handleDisplayOff(PowerState newState) {
- setCurrentState(newState);
- mSystemInterface.setDisplayState(false);
+ private void handleWaitForVhal(CpmsState state) {
+ int carPowerStateListenerState = state.mCarPowerStateListenerState;
+ sendPowerManagerEvent(carPowerStateListenerState, false);
+ // Inspect CarPowerStateListenerState to decide which message to send via VHAL
+ switch (carPowerStateListenerState) {
+ case CarPowerStateListener.WAIT_FOR_VHAL:
+ mHal.sendWaitForVhal();
+ break;
+ case CarPowerStateListener.SHUTDOWN_CANCELLED:
+ mHal.sendShutdownCancel();
+ break;
+ case CarPowerStateListener.SUSPEND_EXIT:
+ mHal.sendSleepExit();
+ break;
+ }
}
- private void handleFullOn(PowerState newState) {
- setCurrentState(newState);
+ private void handleOn() {
mSystemInterface.setDisplayState(true);
+ sendPowerManagerEvent(CarPowerStateListener.ON, false);
+ mHal.sendOn();
}
- private void handleShutdownPrepare(PowerState newState) {
- setCurrentState(newState);
- mSystemInterface.setDisplayState(false);;
- boolean shouldShutdown = true;
- if (mHal.isDeepSleepAllowed() && mSystemInterface.isSystemSupportingDeepSleep() &&
- newState.canEnterDeepSleep() && !mShutdownOnNextSuspend) {
- Log.i(CarLog.TAG_POWER, "starting sleep");
- shouldShutdown = false;
- doHandlePreprocessing(shouldShutdown);
- return;
- } else if (newState.canPostponeShutdown()) {
- Log.i(CarLog.TAG_POWER, "starting shutdown with processing");
- doHandlePreprocessing(shouldShutdown);
+ private void handleShutdownPrepare(CpmsState newState) {
+ mSystemInterface.setDisplayState(false);
+ // Shutdown on finish if the system doesn't support deep sleep or doesn't allow it.
+ mShutdownOnFinish |= !mHal.isDeepSleepAllowed()
+ || !mSystemInterface.isSystemSupportingDeepSleep()
+ || !newState.mCanSleep;
+ if (newState.mCanPostpone) {
+ Log.i(CarLog.TAG_POWER, "starting shutdown postpone");
+ sendPowerManagerEvent(CarPowerStateListener.SHUTDOWN_PREPARE, true);
+ mHal.sendShutdownPrepare();
+ doHandlePreprocessing();
} else {
Log.i(CarLog.TAG_POWER, "starting shutdown immediately");
synchronized (this) {
@@ -285,6 +285,26 @@
}
}
+ private void handleWaitForFinish(CpmsState state) {
+ sendPowerManagerEvent(state.mCarPowerStateListenerState, false);
+ switch (state.mCarPowerStateListenerState) {
+ case CarPowerStateListener.SUSPEND_ENTER:
+ mHal.sendSleepEntry(mNextWakeupSec);
+ break;
+ case CarPowerStateListener.SHUTDOWN_ENTER:
+ mHal.sendShutdownStart(mNextWakeupSec);
+ break;
+ }
+ }
+
+ private void handleFinish() {
+ if (mShutdownOnFinish) {
+ doHandleShutdown();
+ } else {
+ doHandleDeepSleep();
+ }
+ }
+
@GuardedBy("this")
private void releaseTimerLocked() {
if (mTimer != null) {
@@ -293,57 +313,45 @@
mTimer = null;
}
- private void doHandlePreprocessing(boolean shuttingDown) {
- // Set time for powerManager events
- long processingTimeMs = sendPowerManagerEvent(shuttingDown);
- if (processingTimeMs > 0) {
- int pollingCount = (int)(processingTimeMs / SHUTDOWN_POLLING_INTERVAL_MS) + 1;
- Log.i(CarLog.TAG_POWER, "processing before shutdown expected for: "
- + processingTimeMs + " ms, adding polling:" + pollingCount);
- synchronized (this) {
- mProcessingStartTime = SystemClock.elapsedRealtime();
- releaseTimerLocked();
- mTimer = new Timer();
- mTimer.scheduleAtFixedRate(
- new ShutdownProcessingTimerTask(shuttingDown, pollingCount),
- 0 /*delay*/,
- SHUTDOWN_POLLING_INTERVAL_MS);
- }
- } else {
- PowerHandler handler;
- synchronized (this) {
- handler = mHandler;
- }
- handler.handleProcessingComplete(shuttingDown);
+ private void doHandlePreprocessing() {
+ int pollingCount = (sShutdownPrepareTimeMs / SHUTDOWN_POLLING_INTERVAL_MS) + 1;
+ Log.i(CarLog.TAG_POWER, "processing before shutdown expected for: "
+ + sShutdownPrepareTimeMs + " ms, adding polling:" + pollingCount);
+ synchronized (this) {
+ mProcessingStartTime = SystemClock.elapsedRealtime();
+ releaseTimerLocked();
+ mTimer = new Timer();
+ mTimer.scheduleAtFixedRate(
+ new ShutdownProcessingTimerTask(pollingCount),
+ 0 /*delay*/,
+ SHUTDOWN_POLLING_INTERVAL_MS);
}
}
- private long sendPowerManagerEvent(boolean shuttingDown) {
- long processingTimeMs = 0;
- int newState = shuttingDown ? CarPowerStateListener.SHUTDOWN_ENTER :
- CarPowerStateListener.SUSPEND_ENTER;
+ private void sendPowerManagerEvent(int newState, boolean useTokens) {
synchronized (mPowerManagerListenerTokens) {
- mPowerManagerListenerTokens.clear();
+ if (useTokens) {
+ mPowerManagerListenerTokens.clear();
+ }
int i = mPowerManagerListeners.beginBroadcast();
while (i-- > 0) {
try {
+ int token = 0;
ICarPowerStateListener listener = mPowerManagerListeners.getBroadcastItem(i);
- listener.onStateChanged(newState, mTokenValue);
- mPowerManagerListenerTokens.put(listener.asBinder(), mTokenValue);
- mTokenValue++;
+ if (useTokens) {
+ listener.onStateChanged(newState, mTokenValue);
+ mPowerManagerListenerTokens.put(listener.asBinder(), mTokenValue);
+ mTokenValue++;
+ } else {
+ listener.onStateChanged(newState, 0);
+ }
} catch (RemoteException e) {
// Its likely the connection snapped. Let binder death handle the situation.
Log.e(CarLog.TAG_POWER, "onStateChanged calling failed: " + e);
}
}
mPowerManagerListeners.finishBroadcast();
- if (!mPowerManagerListenerTokens.isEmpty()) {
- Log.i(CarLog.TAG_POWER,
- "mPowerManagerListenerTokens not empty, add APP_EXTEND_MAX_MS");
- processingTimeMs += APP_EXTEND_MAX_MS;
- }
}
- return processingTimeMs;
}
private void doHandleDeepSleep() {
@@ -355,61 +363,48 @@
handler = mHandler;
}
handler.cancelProcessingComplete();
- mHal.sendSleepEntry();
synchronized (this) {
mLastSleepEntryTime = SystemClock.elapsedRealtime();
}
- if (!mSystemInterface.enterDeepSleep(mNextWakeupSec)) {
- // System did not suspend. Need to shutdown
- // TODO: Shutdown gracefully
+ if (!mSystemInterface.enterDeepSleep()) {
+ // System did not suspend. VHAL should transition CPMS to shutdown.
Log.e(CarLog.TAG_POWER, "Sleep did not succeed. Need to shutdown");
}
- // When we wake up, we reset the next wake up time and if no one will set it
- // System will suspend / shutdown forever.
+ // On wake, reset nextWakeup time. If not set again, system will suspend/shutdown forever.
mNextWakeupSec = 0;
- mHal.sendSleepExit();
- // Notify applications
- int i = mPowerManagerListeners.beginBroadcast();
- while (i-- > 0) {
- try {
- ICarPowerStateListener listener = mPowerManagerListeners.getBroadcastItem(i);
- listener.onStateChanged(CarPowerStateListener.SUSPEND_EXIT, 0);
- } catch (RemoteException e) {
- // Its likely the connection snapped. Let binder death handle the situation.
- Log.e(CarLog.TAG_POWER, "onStateChanged calling failed: " + e);
- }
- }
- mPowerManagerListeners.finishBroadcast();
- if (mSystemInterface.isWakeupCausedByTimer()) {
- doHandlePreprocessing(false /*shuttingDown*/);
- } else {
- PowerState currentState = mHal.getCurrentPowerState();
- if (currentState != null && needPowerStateChange(currentState)) {
- onApPowerStateChange(currentState);
- } else { // power controller woke-up but no power state change. Just shutdown.
- Log.w(CarLog.TAG_POWER, "external sleep wake up, but no power state change:" +
- currentState);
- doHandleShutdown();
- }
- }
+ onApPowerStateChange(CpmsState.WAIT_FOR_VHAL, CarPowerStateListener.SUSPEND_EXIT);
}
- private void doHandleNotifyPowerOn() {
- boolean displayOn = false;
- synchronized (this) {
- if (mCurrentState != null && mCurrentState.mState == PowerHalService.STATE_ON_FULL) {
- displayOn = true;
- }
- }
- }
-
- private boolean needPowerStateChange(PowerState newState) {
- synchronized (this) {
- if (mCurrentState != null && mCurrentState.equals(newState)) {
- return false;
- }
+ private boolean needPowerStateChangeLocked(CpmsState newState) {
+ if (newState == null) {
+ return false;
+ } else if (mCurrentState == null) {
return true;
+ } else if (mCurrentState.equals(newState)) {
+ return false;
+ }
+
+ // The following switch/case enforces the allowed state transitions.
+ switch (mCurrentState.mState) {
+ case CpmsState.WAIT_FOR_VHAL:
+ return (newState.mState == CpmsState.ON)
+ || (newState.mState == CpmsState.SHUTDOWN_PREPARE);
+ case CpmsState.SUSPEND:
+ return newState.mState == CpmsState.WAIT_FOR_VHAL;
+ case CpmsState.ON:
+ return newState.mState == CpmsState.SHUTDOWN_PREPARE;
+ case CpmsState.SHUTDOWN_PREPARE:
+ // If VHAL sends SHUTDOWN_IMMEDIATELY while in SHUTDOWN_PREPARE state, do it.
+ return ((newState.mState == CpmsState.SHUTDOWN_PREPARE) && !newState.mCanPostpone)
+ || (newState.mState == CpmsState.WAIT_FOR_FINISH)
+ || (newState.mState == CpmsState.WAIT_FOR_VHAL);
+ case CpmsState.WAIT_FOR_FINISH:
+ return newState.mState == CpmsState.SUSPEND;
+ default:
+ Log.e(CarLog.TAG_POWER, "Unhandled state transition: currentState="
+ + mCurrentState.mState + ", newState=" + newState.mState);
+ return false;
}
}
@@ -419,24 +414,21 @@
mSystemInterface.shutdown();
}
- private void doHandleProcessingComplete(boolean shutdownWhenCompleted) {
+ private void doHandleProcessingComplete() {
synchronized (this) {
releaseTimerLocked();
- if (!shutdownWhenCompleted && mLastSleepEntryTime > mProcessingStartTime) {
+ if (!mShutdownOnFinish && mLastSleepEntryTime > mProcessingStartTime) {
// entered sleep after processing start. So this could be duplicate request.
Log.w(CarLog.TAG_POWER, "Duplicate sleep entry request, ignore");
return;
}
}
- if (shutdownWhenCompleted) {
- doHandleShutdown();
- } else {
- doHandleDeepSleep();
- }
- }
- private synchronized void setCurrentState(PowerState state) {
- mCurrentState = state;
+ if (mShutdownOnFinish) {
+ onApPowerStateChange(CpmsState.WAIT_FOR_FINISH, CarPowerStateListener.SHUTDOWN_ENTER);
+ } else {
+ onApPowerStateChange(CpmsState.WAIT_FOR_FINISH, CarPowerStateListener.SUSPEND_ENTER);
+ }
}
@Override
@@ -481,6 +473,8 @@
public void registerListener(ICarPowerStateListener listener) {
ICarImpl.assertPermission(mContext, Car.PERMISSION_CAR_POWER);
mPowerManagerListeners.register(listener);
+ // TODO: Need to send current state to newly registered listener? If so, need to handle
+ // token for SHUTDOWN_PREPARE state
}
@Override
@@ -491,7 +485,6 @@
private void doUnregisterListener(ICarPowerStateListener listener) {
boolean found = mPowerManagerListeners.unregister(listener);
-
if (found) {
// Remove outstanding token if there is one
IBinder binder = listener.asBinder();
@@ -507,14 +500,7 @@
@Override
public void requestShutdownOnNextSuspend() {
ICarImpl.assertPermission(mContext, Car.PERMISSION_CAR_POWER);
- mShutdownOnNextSuspend = true;
- }
-
- @Override
- public int getBootReason() {
- ICarImpl.assertPermission(mContext, Car.PERMISSION_CAR_POWER);
- // Return the most recent bootReason value
- return mBootReason;
+ mShutdownOnFinish = true;
}
@Override
@@ -544,22 +530,30 @@
if (currentToken == token) {
mPowerManagerListenerTokens.remove(binder);
if (mPowerManagerListenerTokens.isEmpty() &&
- (mCurrentState.mState == PowerHalService.STATE_SHUTDOWN_PREPARE)) {
+ (mCurrentState.mState == CpmsState.SHUTDOWN_PREPARE)) {
+ PowerHandler powerHandler;
// All apps are ready to shutdown/suspend.
- Log.i(CarLog.TAG_POWER,
- "Apps are finished, call notifyPowerEventProcessingCompletion");
- notifyPowerEventProcessingCompletion();
+ synchronized (this) {
+ if (!mShutdownOnFinish) {
+ if (mLastSleepEntryTime > mProcessingStartTime
+ && mLastSleepEntryTime < SystemClock.elapsedRealtime()) {
+ Log.i(CarLog.TAG_POWER, "finishedLocked: Already slept!");
+ return;
+ }
+ }
+ powerHandler = mHandler;
+ }
+ Log.i(CarLog.TAG_POWER, "Apps are finished, call handleProcessingComplete()");
+ powerHandler.handleProcessingComplete();
}
}
}
private class PowerHandler extends Handler {
-
private final int MSG_POWER_STATE_CHANGE = 0;
private final int MSG_DISPLAY_BRIGHTNESS_CHANGE = 1;
private final int MSG_MAIN_DISPLAY_STATE_CHANGE = 2;
private final int MSG_PROCESSING_COMPLETE = 3;
- private final int MSG_NOTIFY_POWER_ON = 4;
// Do not handle this immediately but with some delay as there can be a race between
// display off due to rear view camera and delivery to here.
@@ -585,14 +579,9 @@
sendMessageDelayed(msg, MAIN_DISPLAY_EVENT_DELAY_MS);
}
- private void handleProcessingComplete(boolean shutdownWhenCompleted) {
+ private void handleProcessingComplete() {
removeMessages(MSG_PROCESSING_COMPLETE);
- Message msg = obtainMessage(MSG_PROCESSING_COMPLETE, shutdownWhenCompleted ? 1 : 0, 0);
- sendMessage(msg);
- }
-
- private void handlePowerOn() {
- Message msg = obtainMessage(MSG_NOTIFY_POWER_ON);
+ Message msg = obtainMessage(MSG_PROCESSING_COMPLETE);
sendMessage(msg);
}
@@ -605,7 +594,6 @@
removeMessages(MSG_DISPLAY_BRIGHTNESS_CHANGE);
removeMessages(MSG_MAIN_DISPLAY_STATE_CHANGE);
removeMessages(MSG_PROCESSING_COMPLETE);
- removeMessages(MSG_NOTIFY_POWER_ON);
}
@Override
@@ -621,22 +609,17 @@
doHandleMainDisplayStateChange((Boolean) msg.obj);
break;
case MSG_PROCESSING_COMPLETE:
- doHandleProcessingComplete(msg.arg1 == 1);
- break;
- case MSG_NOTIFY_POWER_ON:
- doHandleNotifyPowerOn();
+ doHandleProcessingComplete();
break;
}
}
}
private class ShutdownProcessingTimerTask extends TimerTask {
- private final boolean mShutdownWhenCompleted;
private final int mExpirationCount;
private int mCurrentCount;
- private ShutdownProcessingTimerTask(boolean shutdownWhenCompleted, int expirationCount) {
- mShutdownWhenCompleted = shutdownWhenCompleted;
+ private ShutdownProcessingTimerTask(int expirationCount) {
mExpirationCount = expirationCount;
mCurrentCount = 0;
}
@@ -650,10 +633,124 @@
releaseTimerLocked();
handler = mHandler;
}
- handler.handleProcessingComplete(mShutdownWhenCompleted);
+ handler.handleProcessingComplete();
} else {
mHal.sendShutdownPostpone(SHUTDOWN_EXTEND_MAX_MS);
}
}
}
+
+ private static class CpmsState {
+ public static final int WAIT_FOR_VHAL = 0;
+ public static final int ON = 1;
+ public static final int SHUTDOWN_PREPARE = 2;
+ public static final int WAIT_FOR_FINISH = 3;
+ public static final int SUSPEND = 4;
+
+ /* Config values from AP_POWER_STATE_REQ */
+ public final boolean mCanPostpone;
+ public final boolean mCanSleep;
+ /* Message sent to CarPowerStateListener in response to this state */
+ public final int mCarPowerStateListenerState;
+ /* One of the above state variables */
+ public final int mState;
+
+ /**
+ * This constructor takes a PowerHalService.PowerState object and creates the corresponding
+ * CPMS state from it.
+ */
+ CpmsState(PowerState halPowerState) {
+ switch (halPowerState.mState) {
+ case VehicleApPowerStateReq.ON:
+ this.mCanPostpone = false;
+ this.mCanSleep = false;
+ this.mCarPowerStateListenerState = cpmsStateToPowerStateListenerState(ON);
+ this.mState = ON;
+ break;
+ case VehicleApPowerStateReq.SHUTDOWN_PREPARE:
+ this.mCanPostpone = halPowerState.canPostponeShutdown();
+ this.mCanSleep = halPowerState.canEnterDeepSleep();
+ this.mCarPowerStateListenerState = cpmsStateToPowerStateListenerState(
+ SHUTDOWN_PREPARE);
+ this.mState = SHUTDOWN_PREPARE;
+ break;
+ case VehicleApPowerStateReq.CANCEL_SHUTDOWN:
+ this.mCanPostpone = false;
+ this.mCanSleep = false;
+ this.mCarPowerStateListenerState = CarPowerStateListener.SHUTDOWN_CANCELLED;
+ this.mState = WAIT_FOR_VHAL;
+ break;
+ case VehicleApPowerStateReq.FINISHED:
+ this.mCanPostpone = false;
+ this.mCanSleep = false;
+ this.mCarPowerStateListenerState = cpmsStateToPowerStateListenerState(SUSPEND);
+ this.mState = SUSPEND;
+ break;
+ default:
+ // Illegal state from PowerState. Throw an exception?
+ this.mCanPostpone = false;
+ this.mCanSleep = false;
+ this.mCarPowerStateListenerState = 0;
+ this.mState = 0;
+ break;
+ }
+ }
+
+ CpmsState(int state) {
+ this(state, cpmsStateToPowerStateListenerState(state));
+ }
+
+ CpmsState(int state, int carPowerStateListenerState) {
+ this.mCanPostpone = false;
+ this.mCanSleep = false;
+ this.mCarPowerStateListenerState = carPowerStateListenerState;
+ this.mState = state;
+ }
+
+ private static int cpmsStateToPowerStateListenerState(int state) {
+ int powerStateListenerState = 0;
+
+ // Set the CarPowerStateListenerState based on current state
+ switch (state) {
+ case ON:
+ powerStateListenerState = CarPowerStateListener.ON;
+ break;
+ case SHUTDOWN_PREPARE:
+ powerStateListenerState = CarPowerStateListener.SHUTDOWN_PREPARE;
+ break;
+ case SUSPEND:
+ powerStateListenerState = CarPowerStateListener.SUSPEND_ENTER;
+ break;
+ case WAIT_FOR_VHAL:
+ case WAIT_FOR_FINISH:
+ default:
+ // Illegal state for this constructor. Throw an exception?
+ break;
+ }
+ return powerStateListenerState;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof CpmsState)) {
+ return false;
+ }
+ CpmsState that = (CpmsState) o;
+ return this.mState == that.mState
+ && this.mCanSleep == that.mCanSleep
+ && this.mCanPostpone == that.mCanPostpone
+ && this.mCarPowerStateListenerState == that.mCarPowerStateListenerState;
+ }
+
+ @Override
+ public String toString() {
+ return "CpmsState canSleep:" + mCanSleep + ", canPostpone=" + mCanPostpone
+ + ", carPowerStateListenerState=" + mCarPowerStateListenerState
+ + ", CpmsState=" + mState;
+ }
+ }
+
}