Loading core/java/android/hardware/hdmi/HdmiControlManager.java +10 −0 Original line number Diff line number Diff line Loading @@ -138,6 +138,16 @@ public final class HdmiControlManager { */ public static final String EXTRA_LOCALE = "android.hardware.hdmi.extra.LOCALE"; /** * Broadcast Action: Active Source status was recovered by the device. * <p>Send when device becomes the current active source such that the activity * HdmiCecActiveSourceLostActivity can be finished and cleared from the screen. * <p>Requires {@link android.Manifest.permission#HDMI_CEC} to receive. * @hide */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_ON_ACTIVE_SOURCE_RECOVERED_DISMISS_UI = "android.hardware.hdmi.action.ON_ACTIVE_SOURCE_RECOVERED_DISMISS_UI"; /** * Volume value for mute state. */ Loading core/res/res/values/config.xml +5 −0 Original line number Diff line number Diff line Loading @@ -3351,6 +3351,11 @@ com.android.systemui/com.android.systemui.tv.hdmi.HdmiCecSetMenuLanguageActivity </string> <!-- Component name of the activity used to inform user that their device lost Active Source status and will go to standby if there is no interaction. --> <string name="config_hdmiCecActiveSourceLostActivity" >com.android.systemui/com.android.systemui.tv.hdmi.HdmiCecActiveSourceLostActivity</string> <!-- Name of the dialog that is used to request the user's consent for a Platform VPN --> <string name="config_platformVpnConfirmDialogComponent" translatable="false" >com.android.vpndialogs/com.android.vpndialogs.PlatformVpnConfirmDialog</string> Loading core/res/res/values/symbols.xml +1 −0 Original line number Diff line number Diff line Loading @@ -390,6 +390,7 @@ <java-symbol type="string" name="config_sensorUseStartedActivity_hwToggle" /> <java-symbol type="string" name="config_sensorStateChangedActivity" /> <java-symbol type="string" name="config_hdmiCecSetMenuLanguageActivity" /> <java-symbol type="string" name="config_hdmiCecActiveSourceLostActivity" /> <java-symbol type="integer" name="config_minNumVisibleRecentTasks_lowRam" /> <java-symbol type="integer" name="config_maxNumVisibleRecentTasks_lowRam" /> <java-symbol type="integer" name="config_minNumVisibleRecentTasks" /> Loading services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java +79 −1 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ import android.os.Binder; import android.os.Handler; import android.os.PowerManager; import android.os.SystemProperties; import android.os.UserHandle; import android.sysprop.HdmiProperties; import android.util.Slog; Loading @@ -53,6 +54,16 @@ public class HdmiCecLocalDevicePlayback extends HdmiCecLocalDeviceSource { @VisibleForTesting static final long STANDBY_AFTER_HOTPLUG_OUT_DELAY_MS = 30_000; // How long to wait on active source lost before possibly going to Standby. @VisibleForTesting static final long STANDBY_AFTER_ACTIVE_SOURCE_LOST_DELAY_MS = 30_000; // How long to wait after losing active source, before launching the pop-up that allows the user // to keep the device as the current active source. // We do this to prevent an unnecessary pop-up from being displayed when we lose and regain // active source within this timeout. static final long POPUP_AFTER_ACTIVE_SOURCE_LOST_DELAY_MS = 5_000; // 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. True by default, and can be disabled (i.e. device can go to sleep Loading @@ -64,6 +75,14 @@ public class HdmiCecLocalDevicePlayback extends HdmiCecLocalDeviceSource { // Handler for queueing a delayed Standby runnable after hotplug out. private Handler mDelayedStandbyHandler; // Handler for queueing a delayed Standby runnable after active source lost and after the pop-up // on active source lost was displayed. Handler mDelayedStandbyOnActiveSourceLostHandler; // Handler for queueing a delayed runnable that triggers a pop-up notification on active source // lost. private Handler mDelayedPopupOnActiveSourceLostHandler; // Determines what action should be taken upon receiving Routing Control messages. @VisibleForTesting protected HdmiProperties.playback_device_action_on_routing_control_values Loading @@ -75,6 +94,8 @@ public class HdmiCecLocalDevicePlayback extends HdmiCecLocalDeviceSource { super(service, HdmiDeviceInfo.DEVICE_PLAYBACK); mDelayedStandbyHandler = new Handler(service.getServiceLooper()); mDelayedStandbyOnActiveSourceLostHandler = new Handler(service.getServiceLooper()); mDelayedPopupOnActiveSourceLostHandler = new Handler(service.getServiceLooper()); mStandbyHandler = new HdmiCecStandbyModeHandler(service, this); } Loading Loading @@ -239,6 +260,28 @@ public class HdmiCecLocalDevicePlayback extends HdmiCecLocalDeviceSource { } } private class DelayedStandbyOnActiveSourceLostRunnable implements Runnable { @Override public void run() { if (mService.getPowerManagerInternal().wasDeviceIdleFor( STANDBY_AFTER_ACTIVE_SOURCE_LOST_DELAY_MS)) { mService.standby(); } else { mService.setAndBroadcastActiveSource(mService.getPhysicalAddress(), getDeviceInfo().getDeviceType(), Constants.ADDR_TV, "DelayedActiveSourceLostStandbyRunnable"); } } } @ServiceThreadOnly void dismissUiOnActiveSourceStatusRecovered() { assertRunOnServiceThread(); Intent intent = new Intent(HdmiControlManager.ACTION_ON_ACTIVE_SOURCE_RECOVERED_DISMISS_UI); mService.getContext().sendBroadcastAsUser(intent, UserHandle.ALL, HdmiControlService.PERMISSION); } @Override @ServiceThreadOnly protected void onStandby(boolean initiatedByCec, int standbyAction, Loading Loading @@ -387,13 +430,47 @@ public class HdmiCecLocalDevicePlayback extends HdmiCecLocalDeviceSource { switch (mService.getHdmiCecConfig().getStringValue( HdmiControlManager.CEC_SETTING_NAME_POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST)) { case HdmiControlManager.POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST_STANDBY_NOW: mService.standby(); mDelayedPopupOnActiveSourceLostHandler.removeCallbacksAndMessages(null); mDelayedPopupOnActiveSourceLostHandler.postDelayed( new Runnable() { @Override public void run() { if (!isActiveSource()) { startHdmiCecActiveSourceLostActivity(); mDelayedStandbyOnActiveSourceLostHandler .removeCallbacksAndMessages(null); mDelayedStandbyOnActiveSourceLostHandler.postDelayed( new DelayedStandbyOnActiveSourceLostRunnable(), STANDBY_AFTER_ACTIVE_SOURCE_LOST_DELAY_MS); } } }, POPUP_AFTER_ACTIVE_SOURCE_LOST_DELAY_MS); return; case HdmiControlManager.POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST_NONE: return; } } @VisibleForTesting @ServiceThreadOnly void startHdmiCecActiveSourceLostActivity() { final long identity = Binder.clearCallingIdentity(); try { Context context = mService.getContext(); Intent intent = new Intent(); intent.setComponent( ComponentName.unflattenFromString(context.getResources().getString( com.android.internal.R.string.config_hdmiCecActiveSourceLostActivity ))); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivityAsUser(intent, context.getUser()); } catch (ActivityNotFoundException e) { Slog.e(TAG, "Unable to start HdmiCecActiveSourceLostActivity"); } finally { Binder.restoreCallingIdentity(identity); } } @ServiceThreadOnly @Constants.HandleMessageResult protected int handleUserControlPressed(HdmiCecMessage message) { Loading Loading @@ -557,6 +634,7 @@ public class HdmiCecLocalDevicePlayback extends HdmiCecLocalDeviceSource { setActiveSource(physicalAddress, "HdmiCecLocalDevicePlayback#handleRoutingChangeAndInformation()"); } dismissUiOnActiveSourceStatusRecovered(); switch (mPlaybackDeviceActionOnRoutingControl) { case WAKE_UP_AND_SEND_ACTIVE_SOURCE: setAndBroadcastActiveSource(message, physicalAddress, Loading services/core/java/com/android/server/hdmi/HdmiControlService.java +2 −0 Original line number Diff line number Diff line Loading @@ -4205,10 +4205,12 @@ public class HdmiControlService extends SystemService { // playback will claim active source. Otherwise audio system will. if (deviceType == HdmiDeviceInfo.DEVICE_PLAYBACK) { HdmiCecLocalDevicePlayback playback = playback(); playback.dismissUiOnActiveSourceStatusRecovered(); playback.setActiveSource(playback.getDeviceInfo().getLogicalAddress(), physicalAddress, caller); playback.wakeUpIfActiveSource(); playback.maySendActiveSource(source); playback.mDelayedStandbyOnActiveSourceLostHandler.removeCallbacksAndMessages(null); } if (deviceType == HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM) { Loading Loading
core/java/android/hardware/hdmi/HdmiControlManager.java +10 −0 Original line number Diff line number Diff line Loading @@ -138,6 +138,16 @@ public final class HdmiControlManager { */ public static final String EXTRA_LOCALE = "android.hardware.hdmi.extra.LOCALE"; /** * Broadcast Action: Active Source status was recovered by the device. * <p>Send when device becomes the current active source such that the activity * HdmiCecActiveSourceLostActivity can be finished and cleared from the screen. * <p>Requires {@link android.Manifest.permission#HDMI_CEC} to receive. * @hide */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_ON_ACTIVE_SOURCE_RECOVERED_DISMISS_UI = "android.hardware.hdmi.action.ON_ACTIVE_SOURCE_RECOVERED_DISMISS_UI"; /** * Volume value for mute state. */ Loading
core/res/res/values/config.xml +5 −0 Original line number Diff line number Diff line Loading @@ -3351,6 +3351,11 @@ com.android.systemui/com.android.systemui.tv.hdmi.HdmiCecSetMenuLanguageActivity </string> <!-- Component name of the activity used to inform user that their device lost Active Source status and will go to standby if there is no interaction. --> <string name="config_hdmiCecActiveSourceLostActivity" >com.android.systemui/com.android.systemui.tv.hdmi.HdmiCecActiveSourceLostActivity</string> <!-- Name of the dialog that is used to request the user's consent for a Platform VPN --> <string name="config_platformVpnConfirmDialogComponent" translatable="false" >com.android.vpndialogs/com.android.vpndialogs.PlatformVpnConfirmDialog</string> Loading
core/res/res/values/symbols.xml +1 −0 Original line number Diff line number Diff line Loading @@ -390,6 +390,7 @@ <java-symbol type="string" name="config_sensorUseStartedActivity_hwToggle" /> <java-symbol type="string" name="config_sensorStateChangedActivity" /> <java-symbol type="string" name="config_hdmiCecSetMenuLanguageActivity" /> <java-symbol type="string" name="config_hdmiCecActiveSourceLostActivity" /> <java-symbol type="integer" name="config_minNumVisibleRecentTasks_lowRam" /> <java-symbol type="integer" name="config_maxNumVisibleRecentTasks_lowRam" /> <java-symbol type="integer" name="config_minNumVisibleRecentTasks" /> Loading
services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java +79 −1 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ import android.os.Binder; import android.os.Handler; import android.os.PowerManager; import android.os.SystemProperties; import android.os.UserHandle; import android.sysprop.HdmiProperties; import android.util.Slog; Loading @@ -53,6 +54,16 @@ public class HdmiCecLocalDevicePlayback extends HdmiCecLocalDeviceSource { @VisibleForTesting static final long STANDBY_AFTER_HOTPLUG_OUT_DELAY_MS = 30_000; // How long to wait on active source lost before possibly going to Standby. @VisibleForTesting static final long STANDBY_AFTER_ACTIVE_SOURCE_LOST_DELAY_MS = 30_000; // How long to wait after losing active source, before launching the pop-up that allows the user // to keep the device as the current active source. // We do this to prevent an unnecessary pop-up from being displayed when we lose and regain // active source within this timeout. static final long POPUP_AFTER_ACTIVE_SOURCE_LOST_DELAY_MS = 5_000; // 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. True by default, and can be disabled (i.e. device can go to sleep Loading @@ -64,6 +75,14 @@ public class HdmiCecLocalDevicePlayback extends HdmiCecLocalDeviceSource { // Handler for queueing a delayed Standby runnable after hotplug out. private Handler mDelayedStandbyHandler; // Handler for queueing a delayed Standby runnable after active source lost and after the pop-up // on active source lost was displayed. Handler mDelayedStandbyOnActiveSourceLostHandler; // Handler for queueing a delayed runnable that triggers a pop-up notification on active source // lost. private Handler mDelayedPopupOnActiveSourceLostHandler; // Determines what action should be taken upon receiving Routing Control messages. @VisibleForTesting protected HdmiProperties.playback_device_action_on_routing_control_values Loading @@ -75,6 +94,8 @@ public class HdmiCecLocalDevicePlayback extends HdmiCecLocalDeviceSource { super(service, HdmiDeviceInfo.DEVICE_PLAYBACK); mDelayedStandbyHandler = new Handler(service.getServiceLooper()); mDelayedStandbyOnActiveSourceLostHandler = new Handler(service.getServiceLooper()); mDelayedPopupOnActiveSourceLostHandler = new Handler(service.getServiceLooper()); mStandbyHandler = new HdmiCecStandbyModeHandler(service, this); } Loading Loading @@ -239,6 +260,28 @@ public class HdmiCecLocalDevicePlayback extends HdmiCecLocalDeviceSource { } } private class DelayedStandbyOnActiveSourceLostRunnable implements Runnable { @Override public void run() { if (mService.getPowerManagerInternal().wasDeviceIdleFor( STANDBY_AFTER_ACTIVE_SOURCE_LOST_DELAY_MS)) { mService.standby(); } else { mService.setAndBroadcastActiveSource(mService.getPhysicalAddress(), getDeviceInfo().getDeviceType(), Constants.ADDR_TV, "DelayedActiveSourceLostStandbyRunnable"); } } } @ServiceThreadOnly void dismissUiOnActiveSourceStatusRecovered() { assertRunOnServiceThread(); Intent intent = new Intent(HdmiControlManager.ACTION_ON_ACTIVE_SOURCE_RECOVERED_DISMISS_UI); mService.getContext().sendBroadcastAsUser(intent, UserHandle.ALL, HdmiControlService.PERMISSION); } @Override @ServiceThreadOnly protected void onStandby(boolean initiatedByCec, int standbyAction, Loading Loading @@ -387,13 +430,47 @@ public class HdmiCecLocalDevicePlayback extends HdmiCecLocalDeviceSource { switch (mService.getHdmiCecConfig().getStringValue( HdmiControlManager.CEC_SETTING_NAME_POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST)) { case HdmiControlManager.POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST_STANDBY_NOW: mService.standby(); mDelayedPopupOnActiveSourceLostHandler.removeCallbacksAndMessages(null); mDelayedPopupOnActiveSourceLostHandler.postDelayed( new Runnable() { @Override public void run() { if (!isActiveSource()) { startHdmiCecActiveSourceLostActivity(); mDelayedStandbyOnActiveSourceLostHandler .removeCallbacksAndMessages(null); mDelayedStandbyOnActiveSourceLostHandler.postDelayed( new DelayedStandbyOnActiveSourceLostRunnable(), STANDBY_AFTER_ACTIVE_SOURCE_LOST_DELAY_MS); } } }, POPUP_AFTER_ACTIVE_SOURCE_LOST_DELAY_MS); return; case HdmiControlManager.POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST_NONE: return; } } @VisibleForTesting @ServiceThreadOnly void startHdmiCecActiveSourceLostActivity() { final long identity = Binder.clearCallingIdentity(); try { Context context = mService.getContext(); Intent intent = new Intent(); intent.setComponent( ComponentName.unflattenFromString(context.getResources().getString( com.android.internal.R.string.config_hdmiCecActiveSourceLostActivity ))); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivityAsUser(intent, context.getUser()); } catch (ActivityNotFoundException e) { Slog.e(TAG, "Unable to start HdmiCecActiveSourceLostActivity"); } finally { Binder.restoreCallingIdentity(identity); } } @ServiceThreadOnly @Constants.HandleMessageResult protected int handleUserControlPressed(HdmiCecMessage message) { Loading Loading @@ -557,6 +634,7 @@ public class HdmiCecLocalDevicePlayback extends HdmiCecLocalDeviceSource { setActiveSource(physicalAddress, "HdmiCecLocalDevicePlayback#handleRoutingChangeAndInformation()"); } dismissUiOnActiveSourceStatusRecovered(); switch (mPlaybackDeviceActionOnRoutingControl) { case WAKE_UP_AND_SEND_ACTIVE_SOURCE: setAndBroadcastActiveSource(message, physicalAddress, Loading
services/core/java/com/android/server/hdmi/HdmiControlService.java +2 −0 Original line number Diff line number Diff line Loading @@ -4205,10 +4205,12 @@ public class HdmiControlService extends SystemService { // playback will claim active source. Otherwise audio system will. if (deviceType == HdmiDeviceInfo.DEVICE_PLAYBACK) { HdmiCecLocalDevicePlayback playback = playback(); playback.dismissUiOnActiveSourceStatusRecovered(); playback.setActiveSource(playback.getDeviceInfo().getLogicalAddress(), physicalAddress, caller); playback.wakeUpIfActiveSource(); playback.maySendActiveSource(source); playback.mDelayedStandbyOnActiveSourceLostHandler.removeCallbacksAndMessages(null); } if (deviceType == HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM) { Loading