diff options
4 files changed, 68 insertions, 23 deletions
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java index 1b478885e9cb..d17e9b32bd4f 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java @@ -202,6 +202,14 @@ abstract class HdmiCecLocalDevice { } /** + * Returns true if the local device allows the system to be put to standby. + * The default implementation returns true. + */ + protected boolean canGoToStandby() { + return true; + } + + /** * Dispatch incoming message. * * @param message incoming message diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java index 85a1a152b9ca..a8f6954405c3 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java @@ -19,6 +19,8 @@ package com.android.server.hdmi; import android.hardware.hdmi.HdmiControlManager; import android.hardware.hdmi.HdmiDeviceInfo; import android.hardware.hdmi.IHdmiControlCallback; +import android.os.PowerManager; +import android.os.PowerManager.WakeLock; import android.os.RemoteException; import android.os.SystemProperties; import android.util.Slog; @@ -34,17 +36,17 @@ final class HdmiCecLocalDevicePlayback extends HdmiCecLocalDevice { private boolean mIsActiveSource = false; + // Used to keep the device awake while it is the active source. For devices that + // cannot wake up via CEC commands, this address the inconvenience of having to + // turn them on. + // Lazily initialized - should call getWakeLock() to get the instance. + private WakeLock mWakeLock; + HdmiCecLocalDevicePlayback(HdmiControlService service) { super(service, HdmiDeviceInfo.DEVICE_PLAYBACK); } @Override - void init() { - super.init(); - mIsActiveSource = false; - } - - @Override @ServiceThreadOnly protected void onAddressAllocated(int logicalAddress, int reason) { assertRunOnServiceThread(); @@ -129,12 +131,37 @@ final class HdmiCecLocalDevicePlayback extends HdmiCecLocalDevice { if (connected && mService.isPowerStandbyOrTransient()) { mService.wakeUp(); } + if (!connected) { + getWakeLock().release(); + } } @ServiceThreadOnly - void markActiveSource() { + void setActiveSource(boolean on) { assertRunOnServiceThread(); - mIsActiveSource = true; + mIsActiveSource = on; + if (on) { + getWakeLock().acquire(); + HdmiLogger.debug("active source: %b. Wake lock acquired", mIsActiveSource); + } else { + getWakeLock().release(); + HdmiLogger.debug("Wake lock released"); + } + } + + @ServiceThreadOnly + private WakeLock getWakeLock() { + assertRunOnServiceThread(); + if (mWakeLock == null) { + mWakeLock = mService.getPowerManager().newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG); + mWakeLock.setReferenceCounted(false); + } + return mWakeLock; + } + + @Override + protected boolean canGoToStandby() { + return !getWakeLock().isHeld(); } @Override @@ -148,7 +175,7 @@ final class HdmiCecLocalDevicePlayback extends HdmiCecLocalDevice { private void mayResetActiveSource(int physicalAddress) { if (physicalAddress != mService.getPhysicalAddress()) { - mIsActiveSource = false; + setActiveSource(false); } } @@ -163,9 +190,9 @@ final class HdmiCecLocalDevicePlayback extends HdmiCecLocalDevice { return true; // Broadcast message. } - // Samsung model, we tested, sends <RoutingChange> and <RequestActiveSource> consecutively, - // Then if there is no <ActiveSource> response, it will change the input to - // the internal source. To handle this, we'll set ActiveSource aggressively. + // Samsung model we tested sends <Routing Change> and <Request Active Source> + // in a row, and then changes the input to the internal source if there is no + // <Active Source> in response. To handle this, we'll set ActiveSource aggressively. @Override @ServiceThreadOnly protected boolean handleRoutingChange(HdmiCecMessage message) { @@ -185,11 +212,7 @@ final class HdmiCecLocalDevicePlayback extends HdmiCecLocalDevice { } private void maySetActiveSource(int physicalAddress) { - if (physicalAddress == mService.getPhysicalAddress()) { - mIsActiveSource = true; - } else { - mIsActiveSource = false; - } + setActiveSource(physicalAddress == mService.getPhysicalAddress()); } private void wakeUpIfActiveSource() { @@ -226,7 +249,7 @@ final class HdmiCecLocalDevicePlayback extends HdmiCecLocalDevice { mService.sendCecCommand(HdmiCecMessageBuilder.buildInactiveSource( mAddress, mService.getPhysicalAddress())); } - mIsActiveSource = false; + setActiveSource(false); checkIfPendingActionsCleared(); } diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java index e8cb7204e5f6..2593e2b522ce 100644 --- a/services/core/java/com/android/server/hdmi/HdmiControlService.java +++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java @@ -277,6 +277,9 @@ public final class HdmiControlService extends SystemService { @Nullable private TvInputManager mTvInputManager; + @Nullable + private PowerManager mPowerManager; + // Last input port before switching to the MHL port. Should switch back to this port // when the mobile device sends the request one touch play with off. // Gets invalidated if we go to other port/input. @@ -353,6 +356,7 @@ public final class HdmiControlService extends SystemService { if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) { mTvInputManager = (TvInputManager) getContext().getSystemService( Context.TV_INPUT_SERVICE); + mPowerManager = (PowerManager) getContext().getSystemService(Context.POWER_SERVICE); } } @@ -370,6 +374,10 @@ public final class HdmiControlService extends SystemService { mTvInputManager.unregisterCallback(callback); } + PowerManager getPowerManager() { + return mPowerManager; + } + /** * Called when the initialization of local devices is complete. */ @@ -1859,8 +1867,7 @@ public final class HdmiControlService extends SystemService { void wakeUp() { assertRunOnServiceThread(); mWakeUpMessageReceived = true; - PowerManager pm = (PowerManager) getContext().getSystemService(Context.POWER_SERVICE); - pm.wakeUp(SystemClock.uptimeMillis()); + mPowerManager.wakeUp(SystemClock.uptimeMillis()); // PowerManger will send the broadcast Intent.ACTION_SCREEN_ON and after this gets // the intent, the sequence will continue at onWakeUp(). } @@ -1869,8 +1876,7 @@ public final class HdmiControlService extends SystemService { void standby() { assertRunOnServiceThread(); mStandbyMessageReceived = true; - PowerManager pm = (PowerManager) getContext().getSystemService(Context.POWER_SERVICE); - pm.goToSleep(SystemClock.uptimeMillis(), PowerManager.GO_TO_SLEEP_REASON_HDMI, 0); + mPowerManager.goToSleep(SystemClock.uptimeMillis(), PowerManager.GO_TO_SLEEP_REASON_HDMI, 0); // PowerManger will send the broadcast Intent.ACTION_SCREEN_OFF and after this gets // the intent, the sequence will continue at onStandby(). } @@ -1896,6 +1902,7 @@ public final class HdmiControlService extends SystemService { @ServiceThreadOnly private void onStandby() { assertRunOnServiceThread(); + if (!canGoToStandby()) return; mPowerStatus = HdmiControlManager.POWER_STATUS_TRANSIENT_TO_STANDBY; invokeVendorCommandListenersOnControlStateChanged(false, HdmiControlManager.CONTROL_STATE_CHANGED_REASON_STANDBY); @@ -1916,6 +1923,13 @@ public final class HdmiControlService extends SystemService { }); } + private boolean canGoToStandby() { + for (HdmiCecLocalDevice device : mCecController.getLocalDeviceList()) { + if (!device.canGoToStandby()) return false; + } + return true; + } + @ServiceThreadOnly private void onLanguageChanged(String language) { assertRunOnServiceThread(); diff --git a/services/core/java/com/android/server/hdmi/OneTouchPlayAction.java b/services/core/java/com/android/server/hdmi/OneTouchPlayAction.java index e764a1c85c79..a711102f84fd 100644 --- a/services/core/java/com/android/server/hdmi/OneTouchPlayAction.java +++ b/services/core/java/com/android/server/hdmi/OneTouchPlayAction.java @@ -82,7 +82,7 @@ final class OneTouchPlayAction extends HdmiCecFeatureAction { private void broadcastActiveSource() { sendCommand(HdmiCecMessageBuilder.buildActiveSource(getSourceAddress(), getSourcePath())); // Because only playback device can create this action, it's safe to cast. - playback().markActiveSource(); + playback().setActiveSource(true); } private void queryDevicePowerStatus() { |