Merge "Add API setProhibitMode in HdmiControlService"
diff --git a/Android.mk b/Android.mk
index 5ffafc0..c22bc73 100644
--- a/Android.mk
+++ b/Android.mk
@@ -151,6 +151,7 @@
 	core/java/android/hardware/hdmi/IHdmiControlService.aidl \
 	core/java/android/hardware/hdmi/IHdmiDeviceEventListener.aidl \
 	core/java/android/hardware/hdmi/IHdmiHotplugEventListener.aidl \
+	core/java/android/hardware/hdmi/IHdmiInputChangeListener.aidl \
 	core/java/android/hardware/hdmi/IHdmiSystemAudioModeChangeListener.aidl \
 	core/java/android/hardware/input/IInputManager.aidl \
 	core/java/android/hardware/input/IInputDevicesChangedListener.aidl \
diff --git a/core/java/android/hardware/hdmi/HdmiCecDeviceInfo.java b/core/java/android/hardware/hdmi/HdmiCecDeviceInfo.java
index fbfcca0..e1bb780 100644
--- a/core/java/android/hardware/hdmi/HdmiCecDeviceInfo.java
+++ b/core/java/android/hardware/hdmi/HdmiCecDeviceInfo.java
@@ -105,6 +105,15 @@
     }
 
     /**
+     * Return {@code true} if the device is of a type that can be an input source.
+     */
+    public boolean isSourceType() {
+        return mDeviceType == HdmiCec.DEVICE_PLAYBACK
+                || mDeviceType == HdmiCec.DEVICE_RECORDER
+                || mDeviceType == HdmiCec.DEVICE_TUNER;
+    }
+
+    /**
      * Return display (OSD) name of the device.
      */
     public String getDisplayName() {
diff --git a/core/java/android/hardware/hdmi/IHdmiControlService.aidl b/core/java/android/hardware/hdmi/IHdmiControlService.aidl
index 0798311..3f0f2ae 100644
--- a/core/java/android/hardware/hdmi/IHdmiControlService.aidl
+++ b/core/java/android/hardware/hdmi/IHdmiControlService.aidl
@@ -21,6 +21,7 @@
 import android.hardware.hdmi.IHdmiControlCallback;
 import android.hardware.hdmi.IHdmiDeviceEventListener;
 import android.hardware.hdmi.IHdmiHotplugEventListener;
+import android.hardware.hdmi.IHdmiInputChangeListener;
 import android.hardware.hdmi.IHdmiSystemAudioModeChangeListener;
 
 import java.util.List;
@@ -54,4 +55,6 @@
     void setProhibitMode(boolean enabled);
     oneway void setSystemAudioVolume(int oldIndex, int newIndex, int maxIndex);
     oneway void setSystemAudioMute(boolean mute);
+    void setInputChangeListener(IHdmiInputChangeListener listener);
+    List<HdmiCecDeviceInfo> getInputDevices();
 }
diff --git a/core/java/android/hardware/hdmi/IHdmiInputChangeListener.aidl b/core/java/android/hardware/hdmi/IHdmiInputChangeListener.aidl
new file mode 100644
index 0000000..98ad300
--- /dev/null
+++ b/core/java/android/hardware/hdmi/IHdmiInputChangeListener.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.hdmi;
+
+import android.hardware.hdmi.HdmiCecDeviceInfo;
+
+/**
+ * Callback interface definition for TV to get informed of
+ * the input change event coming from other device.
+ *
+ * @hide
+ */
+oneway interface IHdmiInputChangeListener {
+    void onChanged(in HdmiCecDeviceInfo device);
+}
diff --git a/services/core/java/com/android/server/hdmi/ActiveSourceHandler.java b/services/core/java/com/android/server/hdmi/ActiveSourceHandler.java
index 92fab2d..dcf43a3 100644
--- a/services/core/java/com/android/server/hdmi/ActiveSourceHandler.java
+++ b/services/core/java/com/android/server/hdmi/ActiveSourceHandler.java
@@ -92,7 +92,7 @@
                 HdmiCecMessage routingChange = HdmiCecMessageBuilder.buildRoutingChange(
                         getSourceAddress(), activePath, currentPath);
                 mService.sendCecCommand(routingChange);
-                tv.addAndStartAction(new RoutingControlAction(tv, currentPath, mCallback));
+                tv.addAndStartAction(new RoutingControlAction(tv, currentPath, true, mCallback));
             }
         }
     }
diff --git a/services/core/java/com/android/server/hdmi/DeviceSelectAction.java b/services/core/java/com/android/server/hdmi/DeviceSelectAction.java
index b97350d..18bba37 100644
--- a/services/core/java/com/android/server/hdmi/DeviceSelectAction.java
+++ b/services/core/java/com/android/server/hdmi/DeviceSelectAction.java
@@ -165,9 +165,9 @@
 
     private void turnOnDevice() {
         sendUserControlPressedAndReleased(mTarget.getLogicalAddress(),
-                HdmiConstants.UI_COMMAND_POWER);
+                HdmiCecKeycode.CEC_KEYCODE_POWER);
         sendUserControlPressedAndReleased(mTarget.getLogicalAddress(),
-                HdmiConstants.UI_COMMAND_POWER_ON_FUNCTION);
+                HdmiCecKeycode.CEC_KEYCODE_POWER_ON_FUNCTION);
         mState = STATE_WAIT_FOR_DEVICE_POWER_ON;
         addTimer(mState, TIMEOUT_POWER_ON_MS);
     }
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
index 093cc17..d6d6006 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
@@ -293,8 +293,6 @@
     @ServiceThreadOnly
     protected boolean handleUserControlPressed(HdmiCecMessage message) {
         assertRunOnServiceThread();
-        final int opCode = message.getOpcode();
-        final byte[] params = message.getParams();
         if (mService.isPowerOnOrTransient() && isPowerOffOrToggleCommand(message)) {
             mService.standby();
             return true;
@@ -308,17 +306,17 @@
     private static boolean isPowerOnOrToggleCommand(HdmiCecMessage message) {
         byte[] params = message.getParams();
         return message.getOpcode() == HdmiCec.MESSAGE_USER_CONTROL_PRESSED && params.length == 1
-                && (params[0] == HdmiConstants.UI_COMMAND_POWER
-                        || params[0] == HdmiConstants.UI_COMMAND_POWER_ON_FUNCTION
-                        || params[0] == HdmiConstants.UI_COMMAND_POWER_TOGGLE_FUNCTION);
+                && (params[0] == HdmiCecKeycode.CEC_KEYCODE_POWER
+                        || params[0] == HdmiCecKeycode.CEC_KEYCODE_POWER_ON_FUNCTION
+                        || params[0] == HdmiCecKeycode.CEC_KEYCODE_POWER_TOGGLE_FUNCTION);
     }
 
     private static boolean isPowerOffOrToggleCommand(HdmiCecMessage message) {
         byte[] params = message.getParams();
         return message.getOpcode() == HdmiCec.MESSAGE_USER_CONTROL_PRESSED && params.length == 1
-                && (params[0] == HdmiConstants.UI_COMMAND_POWER
-                        || params[0] == HdmiConstants.UI_COMMAND_POWER_OFF_FUNCTION
-                        || params[0] == HdmiConstants.UI_COMMAND_POWER_TOGGLE_FUNCTION);
+                && (params[0] == HdmiCecKeycode.CEC_KEYCODE_POWER
+                        || params[0] == HdmiCecKeycode.CEC_KEYCODE_POWER_OFF_FUNCTION
+                        || params[0] == HdmiCecKeycode.CEC_KEYCODE_POWER_TOGGLE_FUNCTION);
     }
 
     protected boolean handleTextViewOn(HdmiCecMessage message) {
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
index dafcc46..eb80b20 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
@@ -21,6 +21,7 @@
 import android.hardware.hdmi.HdmiCecMessage;
 import android.hardware.hdmi.IHdmiControlCallback;
 import android.media.AudioSystem;
+import android.os.IBinder;
 import android.os.RemoteException;
 import android.util.Slog;
 import android.util.SparseArray;
@@ -69,9 +70,9 @@
     // Copy of mDeviceInfos to guarantee thread-safety.
     @GuardedBy("mLock")
     private List<HdmiCecDeviceInfo> mSafeAllDeviceInfos = Collections.emptyList();
-    // All external cec device which excludes local devices.
+    // All external cec input(source) devices. Does not include system audio device.
     @GuardedBy("mLock")
-    private List<HdmiCecDeviceInfo> mSafeExternalDeviceInfos = Collections.emptyList();
+    private List<HdmiCecDeviceInfo> mSafeExternalInputs = Collections.emptyList();
 
     // Map-like container of all cec devices including local ones.
     // A logical address of device is used as key of container.
@@ -186,6 +187,7 @@
         setPrevPortId(portId);
         // TODO: Actually switch the physical port here. Handle PAP/PIP as well.
         //       Show OSD port change banner
+        mService.invokeInputChangeListener(getActiveSource());
     }
 
     @ServiceThreadOnly
@@ -211,7 +213,7 @@
         HdmiCecMessage routingChange =
                 HdmiCecMessageBuilder.buildRoutingChange(mAddress, oldPath, newPath);
         mService.sendCecCommand(routingChange);
-        addAndStartAction(new RoutingControlAction(this, newPath, callback));
+        addAndStartAction(new RoutingControlAction(this, newPath, false, callback));
     }
 
     /**
@@ -347,7 +349,7 @@
             int newPath = mService.portIdToPath(getActivePortId());
             mService.sendCecCommand(HdmiCecMessageBuilder.buildRoutingChange(
                     mAddress, getActivePath(), newPath));
-            addAndStartAction(new RoutingControlAction(this, getActivePortId(), null));
+            addAndStartAction(new RoutingControlAction(this, getActivePortId(), false, null));
         }
     }
 
@@ -393,7 +395,7 @@
             int newPath = HdmiUtils.twoBytesToInt(params, 2);
             setActivePath(newPath);
             removeAction(RoutingControlAction.class);
-            addAndStartAction(new RoutingControlAction(this, newPath, null));
+            addAndStartAction(new RoutingControlAction(this, newPath, true, null));
         }
         return true;
     }
@@ -807,17 +809,11 @@
     }
 
     /**
-     * Return a list of  {@link HdmiCecDeviceInfo}.
-     *
-     * @param includeLocalDevice whether to include local device in result.
+     * Return external input devices.
      */
-    List<HdmiCecDeviceInfo> getSafeDeviceInfoList(boolean includeLocalDevice) {
+    List<HdmiCecDeviceInfo> getSafeExternalInputs() {
         synchronized (mLock) {
-            if (includeLocalDevice) {
-                return mSafeAllDeviceInfos;
-            } else {
-                return mSafeExternalDeviceInfos;
-            }
+            return mSafeExternalInputs;
         }
     }
 
@@ -825,13 +821,33 @@
     private void updateSafeDeviceInfoList() {
         assertRunOnServiceThread();
         List<HdmiCecDeviceInfo> copiedDevices = HdmiUtils.sparseArrayToList(mDeviceInfos);
-        List<HdmiCecDeviceInfo> externalDeviceInfos = getDeviceInfoList(false);
+        List<HdmiCecDeviceInfo> externalInputs = getInputDevices();
         synchronized (mLock) {
             mSafeAllDeviceInfos = copiedDevices;
-            mSafeExternalDeviceInfos = externalDeviceInfos;
+            mSafeExternalInputs = externalInputs;
         }
     }
 
+    /**
+     * Return a list of external cec input (source) devices.
+     *
+     * <p>Note that this effectively excludes non-source devices like system audio,
+     * secondary TV.
+     */
+    private List<HdmiCecDeviceInfo> getInputDevices() {
+        ArrayList<HdmiCecDeviceInfo> infoList = new ArrayList<>();
+        for (int i = 0; i < mDeviceInfos.size(); ++i) {
+            HdmiCecDeviceInfo info = mDeviceInfos.valueAt(i);
+            if (isLocalDeviceAddress(i)) {
+                continue;
+            }
+            if (info.isSourceType()) {
+                infoList.add(info);
+            }
+        }
+        return infoList;
+    }
+
     @ServiceThreadOnly
     private boolean isLocalDeviceAddress(int address) {
         assertRunOnServiceThread();
@@ -911,19 +927,21 @@
     final void removeCecDevice(int address) {
         assertRunOnServiceThread();
         HdmiCecDeviceInfo info = removeDeviceInfo(address);
-        handleRemoveActiveRoutingPath(info.getPhysicalAddress());
+
         mCecMessageCache.flushMessagesFrom(address);
         mService.invokeDeviceEventListeners(info, false);
     }
 
-    private void handleRemoveActiveRoutingPath(int path) {
+    @ServiceThreadOnly
+    void handleRemoveActiveRoutingPath(int path) {
+        assertRunOnServiceThread();
         // Seq #23
         if (isTailOfActivePath(path, getActivePath())) {
             removeAction(RoutingControlAction.class);
             int newPath = mService.portIdToPath(getActivePortId());
             mService.sendCecCommand(HdmiCecMessageBuilder.buildRoutingChange(
                     mAddress, getActivePath(), newPath));
-            addAndStartAction(new RoutingControlAction(this, getActivePortId(), null));
+            addAndStartAction(new RoutingControlAction(this, getActivePortId(), true, null));
         }
     }
 
@@ -939,7 +957,7 @@
             int newPath = mService.portIdToPath(getActivePortId());
             mService.sendCecCommand(
                     HdmiCecMessageBuilder.buildRoutingChange(mAddress, getActivePath(), newPath));
-            addAndStartAction(new RoutingControlAction(this, getActivePortId(), null));
+            addAndStartAction(new RoutingControlAction(this, getActivePortId(), false, null));
         } else {
             int activePath = mService.getPhysicalAddress();
             setActivePath(activePath);
diff --git a/services/core/java/com/android/server/hdmi/HdmiConstants.java b/services/core/java/com/android/server/hdmi/HdmiConstants.java
index c0accc3..3f9e517 100644
--- a/services/core/java/com/android/server/hdmi/HdmiConstants.java
+++ b/services/core/java/com/android/server/hdmi/HdmiConstants.java
@@ -37,18 +37,6 @@
     static final int SYSTEM_AUDIO_STATUS_OFF = 0;
     static final int SYSTEM_AUDIO_STATUS_ON = 1;
 
-    // Constants related to UI Command Codes.
-    // Refer to CEC Table 30 in HDMI Spec v1.4b.
-    static final int UI_COMMAND_POWER = 0x40;
-    static final int UI_COMMAND_VOLUME_UP = 0x41;
-    static final int UI_COMMAND_VOLUME_DOWN = 0x42;
-    static final int UI_COMMAND_MUTE = 0x43;
-    static final int UI_COMMAND_MUTE_FUNCTION = 0x65;
-    static final int UI_COMMAND_RESTORE_VOLUME_FUNCTION = 0x66;
-    static final int UI_COMMAND_POWER_TOGGLE_FUNCTION = 0x6B;
-    static final int UI_COMMAND_POWER_OFF_FUNCTION = 0x6C;
-    static final int UI_COMMAND_POWER_ON_FUNCTION = 0x6D;
-
     // Bit mask used to get the routing path of the top level device.
     // When &'d with the path 1.2.2.0 (0x1220), for instance, gives 1.0.0.0.
     static final int ROUTING_PATH_TOP_MASK = 0xF000;
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 0243510..6dd3250 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -30,6 +30,7 @@
 import android.hardware.hdmi.IHdmiControlService;
 import android.hardware.hdmi.IHdmiDeviceEventListener;
 import android.hardware.hdmi.IHdmiHotplugEventListener;
+import android.hardware.hdmi.IHdmiInputChangeListener;
 import android.hardware.hdmi.IHdmiSystemAudioModeChangeListener;
 import android.media.AudioManager;
 import android.os.Build;
@@ -139,6 +140,12 @@
     private final ArrayList<DeviceEventListenerRecord> mDeviceEventListenerRecords =
             new ArrayList<>();
 
+    @GuardedBy("mLock")
+    private IHdmiInputChangeListener mInputChangeListener;
+
+    @GuardedBy("mLock")
+    private InputChangeListenerRecord mInputChangeListenerRecord;
+
     // Set to true while HDMI control is enabled. If set to false, HDMI-CEC/MHL protocol
     // handling will be disabled and no request will be handled.
     @GuardedBy("mLock")
@@ -781,6 +788,24 @@
         }
 
         @Override
+        public void setInputChangeListener(final IHdmiInputChangeListener listener) {
+            enforceAccessPermission();
+            HdmiControlService.this.setInputChangeListener(listener);
+        }
+
+        @Override
+        public List<HdmiCecDeviceInfo> getInputDevices() {
+            enforceAccessPermission();
+            // No need to hold the lock for obtaining TV device as the local device instance
+            // is preserved while the HDMI control is enabled.
+            HdmiCecLocalDeviceTv tv = tv();
+            if (tv == null) {
+                return Collections.emptyList();
+            }
+            return tv.getSafeExternalInputs();
+        }
+
+        @Override
         public void setControlEnabled(final boolean enabled) {
             enforceAccessPermission();
             synchronized (mLock) {
@@ -999,6 +1024,41 @@
         }
     }
 
+    private final class InputChangeListenerRecord implements IBinder.DeathRecipient {
+        @Override
+        public void binderDied() {
+            synchronized (mLock) {
+                mInputChangeListener = null;
+            }
+        }
+    }
+
+    private void setInputChangeListener(IHdmiInputChangeListener listener) {
+        synchronized (mLock) {
+            mInputChangeListenerRecord = new InputChangeListenerRecord();
+            try {
+                listener.asBinder().linkToDeath(mInputChangeListenerRecord, 0);
+            } catch (RemoteException e) {
+                Slog.w(TAG, "Listener already died");
+                return;
+            }
+            mInputChangeListener = listener;
+        }
+    }
+
+    void invokeInputChangeListener(int activeAddress) {
+        synchronized (mLock) {
+            if (mInputChangeListener != null) {
+                HdmiCecDeviceInfo activeSource = getDeviceInfo(activeAddress);
+                try {
+                    mInputChangeListener.onChanged(activeSource);
+                } catch (RemoteException e) {
+                    Slog.w(TAG, "Exception thrown by IHdmiInputChangeListener: " + e);
+                }
+            }
+        }
+    }
+
     private void invokeCallback(IHdmiControlCallback callback, int result) {
         try {
             callback.onComplete(result);
diff --git a/services/core/java/com/android/server/hdmi/HotplugDetectionAction.java b/services/core/java/com/android/server/hdmi/HotplugDetectionAction.java
index 7c6c303..8ee92f3 100644
--- a/services/core/java/com/android/server/hdmi/HotplugDetectionAction.java
+++ b/services/core/java/com/android/server/hdmi/HotplugDetectionAction.java
@@ -34,6 +34,7 @@
  * If system audio is on, check hot-plug for audio system every 5 secs.
  * For other devices, keep 15 secs period.
  */
+// Seq #3
 final class HotplugDetectionAction extends FeatureAction {
     private static final String TAG = "HotPlugDetectionAction";
 
@@ -193,14 +194,12 @@
     }
 
     private void addDevice(int addedAddress) {
-        // Send <Give Physical Address>.
+        // Sending <Give Physical Address> will initiate new device action.
         sendCommand(HdmiCecMessageBuilder.buildGivePhysicalAddress(getSourceAddress(),
                 addedAddress));
     }
 
     private void removeDevice(int removedAddress) {
-        // TODO: move the following logic to local device once move many logic to
-        //       local device.
         mayChangeRoutingPath(removedAddress);
         mayCancelDeviceSelect(removedAddress);
         mayCancelOneTouchRecord(removedAddress);
@@ -210,10 +209,10 @@
     }
 
     private void mayChangeRoutingPath(int address) {
-        // TODO: if removed address is current active source, it should change active source
-        // path new one. we can keep previous selection or can choose default input,
-        // such as internal tuner. Consider send intent to app so that app
-        // can handle it.
+        HdmiCecDeviceInfo info = tv().getDeviceInfo(address);
+        if (info != null) {
+            tv().handleRemoveActiveRoutingPath(info.getPhysicalAddress());
+        }
     }
 
     private void mayCancelDeviceSelect(int address) {
diff --git a/services/core/java/com/android/server/hdmi/RoutingControlAction.java b/services/core/java/com/android/server/hdmi/RoutingControlAction.java
index 0c3bc0c..5f3c654 100644
--- a/services/core/java/com/android/server/hdmi/RoutingControlAction.java
+++ b/services/core/java/com/android/server/hdmi/RoutingControlAction.java
@@ -44,13 +44,13 @@
 
     // State in which we wait for <Routing Information> to arrive. If timed out, we use the
     // latest routing path to set the new active source.
-    private final static int STATE_WAIT_FOR_ROUTING_INFORMATION = 1;
+    private static final int STATE_WAIT_FOR_ROUTING_INFORMATION = 1;
 
     // State in which we wait for <Report Power Status> in response to <Give Device Power Status>
     // we have sent. If the response tells us the device power is on, we send <Set Stream Path>
     // to make it the active source. Otherwise we do not send <Set Stream Path>, and possibly
     // just show the blank screen.
-    private final static int STATE_WAIT_FOR_REPORT_POWER_STATUS = 2;
+    private static final int STATE_WAIT_FOR_REPORT_POWER_STATUS = 2;
 
     // Time out in millseconds used for <Routing Information>
     private static final int TIMEOUT_ROUTING_INFORMATION_MS = 1000;
@@ -58,15 +58,20 @@
     // Time out in milliseconds used for <Report Power Status>
     private static final int TIMEOUT_REPORT_POWER_STATUS_MS = 1000;
 
+    // true if <Give Power Status> should be sent once the new active routing path is determined.
+    private final boolean mQueryDevicePowerStatus;
+
     @Nullable private final IHdmiControlCallback mCallback;
 
     // The latest routing path. Updated by each <Routing Information> from CEC switches.
     private int mCurrentRoutingPath;
 
-    RoutingControlAction(HdmiCecLocalDevice localDevice, int path, IHdmiControlCallback callback) {
+    RoutingControlAction(HdmiCecLocalDevice localDevice, int path, boolean queryDevicePowerStatus,
+            IHdmiControlCallback callback) {
         super(localDevice);
         mCallback = callback;
         mCurrentRoutingPath = path;
+        mQueryDevicePowerStatus = queryDevicePowerStatus;
     }
 
     @Override
@@ -138,13 +143,7 @@
         switch (timeoutState) {
             case STATE_WAIT_FOR_ROUTING_INFORMATION:
                 HdmiCecDeviceInfo device = tv().getDeviceInfoByPath(mCurrentRoutingPath);
-                if (device == null) {
-                    tv().updateActivePortId(tv().pathToPortId(mCurrentRoutingPath));
-                } else {
-                    // TODO: Also check followings and then proceed:
-                    //       if routing change was neither triggered by TV at CEC enable time, nor
-                    //       at the detection of new device at the end of the active routing path, nor
-                    //       by TV power on with HDMI input as the active signal source.
+                if (device != null && mQueryDevicePowerStatus) {
                     int deviceLogicalAddress = device.getLogicalAddress();
                     queryDevicePowerStatus(deviceLogicalAddress, new SendMessageCallback() {
                         @Override
@@ -152,6 +151,8 @@
                             handlDevicePowerStatusAckResult(error == HdmiCec.RESULT_SUCCESS);
                         }
                     });
+                } else {
+                    tv().updateActivePortId(tv().pathToPortId(mCurrentRoutingPath));
                 }
                 return;
             case STATE_WAIT_FOR_REPORT_POWER_STATUS:
diff --git a/services/core/java/com/android/server/hdmi/SystemAudioStatusAction.java b/services/core/java/com/android/server/hdmi/SystemAudioStatusAction.java
index ecb158b..fb61674 100644
--- a/services/core/java/com/android/server/hdmi/SystemAudioStatusAction.java
+++ b/services/core/java/com/android/server/hdmi/SystemAudioStatusAction.java
@@ -70,8 +70,8 @@
         tv().setAudioStatus(false, HdmiConstants.UNKNOWN_VOLUME);
 
         int uiCommand = tv().getSystemAudioMode()
-                ? HdmiConstants.UI_COMMAND_RESTORE_VOLUME_FUNCTION  // SystemAudioMode: ON
-                : HdmiConstants.UI_COMMAND_MUTE_FUNCTION;           // SystemAudioMode: OFF
+                ? HdmiCecKeycode.CEC_KEYCODE_RESTORE_VOLUME_FUNCTION  // SystemAudioMode: ON
+                : HdmiCecKeycode.CEC_KEYCODE_MUTE_FUNCTION;           // SystemAudioMode: OFF
         sendUserControlPressedAndReleased(mAvrAddress, uiCommand);
 
         // Still return SUCCESS to callback.
@@ -102,7 +102,7 @@
 
             if ((tv().getSystemAudioMode() && mute) || (!tv().getSystemAudioMode() && !mute)) {
                 // Toggle AVR's mute status to match with the system audio status.
-                sendUserControlPressedAndReleased(mAvrAddress, HdmiConstants.UI_COMMAND_MUTE);
+                sendUserControlPressedAndReleased(mAvrAddress, HdmiCecKeycode.CEC_KEYCODE_MUTE);
             }
             finishWithCallback(HdmiCec.RESULT_SUCCESS);
         } else {
diff --git a/services/core/java/com/android/server/hdmi/VolumeControlAction.java b/services/core/java/com/android/server/hdmi/VolumeControlAction.java
index 07c72f7..350ce36 100644
--- a/services/core/java/com/android/server/hdmi/VolumeControlAction.java
+++ b/services/core/java/com/android/server/hdmi/VolumeControlAction.java
@@ -130,7 +130,6 @@
         return mTargetVolume == VOLUME_MUTE || mTargetVolume == VOLUME_RESTORE;
     }
 
-
     private void startVolumeChange() {
         mTimeoutCount = 0;
         sendVolumeChange(mIsVolumeUp);
@@ -146,8 +145,8 @@
 
     private void sendMuteChange(boolean mute) {
         sendUserControlPressedAndReleased(mAvrAddress,
-                mute ? HdmiConstants.UI_COMMAND_MUTE_FUNCTION :
-                        HdmiConstants.UI_COMMAND_RESTORE_VOLUME_FUNCTION);
+                mute ? HdmiCecKeycode.CEC_KEYCODE_MUTE_FUNCTION :
+                        HdmiCecKeycode.CEC_KEYCODE_RESTORE_VOLUME_FUNCTION);
     }
 
     @Override