Handle the power state change.
- Add BrocastIntent listener to catch SCREEN_ON/OFF intents. - Add callbacks onTransitionToStandBy(), onStandBy() in HdmiCecLocalDevice.java. - When it gets the SCREEN_OFF intent, the state will be TRANSITION_TO_STANDBY, then when there is no outstanding actions, the state will be STANDBY. - When the state is STANDBY, the TV device will broadcast <StandBy>. - When it gets the SCREEN_ON intent, the state will be TRANSITION_TO_ON, then when the initialization is done, the state will be ON. - When the state is ON and it receives <StandBy> CEC message, it will force the system to go to sleep. - When the state is STANDBY and it receives the cec messages to wake-up the system, it will force the system to wake up from sleep. - Manage the active source state for the playback device. Change-Id: Ib473219a0b0deb5224df89386db5a83720000411
This commit is contained in:
@@ -155,6 +155,18 @@ abstract class HdmiCecLocalDevice {
|
||||
return handleSystemAudioModeStatus(message);
|
||||
case HdmiCec.MESSAGE_REPORT_AUDIO_STATUS:
|
||||
return handleReportAudioStatus(message);
|
||||
case HdmiCec.MESSAGE_STANDBY:
|
||||
return handleStandby(message);
|
||||
case HdmiCec.MESSAGE_TEXT_VIEW_ON:
|
||||
return handleTextViewOn(message);
|
||||
case HdmiCec.MESSAGE_IMAGE_VIEW_ON:
|
||||
return handleImageViewOn(message);
|
||||
case HdmiCec.MESSAGE_USER_CONTROL_PRESSED:
|
||||
return handleUserControlPressed(message);
|
||||
case HdmiCec.MESSAGE_SET_STREAM_PATH:
|
||||
return handleSetStreamPath(message);
|
||||
case HdmiCec.MESSAGE_GIVE_DEVICE_POWER_STATUS:
|
||||
return handleGiveDevicePowerStatus(message);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@@ -275,6 +287,67 @@ abstract class HdmiCecLocalDevice {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ServiceThreadOnly
|
||||
protected boolean handleStandby(HdmiCecMessage message) {
|
||||
assertRunOnServiceThread();
|
||||
// Seq #12
|
||||
if (mService.isControlEnabled() && !isInPresetInstallationMode()
|
||||
&& mService.isPowerOnOrTransient()) {
|
||||
mService.standby();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@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;
|
||||
} else if (mService.isPowerStandbyOrTransient() && isPowerOnOrToggleCommand(message)) {
|
||||
mService.wakeUp();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
protected boolean handleTextViewOn(HdmiCecMessage message) {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected boolean handleImageViewOn(HdmiCecMessage message) {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected boolean handleSetStreamPath(HdmiCecMessage message) {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected boolean handleGiveDevicePowerStatus(HdmiCecMessage message) {
|
||||
mService.sendCecCommand(HdmiCecMessageBuilder.buildReportPowerStatus(
|
||||
mAddress, message.getSource(), mService.getPowerStatus()));
|
||||
return true;
|
||||
}
|
||||
|
||||
@ServiceThreadOnly
|
||||
final void handleAddressAllocated(int logicalAddress) {
|
||||
assertRunOnServiceThread();
|
||||
@@ -323,6 +396,10 @@ abstract class HdmiCecLocalDevice {
|
||||
@ServiceThreadOnly
|
||||
void addAndStartAction(final FeatureAction action) {
|
||||
assertRunOnServiceThread();
|
||||
if (mService.isPowerStandbyOrTransient()) {
|
||||
Slog.w(TAG, "Skip the action during Standby: " + action);
|
||||
return;
|
||||
}
|
||||
mActions.add(action);
|
||||
action.start();
|
||||
}
|
||||
@@ -361,6 +438,7 @@ abstract class HdmiCecLocalDevice {
|
||||
void removeAction(final FeatureAction action) {
|
||||
assertRunOnServiceThread();
|
||||
mActions.remove(action);
|
||||
checkIfPendingActionsCleared();
|
||||
}
|
||||
|
||||
// Remove all actions matched with the given Class type.
|
||||
@@ -383,8 +461,14 @@ abstract class HdmiCecLocalDevice {
|
||||
mActions.remove(action);
|
||||
}
|
||||
}
|
||||
checkIfPendingActionsCleared();
|
||||
}
|
||||
|
||||
protected void checkIfPendingActionsCleared() {
|
||||
if (mActions.isEmpty()) {
|
||||
mService.onPendingActionsCleared();
|
||||
}
|
||||
}
|
||||
protected void assertRunOnServiceThread() {
|
||||
if (Looper.myLooper() != mService.getServiceLooper()) {
|
||||
throw new IllegalStateException("Should run on service thread.");
|
||||
@@ -488,4 +572,23 @@ abstract class HdmiCecLocalDevice {
|
||||
assertRunOnServiceThread();
|
||||
return mService.pathToPortId(newPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the system started transition to standby mode.
|
||||
*
|
||||
* @param initiatedByCec true if this power sequence is initiated
|
||||
* by the reception the CEC messages like <StandBy>
|
||||
*/
|
||||
protected void onTransitionToStandby(boolean initiatedByCec) {
|
||||
// If there are no outstanding actions, we'll go to STANDBY state.
|
||||
checkIfPendingActionsCleared();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the system goes to standby mode.
|
||||
*
|
||||
* @param initiatedByCec true if this power sequence is initiated
|
||||
* by the reception the CEC messages like <StandBy>
|
||||
*/
|
||||
protected void onStandBy(boolean initiatedByCec) {}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.android.server.hdmi;
|
||||
|
||||
import android.hardware.hdmi.HdmiCec;
|
||||
import android.hardware.hdmi.HdmiCecMessage;
|
||||
import android.hardware.hdmi.IHdmiControlCallback;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Slog;
|
||||
@@ -29,6 +30,8 @@ import com.android.server.hdmi.HdmiAnnotations.ServiceThreadOnly;
|
||||
final class HdmiCecLocalDevicePlayback extends HdmiCecLocalDevice {
|
||||
private static final String TAG = "HdmiCecLocalDevicePlayback";
|
||||
|
||||
private boolean mIsActiveSource = false;
|
||||
|
||||
HdmiCecLocalDevicePlayback(HdmiControlService service) {
|
||||
super(service, HdmiCec.DEVICE_PLAYBACK);
|
||||
}
|
||||
@@ -93,7 +96,57 @@ final class HdmiCecLocalDevicePlayback extends HdmiCecLocalDevice {
|
||||
@ServiceThreadOnly
|
||||
void onHotplug(int portId, boolean connected) {
|
||||
assertRunOnServiceThread();
|
||||
// TODO: clear devices connected to the given port id.
|
||||
mCecMessageCache.flushAll();
|
||||
mIsActiveSource = false;
|
||||
if (connected && mService.isPowerStandbyOrTransient()) {
|
||||
mService.wakeUp();
|
||||
}
|
||||
}
|
||||
|
||||
@ServiceThreadOnly
|
||||
void markActiveSource() {
|
||||
assertRunOnServiceThread();
|
||||
mIsActiveSource = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ServiceThreadOnly
|
||||
protected boolean handleActiveSource(HdmiCecMessage message) {
|
||||
assertRunOnServiceThread();
|
||||
int physicalAddress = HdmiUtils.twoBytesToInt(message.getParams());
|
||||
if (physicalAddress != mService.getPhysicalAddress()) {
|
||||
mIsActiveSource = false;
|
||||
if (mService.isPowerOnOrTransient()) {
|
||||
mService.standby();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ServiceThreadOnly
|
||||
protected boolean handleSetStreamPath(HdmiCecMessage message) {
|
||||
assertRunOnServiceThread();
|
||||
int physicalAddress = HdmiUtils.twoBytesToInt(message.getParams());
|
||||
if (physicalAddress == mService.getPhysicalAddress()) {
|
||||
if (mService.isPowerStandbyOrTransient()) {
|
||||
mService.wakeUp();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ServiceThreadOnly
|
||||
protected void onTransitionToStandby(boolean initiatedByCec) {
|
||||
assertRunOnServiceThread();
|
||||
if (!initiatedByCec && mIsActiveSource) {
|
||||
mService.sendCecCommand(HdmiCecMessageBuilder.buildInactiveSource(
|
||||
mAddress, mService.getPhysicalAddress()));
|
||||
}
|
||||
mIsActiveSource = false;
|
||||
checkIfPendingActionsCleared();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -441,6 +441,26 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ServiceThreadOnly
|
||||
protected boolean handleTextViewOn(HdmiCecMessage message) {
|
||||
assertRunOnServiceThread();
|
||||
if (mService.isPowerStandbyOrTransient()) {
|
||||
mService.wakeUp();
|
||||
}
|
||||
// TODO: Connect to Hardware input manager to invoke TV App with the appropriate channel
|
||||
// that represents the source device.
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ServiceThreadOnly
|
||||
protected boolean handleImageViewOn(HdmiCecMessage message) {
|
||||
assertRunOnServiceThread();
|
||||
// Currently, it's the same as <Text View On>.
|
||||
return handleTextViewOn(message);
|
||||
}
|
||||
|
||||
@ServiceThreadOnly
|
||||
private void launchDeviceDiscovery() {
|
||||
assertRunOnServiceThread();
|
||||
@@ -985,4 +1005,42 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
|
||||
assertRunOnServiceThread();
|
||||
mAutoDeviceOff = enabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ServiceThreadOnly
|
||||
protected void onTransitionToStandby(boolean initiatedByCec) {
|
||||
assertRunOnServiceThread();
|
||||
// Remove any repeated working actions.
|
||||
// HotplugDetectionAction will be reinstated during the wake up process.
|
||||
// HdmiControlService.onWakeUp() -> initializeLocalDevices() ->
|
||||
// LocalDeviceTv.onAddressAllocated() -> launchDeviceDiscovery().
|
||||
removeAction(HotplugDetectionAction.class);
|
||||
checkIfPendingActionsCleared();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ServiceThreadOnly
|
||||
protected void onStandBy(boolean initiatedByCec) {
|
||||
assertRunOnServiceThread();
|
||||
// Seq #11
|
||||
if (!mService.isControlEnabled()) {
|
||||
return;
|
||||
}
|
||||
if (!initiatedByCec) {
|
||||
mService.sendCecCommand(HdmiCecMessageBuilder.buildStandby(
|
||||
mAddress, HdmiCec.ADDR_BROADCAST));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ServiceThreadOnly
|
||||
protected boolean handleStandby(HdmiCecMessage message) {
|
||||
assertRunOnServiceThread();
|
||||
// Seq #12
|
||||
// Tv accepts directly addressed <Standby> only.
|
||||
if (message.getDestination() == mAddress) {
|
||||
super.handleStandby(message);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -269,6 +269,18 @@ public class HdmiCecMessageBuilder {
|
||||
physicalAddressToParam(physicalAddress));
|
||||
}
|
||||
|
||||
/**
|
||||
* Build <Inactive Source> command.
|
||||
*
|
||||
* @param src source address of command
|
||||
* @param physicalAddress physical address of the device to become inactive
|
||||
* @return newly created {@link HdmiCecMessage}
|
||||
*/
|
||||
static HdmiCecMessage buildInactiveSource(int src, int physicalAddress) {
|
||||
return buildCommand(src, HdmiCec.ADDR_BROADCAST, HdmiCec.MESSAGE_INACTIVE_SOURCE,
|
||||
physicalAddressToParam(physicalAddress));
|
||||
}
|
||||
|
||||
/**
|
||||
* Build <Set Stream Path> command.
|
||||
*
|
||||
@@ -312,6 +324,21 @@ public class HdmiCecMessageBuilder {
|
||||
return buildCommand(src, dest, HdmiCec.MESSAGE_GIVE_DEVICE_POWER_STATUS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build <Report Power Status> command.
|
||||
*
|
||||
* @param src source address of command
|
||||
* @param dest destination address of command
|
||||
* @param powerStatus power status of the device
|
||||
* @return newly created {@link HdmiCecMessage}
|
||||
*/
|
||||
static HdmiCecMessage buildReportPowerStatus(int src, int dest, int powerStatus) {
|
||||
byte[] param = new byte[] {
|
||||
(byte) (powerStatus)
|
||||
};
|
||||
return buildCommand(src, dest, HdmiCec.MESSAGE_REPORT_POWER_STATUS, param);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build <System Audio Mode Request> command.
|
||||
*
|
||||
@@ -388,6 +415,17 @@ public class HdmiCecMessageBuilder {
|
||||
return buildCommand(src, dest, HdmiCec.MESSAGE_GIVE_SYSTEM_AUDIO_MODE_STATUS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build <Standby> command.
|
||||
*
|
||||
* @param src source address of command
|
||||
* @param dest destination address of command
|
||||
* @return newly created {@link HdmiCecMessage}
|
||||
*/
|
||||
public static HdmiCecMessage buildStandby(int src, int dest) {
|
||||
return buildCommand(src, dest, HdmiCec.MESSAGE_STANDBY);
|
||||
}
|
||||
|
||||
/***** Please ADD new buildXXX() methods above. ******/
|
||||
|
||||
/**
|
||||
|
||||
@@ -45,6 +45,8 @@ final class HdmiConstants {
|
||||
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.
|
||||
|
||||
@@ -17,7 +17,10 @@
|
||||
package com.android.server.hdmi;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.hardware.hdmi.HdmiCec;
|
||||
import android.hardware.hdmi.HdmiCecDeviceInfo;
|
||||
import android.hardware.hdmi.HdmiCecMessage;
|
||||
@@ -34,8 +37,9 @@ import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.os.IBinder;
|
||||
import android.os.Looper;
|
||||
import android.os.PowerManager;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
import android.os.SystemClock;
|
||||
import android.util.Slog;
|
||||
import android.util.SparseArray;
|
||||
import android.util.SparseIntArray;
|
||||
@@ -86,6 +90,24 @@ public final class HdmiControlService extends SystemService {
|
||||
void onPollingFinished(List<Integer> ackedAddress);
|
||||
}
|
||||
|
||||
private class PowerStateReceiver extends BroadcastReceiver {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
switch (intent.getAction()) {
|
||||
case Intent.ACTION_SCREEN_OFF:
|
||||
if (isPowerOnOrTransient()) {
|
||||
onStandby();
|
||||
}
|
||||
break;
|
||||
case Intent.ACTION_SCREEN_ON:
|
||||
if (isPowerStandbyOrTransient()) {
|
||||
onWakeUp();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// A thread to handle synchronous IO of CEC and MHL control service.
|
||||
// Since all of CEC and MHL HAL interfaces processed in short time (< 200ms)
|
||||
// and sparse call it shares a thread to handle IO operations.
|
||||
@@ -143,6 +165,14 @@ public final class HdmiControlService extends SystemService {
|
||||
// from being modified.
|
||||
private List<HdmiPortInfo> mPortInfo;
|
||||
|
||||
private final PowerStateReceiver mPowerStateReceiver = new PowerStateReceiver();
|
||||
|
||||
@ServiceThreadOnly
|
||||
private int mPowerStatus = HdmiCec.POWER_STATUS_STANDBY;
|
||||
|
||||
@ServiceThreadOnly
|
||||
private boolean mStandbyMessageReceived = false;
|
||||
|
||||
public HdmiControlService(Context context) {
|
||||
super(context);
|
||||
mLocalDevices = HdmiUtils.asImmutableList(getContext().getResources().getIntArray(
|
||||
@@ -152,9 +182,11 @@ public final class HdmiControlService extends SystemService {
|
||||
@Override
|
||||
public void onStart() {
|
||||
mIoThread.start();
|
||||
mPowerStatus = HdmiCec.POWER_STATUS_TRANSIENT_TO_ON;
|
||||
mCecController = HdmiCecController.create(this);
|
||||
|
||||
if (mCecController != null) {
|
||||
mCecController.setOption(HdmiCec.OPTION_CEC_SERVICE_CONTROL, HdmiCec.DISABLED);
|
||||
initializeLocalDevices(mLocalDevices);
|
||||
} else {
|
||||
Slog.i(TAG, "Device does not support HDMI-CEC.");
|
||||
@@ -167,6 +199,14 @@ public final class HdmiControlService extends SystemService {
|
||||
mPortInfo = initPortInfo();
|
||||
publishBinderService(Context.HDMI_CONTROL_SERVICE, new BinderService());
|
||||
|
||||
// Register broadcast receiver for power state change.
|
||||
if (mCecController != null || mMhlController != null) {
|
||||
IntentFilter filter = new IntentFilter();
|
||||
filter.addAction(Intent.ACTION_SCREEN_OFF);
|
||||
filter.addAction(Intent.ACTION_SCREEN_ON);
|
||||
getContext().registerReceiver(mPowerStateReceiver, filter);
|
||||
}
|
||||
|
||||
// TODO: Read the preference for SystemAudioMode and initialize mSystemAudioMode and
|
||||
// start to monitor the preference value and invoke SystemAudioActionFromTv if needed.
|
||||
mHdmiControlEnabled = true;
|
||||
@@ -199,6 +239,9 @@ public final class HdmiControlService extends SystemService {
|
||||
|
||||
// Address allocation completed for all devices. Notify each device.
|
||||
if (deviceTypes.size() == finished.size()) {
|
||||
if (mPowerStatus == HdmiCec.POWER_STATUS_TRANSIENT_TO_ON) {
|
||||
mPowerStatus = HdmiCec.POWER_STATUS_ON;
|
||||
}
|
||||
notifyAddressAllocated(devices);
|
||||
}
|
||||
}
|
||||
@@ -531,7 +574,7 @@ public final class HdmiControlService extends SystemService {
|
||||
}
|
||||
|
||||
private final class SystemAudioModeChangeListenerRecord implements IBinder.DeathRecipient {
|
||||
private IHdmiSystemAudioModeChangeListener mListener;
|
||||
private final IHdmiSystemAudioModeChangeListener mListener;
|
||||
|
||||
public SystemAudioModeChangeListenerRecord(IHdmiSystemAudioModeChangeListener listener) {
|
||||
mListener = listener;
|
||||
@@ -795,7 +838,7 @@ public final class HdmiControlService extends SystemService {
|
||||
public void run() {
|
||||
HdmiCecLocalDeviceTv tv = tv();
|
||||
if (tv == null) {
|
||||
Log.w(TAG, "Local tv device not available to change arc mode.");
|
||||
Slog.w(TAG, "Local tv device not available to change arc mode.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -992,4 +1035,82 @@ public final class HdmiControlService extends SystemService {
|
||||
return mHdmiControlEnabled;
|
||||
}
|
||||
}
|
||||
|
||||
int getPowerStatus() {
|
||||
return mPowerStatus;
|
||||
}
|
||||
|
||||
boolean isPowerOnOrTransient() {
|
||||
return mPowerStatus == HdmiCec.POWER_STATUS_ON
|
||||
|| mPowerStatus == HdmiCec.POWER_STATUS_TRANSIENT_TO_ON;
|
||||
}
|
||||
|
||||
boolean isPowerStandbyOrTransient() {
|
||||
return mPowerStatus == HdmiCec.POWER_STATUS_STANDBY
|
||||
|| mPowerStatus == HdmiCec.POWER_STATUS_TRANSIENT_TO_STANDBY;
|
||||
}
|
||||
|
||||
boolean isPowerStandby() {
|
||||
return mPowerStatus == HdmiCec.POWER_STATUS_STANDBY;
|
||||
}
|
||||
|
||||
@ServiceThreadOnly
|
||||
void wakeUp() {
|
||||
assertRunOnServiceThread();
|
||||
PowerManager pm = (PowerManager) getContext().getSystemService(Context.POWER_SERVICE);
|
||||
pm.wakeUp(SystemClock.uptimeMillis());
|
||||
// PowerManger will send the broadcast Intent.ACTION_SCREEN_ON and after this gets
|
||||
// the intent, the sequence will continue at onWakeUp().
|
||||
}
|
||||
|
||||
@ServiceThreadOnly
|
||||
void standby() {
|
||||
assertRunOnServiceThread();
|
||||
mStandbyMessageReceived = true;
|
||||
PowerManager pm = (PowerManager) getContext().getSystemService(Context.POWER_SERVICE);
|
||||
pm.goToSleep(SystemClock.uptimeMillis());
|
||||
// PowerManger will send the broadcast Intent.ACTION_SCREEN_OFF and after this gets
|
||||
// the intent, the sequence will continue at onStandby().
|
||||
}
|
||||
|
||||
@ServiceThreadOnly
|
||||
private void onWakeUp() {
|
||||
assertRunOnServiceThread();
|
||||
mPowerStatus = HdmiCec.POWER_STATUS_TRANSIENT_TO_ON;
|
||||
if (mCecController != null) {
|
||||
mCecController.setOption(HdmiCec.OPTION_CEC_SERVICE_CONTROL, HdmiCec.ENABLED);
|
||||
initializeLocalDevices(mLocalDevices);
|
||||
} else {
|
||||
Slog.i(TAG, "Device does not support HDMI-CEC.");
|
||||
}
|
||||
// TODO: Initialize MHL local devices.
|
||||
}
|
||||
|
||||
@ServiceThreadOnly
|
||||
private void onStandby() {
|
||||
assertRunOnServiceThread();
|
||||
mPowerStatus = HdmiCec.POWER_STATUS_TRANSIENT_TO_STANDBY;
|
||||
for (HdmiCecLocalDevice device : mCecController.getLocalDeviceList()) {
|
||||
device.onTransitionToStandby(mStandbyMessageReceived);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when there are the outstanding actions in the local devices.
|
||||
* This callback is used to wait for when the action queue is empty
|
||||
* during the power state transition to standby.
|
||||
*/
|
||||
@ServiceThreadOnly
|
||||
void onPendingActionsCleared() {
|
||||
assertRunOnServiceThread();
|
||||
if (mPowerStatus != HdmiCec.POWER_STATUS_TRANSIENT_TO_STANDBY) {
|
||||
return;
|
||||
}
|
||||
mPowerStatus = HdmiCec.POWER_STATUS_STANDBY;
|
||||
for (HdmiCecLocalDevice device : mCecController.getLocalDeviceList()) {
|
||||
device.onStandBy(mStandbyMessageReceived);
|
||||
}
|
||||
mStandbyMessageReceived = false;
|
||||
mCecController.setOption(HdmiCec.OPTION_CEC_SERVICE_CONTROL, HdmiCec.DISABLED);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,9 +15,10 @@
|
||||
*/
|
||||
package com.android.server.hdmi;
|
||||
|
||||
import android.hardware.hdmi.IHdmiControlCallback;
|
||||
import android.hardware.hdmi.HdmiCec;
|
||||
import android.hardware.hdmi.HdmiCecMessage;
|
||||
import android.hardware.hdmi.HdmiControlManager;
|
||||
import android.hardware.hdmi.IHdmiControlCallback;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Slog;
|
||||
|
||||
@@ -54,7 +55,7 @@ final class OneTouchPlayAction extends FeatureAction {
|
||||
private int mPowerStatusCounter = 0;
|
||||
|
||||
// Factory method. Ensures arguments are valid.
|
||||
static OneTouchPlayAction create(HdmiCecLocalDevice source,
|
||||
static OneTouchPlayAction create(HdmiCecLocalDevicePlayback source,
|
||||
int targetAddress, IHdmiControlCallback callback) {
|
||||
if (source == null || callback == null) {
|
||||
Slog.e(TAG, "Wrong arguments");
|
||||
@@ -83,6 +84,8 @@ final class OneTouchPlayAction extends FeatureAction {
|
||||
|
||||
private void broadcastActiveSource() {
|
||||
sendCommand(HdmiCecMessageBuilder.buildActiveSource(getSourceAddress(), getSourcePath()));
|
||||
// Because only playback device can create this action, it's safe to cast.
|
||||
playback().markActiveSource();
|
||||
}
|
||||
|
||||
private void queryDevicePowerStatus() {
|
||||
|
||||
Reference in New Issue
Block a user