Merge "Marking the string non translatable that are component name or app name."
diff --git a/car-lib/src/android/car/hardware/power/CarPowerManager.java b/car-lib/src/android/car/hardware/power/CarPowerManager.java
index e61a817..007c1e7 100644
--- a/car-lib/src/android/car/hardware/power/CarPowerManager.java
+++ b/car-lib/src/android/car/hardware/power/CarPowerManager.java
@@ -38,14 +38,15 @@
 public class CarPowerManager implements CarManagerBase {
     private final static boolean DBG = false;
     private final static String TAG = "CarPowerManager";
-    private CarPowerStateListener mListener;
-    private final ICarPower mService;
-    private CompletableFuture<Void> mFuture;
 
+    private final Object mLock = new Object();
+    private final ICarPower mService;
+
+    private CarPowerStateListener mListener;
+    private CompletableFuture<Void> mFuture;
     @GuardedBy("mLock")
     private ICarPowerStateListener mListenerToService;
 
-    private final Object mLock = new Object();
 
     /**
      * Deleted! Don't use.
@@ -184,6 +185,12 @@
     public void setListener(CarPowerStateListener listener) throws
             CarNotConnectedException, IllegalStateException {
         synchronized(mLock) {
+            if (mListener == null) {
+                // Update listener
+                mListener = listener;
+            } else {
+                throw new IllegalStateException("Listener must be cleared first");
+            }
             if (mListenerToService == null) {
                 ICarPowerStateListener listenerToService = new ICarPowerStateListener.Stub() {
                     @Override
@@ -201,12 +208,6 @@
                     Car.checkCarNotConnectedExceptionFromCarService(ex);
                 }
             }
-            if (mListener == null) {
-                // Update listener
-                mListener = listener;
-            } else {
-                throw new IllegalStateException("Listener must be cleared first");
-            }
         }
     }
 
diff --git a/service/src/com/android/car/CarPowerManagementService.java b/service/src/com/android/car/CarPowerManagementService.java
index 5c744eb..41c075e 100644
--- a/service/src/com/android/car/CarPowerManagementService.java
+++ b/service/src/com/android/car/CarPowerManagementService.java
@@ -244,7 +244,7 @@
 
     private void handleWaitForVhal(CpmsState state) {
         int carPowerStateListenerState = state.mCarPowerStateListenerState;
-        sendPowerManagerEvent(carPowerStateListenerState, false);
+        sendPowerManagerEvent(carPowerStateListenerState);
         // Inspect CarPowerStateListenerState to decide which message to send via VHAL
         switch (carPowerStateListenerState) {
             case CarPowerStateListener.WAIT_FOR_VHAL:
@@ -261,7 +261,7 @@
 
     private void handleOn() {
         mSystemInterface.setDisplayState(true);
-        sendPowerManagerEvent(CarPowerStateListener.ON, false);
+        sendPowerManagerEvent(CarPowerStateListener.ON);
         mHal.sendOn();
     }
 
@@ -273,7 +273,7 @@
                 || !newState.mCanSleep;
         if (newState.mCanPostpone) {
             Log.i(CarLog.TAG_POWER, "starting shutdown postpone");
-            sendPowerManagerEvent(CarPowerStateListener.SHUTDOWN_PREPARE, true);
+            sendPowerManagerEvent(CarPowerStateListener.SHUTDOWN_PREPARE);
             mHal.sendShutdownPrepare();
             doHandlePreprocessing();
         } else {
@@ -290,7 +290,7 @@
     }
 
     private void handleWaitForFinish(CpmsState state) {
-        sendPowerManagerEvent(state.mCarPowerStateListenerState, false);
+        sendPowerManagerEvent(state.mCarPowerStateListenerState);
         switch (state.mCarPowerStateListenerState) {
             case CarPowerStateListener.SUSPEND_ENTER:
                 mHal.sendSleepEntry(mNextWakeupSec);
@@ -333,26 +333,46 @@
         }
     }
 
-    private void sendPowerManagerEvent(int newState, boolean useTokens) {
+    private void sendPowerManagerEvent(int newState) {
+        // Based on new state, do we need to use tokens? In current design, SHUTDOWN_PREPARE
+        // is the only state where we need to maintain callback from listener components.
+        boolean useTokens = (newState == CarPowerStateListener.SHUTDOWN_PREPARE);
+
+        // First lets generate the tokens
+        generateTokensList(useTokens);
+
+        // Now lets notify listeners that we are making a state transition
+        sendBroadcasts(newState, useTokens);
+    }
+
+    private void generateTokensList(boolean useTokens) {
         synchronized (mPowerManagerListenerTokens) {
             if (useTokens) {
                 mPowerManagerListenerTokens.clear();
             }
             int i = mPowerManagerListeners.beginBroadcast();
             while (i-- > 0) {
+                ICarPowerStateListener listener = mPowerManagerListeners.getBroadcastItem(i);
+                if (useTokens) {
+                    mPowerManagerListenerTokens.put(listener.asBinder(), mTokenValue);
+                    mTokenValue++;
+                }
+            }
+            mPowerManagerListeners.finishBroadcast();
+        }
+    }
+
+    private void sendBroadcasts(int newState, boolean useTokens) {
+        synchronized (mPowerManagerListenerTokens) {
+            int i = mPowerManagerListeners.beginBroadcast();
+            while (i-- > 0) {
+                ICarPowerStateListener listener = mPowerManagerListeners.getBroadcastItem(i);
+                int token = useTokens ? mPowerManagerListenerTokens.get(listener.asBinder()) : 0;
                 try {
-                    int token = 0;
-                    ICarPowerStateListener listener = mPowerManagerListeners.getBroadcastItem(i);
-                    if (useTokens) {
-                        mPowerManagerListenerTokens.put(listener.asBinder(), mTokenValue);
-                        listener.onStateChanged(newState, mTokenValue);
-                        mTokenValue++;
-                    } else {
-                        listener.onStateChanged(newState, 0);
-                    }
+                    listener.onStateChanged(newState, token);
                 } catch (RemoteException e) {
                     // Its likely the connection snapped. Let binder death handle the situation.
-                    Log.e(CarLog.TAG_POWER, "onStateChanged calling failed: " + e);
+                    Log.e(CarLog.TAG_POWER, "onStateChanged() call failed: " + e, e);
                 }
             }
             mPowerManagerListeners.finishBroadcast();
@@ -472,7 +492,7 @@
     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
+        // TODO: Need to send current state to newly registered listener?  If so, need to handle
         //          token for SHUTDOWN_PREPARE state
     }