diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java index 62a67b6243d71..38eb7fb7fe0ba 100755 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java @@ -996,6 +996,11 @@ abstract class HdmiCecLocalDevice { */ protected void onStandby(boolean initiatedByCec, int standbyAction) {} + /** + * Called when the initialization of local devices is complete. + */ + protected void onInitializeCecComplete(int initiatedBy) {} + /** * Disable device. {@code callback} is used to get notified when all pending actions are * completed or timeout is issued. diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java index 6257032cf7090..98779197db693 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java @@ -222,6 +222,21 @@ public class HdmiCecLocalDevicePlayback extends HdmiCecLocalDeviceSource { } } + @Override + @ServiceThreadOnly + protected void onInitializeCecComplete(int initiatedBy) { + if (initiatedBy == HdmiControlService.INITIATED_BY_SCREEN_ON) { + oneTouchPlay(new IHdmiControlCallback.Stub() { + @Override + public void onComplete(int result) { + if (result != HdmiControlManager.RESULT_SUCCESS) { + Slog.w(TAG, "Failed to complete One Touch Play. result=" + result); + } + } + }); + } + } + @Override @ServiceThreadOnly void setAutoDeviceOff(boolean enabled) { diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java index cc0b8829fb7c7..b96aa3ab4e6b8 100644 --- a/services/core/java/com/android/server/hdmi/HdmiControlService.java +++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java @@ -29,6 +29,7 @@ import static com.android.server.hdmi.Constants.OPTION_MHL_SERVICE_CONTROL; import static com.android.server.hdmi.Constants.VERSION_1_4; import static com.android.server.power.ShutdownThread.SHUTDOWN_ACTION_PROPERTY; +import android.annotation.IntDef; import android.annotation.Nullable; import android.content.BroadcastReceiver; import android.content.ContentResolver; @@ -90,6 +91,8 @@ import libcore.util.EmptyArray; import java.io.FileDescriptor; import java.io.PrintWriter; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -178,6 +181,19 @@ public class HdmiControlService extends SystemService { private HdmiCecNetwork mHdmiCecNetwork; + static final int WAKE_UP_SCREEN_ON = 0; + static final int WAKE_UP_BOOT_UP = 1; + + // The reason code for starting the wake-up procedure. This procedure starts either by + // Intent.ACTION_SCREEN_ON or after boot-up. + @IntDef({ + WAKE_UP_SCREEN_ON, + WAKE_UP_BOOT_UP + }) + @Retention(RetentionPolicy.SOURCE) + public @interface WakeReason { + } + // Logical address of the active source. @GuardedBy("mLock") protected final ActiveSource mActiveSource = new ActiveSource(); @@ -237,7 +253,7 @@ public class HdmiControlService extends SystemService { break; case Intent.ACTION_SCREEN_ON: if (isPowerStandbyOrTransient()) { - onWakeUp(); + onWakeUp(WAKE_UP_SCREEN_ON); } break; case Intent.ACTION_CONFIGURATION_CHANGED: @@ -553,7 +569,7 @@ public class HdmiControlService extends SystemService { private void bootCompleted() { // on boot, if device is interactive, set HDMI CEC state as powered on as well if (mPowerManager.isInteractive() && isPowerStandbyOrTransient()) { - onWakeUp(); + onWakeUp(WAKE_UP_BOOT_UP); } } @@ -639,6 +655,12 @@ public class HdmiControlService extends SystemService { reason = HdmiControlManager.CONTROL_STATE_CHANGED_REASON_SETTING; break; case INITIATED_BY_SCREEN_ON: + reason = HdmiControlManager.CONTROL_STATE_CHANGED_REASON_WAKEUP; + final List devices = getAllLocalDevices(); + for (HdmiCecLocalDevice device : devices) { + device.onInitializeCecComplete(initiatedBy); + } + break; case INITIATED_BY_WAKE_UP_MESSAGE: reason = HdmiControlManager.CONTROL_STATE_CHANGED_REASON_WAKEUP; break; @@ -2893,14 +2915,26 @@ public class HdmiControlService extends SystemService { } @ServiceThreadOnly - private void onWakeUp() { + private void onWakeUp(@WakeReason final int wakeUpAction) { assertRunOnServiceThread(); mPowerStatus = HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON; if (mCecController != null) { if (mHdmiControlEnabled) { - int startReason = INITIATED_BY_SCREEN_ON; - if (mWakeUpMessageReceived) { - startReason = INITIATED_BY_WAKE_UP_MESSAGE; + int startReason = -1; + switch (wakeUpAction) { + case WAKE_UP_SCREEN_ON: + startReason = INITIATED_BY_SCREEN_ON; + if (mWakeUpMessageReceived) { + startReason = INITIATED_BY_WAKE_UP_MESSAGE; + } + break; + case WAKE_UP_BOOT_UP: + startReason = INITIATED_BY_BOOT_UP; + break; + default: + Slog.e(TAG, "wakeUpAction " + wakeUpAction + " not defined."); + return; + } initializeCec(startReason); } diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java index 440befcb33684..c0dad52be5a20 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java @@ -644,6 +644,91 @@ public class HdmiCecLocalDevicePlaybackTest { assertThat(mNativeWrapper.getResultMessages()).doesNotContain(standbyMessageBroadcast); } + @Test + public void handleOnInitializeCecComplete_ByEnableCec() { + mHdmiCecLocalDevicePlayback.onInitializeCecComplete( + mHdmiControlService.INITIATED_BY_ENABLE_CEC); + mTestLooper.dispatchAll(); + + HdmiCecMessage activeSource = + HdmiCecMessageBuilder.buildActiveSource(mPlaybackLogicalAddress, + mPlaybackPhysicalAddress); + HdmiCecMessage textViewOn = + HdmiCecMessageBuilder.buildTextViewOn(mPlaybackLogicalAddress, + ADDR_TV); + + assertThat(mNativeWrapper.getResultMessages()).doesNotContain(activeSource); + assertThat(mNativeWrapper.getResultMessages()).doesNotContain(textViewOn); + } + + @Test + public void handleOnInitializeCecComplete_ByBootUp() { + mHdmiCecLocalDevicePlayback.onInitializeCecComplete( + mHdmiControlService.INITIATED_BY_BOOT_UP); + mTestLooper.dispatchAll(); + + HdmiCecMessage activeSource = + HdmiCecMessageBuilder.buildActiveSource(mPlaybackLogicalAddress, + mPlaybackPhysicalAddress); + HdmiCecMessage textViewOn = + HdmiCecMessageBuilder.buildTextViewOn(mPlaybackLogicalAddress, + ADDR_TV); + + assertThat(mNativeWrapper.getResultMessages()).doesNotContain(activeSource); + assertThat(mNativeWrapper.getResultMessages()).doesNotContain(textViewOn); + } + + @Test + public void handleOnInitializeCecComplete_ByScreenOn() { + mHdmiCecLocalDevicePlayback.onInitializeCecComplete( + mHdmiControlService.INITIATED_BY_SCREEN_ON); + mTestLooper.dispatchAll(); + + HdmiCecMessage activeSource = + HdmiCecMessageBuilder.buildActiveSource(mPlaybackLogicalAddress, + mPlaybackPhysicalAddress); + HdmiCecMessage textViewOn = + HdmiCecMessageBuilder.buildTextViewOn(mPlaybackLogicalAddress, + ADDR_TV); + + assertThat(mNativeWrapper.getResultMessages()).contains(activeSource); + assertThat(mNativeWrapper.getResultMessages()).contains(textViewOn); + } + + @Test + public void handleOnInitializeCecComplete_ByWakeUpMessage() { + mHdmiCecLocalDevicePlayback.onInitializeCecComplete( + mHdmiControlService.INITIATED_BY_WAKE_UP_MESSAGE); + mTestLooper.dispatchAll(); + + HdmiCecMessage activeSource = + HdmiCecMessageBuilder.buildActiveSource(mPlaybackLogicalAddress, + mPlaybackPhysicalAddress); + HdmiCecMessage textViewOn = + HdmiCecMessageBuilder.buildTextViewOn(mPlaybackLogicalAddress, + ADDR_TV); + + assertThat(mNativeWrapper.getResultMessages()).doesNotContain(activeSource); + assertThat(mNativeWrapper.getResultMessages()).doesNotContain(textViewOn); + } + + @Test + public void handleOnInitializeCecComplete_ByHotplug() { + mHdmiCecLocalDevicePlayback.onInitializeCecComplete( + mHdmiControlService.INITIATED_BY_HOTPLUG); + mTestLooper.dispatchAll(); + + HdmiCecMessage activeSource = + HdmiCecMessageBuilder.buildActiveSource(mPlaybackLogicalAddress, + mPlaybackPhysicalAddress); + HdmiCecMessage textViewOn = + HdmiCecMessageBuilder.buildTextViewOn(mPlaybackLogicalAddress, + ADDR_TV); + + assertThat(mNativeWrapper.getResultMessages()).doesNotContain(activeSource); + assertThat(mNativeWrapper.getResultMessages()).doesNotContain(textViewOn); + } + @Test public void handleActiveSource_ActiveSource_None() { mHdmiCecLocalDevicePlayback.mPowerStateChangeOnActiveSourceLost =