Android Tv HDMI-CEC框架层移植
2017-06-17 14:13
549 查看
本文介绍Android 5.1和Android6.0平台下,框架层实现盒子与支持CEC的电视控制和交互逻辑:
(1)盒子待机,控制电视待机
(2)电视待机,控制盒子待机
(3)盒子唤醒,控制电视唤醒
(4)获取盒子,电视的电源状态
其中(2)Android框架层已经实现
关于HDMI-CEC的介绍,请移步https://source.android.com/devices/tv/hdmi-cec
HDMI-CEC框架层控制部分别在两个部分:
frameworks/base/core/java/android/hardware/hdmi
frameworks/base/services/core/java/com/android/server/hdmi
1.修改盒子名称在电视显示的名字
2.在HdmiControlManager.java添加广播动作,主要用于发送广播获取电视,盒子的待机状态,第三方应用可以通过接受广播获取盒子和电视的待机状态
3.IHdmiControlService.aidl添加发送CEC命令,获取电视或盒子的逻辑地址,获取盒子电源状态等接口,这些接口在service端的HdmiControlService.java文件实现,第三方应用可以通过Binder机制去发送CEC控制命令,获取盒子电源状态等
4.在HdmiCecLocalDevice.java广播电视的待机状态,激活盒子作为输入源,控制盒子待机
5.HdmiControlService.java实现IHdmiControlService.aidl添加的三个接口方法,监听HDMI的插拔事件,激活输入源,实现控制电视待机,唤醒的方法
6.PowerManagerService.java在盒子待机的时候,也让电视待机
至此,HDMI-CEC基本的功能(待机,唤醒,获取电源状态)已经实现。
觉得文章对您有益,打赏一下?
(1)盒子待机,控制电视待机
(2)电视待机,控制盒子待机
(3)盒子唤醒,控制电视唤醒
(4)获取盒子,电视的电源状态
其中(2)Android框架层已经实现
关于HDMI-CEC的介绍,请移步https://source.android.com/devices/tv/hdmi-cec
HDMI-CEC框架层控制部分别在两个部分:
frameworks/base/core/java/android/hardware/hdmi
frameworks/base/services/core/java/com/android/server/hdmi
1.修改盒子名称在电视显示的名字
diff --git a/core/java/android/hardware/hdmi/HdmiDeviceInfo.java b/core/java/android/hardware/hdmi/HdmiDeviceInfo.java index 48ea9a6..a921ebb 100644 --- a/core/java/android/hardware/hdmi/HdmiDeviceInfo.java +++ b/core/java/android/hardware/hdmi/HdmiDeviceInfo.java @@ -19,6 +19,7 @@ package android.hardware.hdmi; import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; +import android.os.SystemProperties; /** * A class to encapsulate device information for HDMI devices including CEC and MHL. In terms of @@ -407,7 +408,10 @@ public class HdmiDeviceInfo implements Parcelable { * Returns display (OSD) name of the device. */ public String getDisplayName() { - return mDisplayName; + + mDisplayName = SystemProperties.get("persist.sys.exdevicename", "box"); + return mDisplayName; }
2.在HdmiControlManager.java添加广播动作,主要用于发送广播获取电视,盒子的待机状态,第三方应用可以通过接受广播获取盒子和电视的待机状态
diff --git a/core/java/android/hardware/hdmi/HdmiControlManager.java b/core/java/android/hardware/hdmi/HdmiControlManager.java old mode 100644 new mode 100755 index 308a219..4043e2e --- a/core/java/android/hardware/hdmi/HdmiControlManager.java +++ b/core/java/android/hardware/hdmi/HdmiControlManager.java @@ -254,6 +254,16 @@ public final class HdmiControlManager { // True if we have a logical device of type TV hosted in the system. private final boolean mHasTvDevice; + //Broadcast action for power status changed + public static final String POWER_STATUS_CHANGED = "com.rockchip.hdmicec.power_status_changed"; + //The key for box power status + public static final String HDMI_CEC_POWER_STATUS = "hdmi_cec_power_status"; + //The key for hdmi cec device type + public static final String HDMI_CEC_DEVICE_TYPE = "hdmi_cec_device_type"; + //box type + public static final int TYPE_HDMI_CEC_BOX = 0; + //tv type + public static final int TYPE_HDMI_CEC_TV= 1;
3.IHdmiControlService.aidl添加发送CEC命令,获取电视或盒子的逻辑地址,获取盒子电源状态等接口,这些接口在service端的HdmiControlService.java文件实现,第三方应用可以通过Binder机制去发送CEC控制命令,获取盒子电源状态等
diff --git a/core/java/android/hardware/hdmi/IHdmiControlService.aidl b/core/java/android/hardware/hdmi/IHdmiControlService.aidl old mode 100644 new mode 100755 index c1e924e..62dea8a --- a/core/java/android/hardware/hdmi/IHdmiControlService.aidl +++ b/core/java/android/hardware/hdmi/IHdmiControlService.aidl @@ -71,4 +71,10 @@ interface IHdmiControlService { void clearTimerRecording(int recorderAddress, int sourceType, in byte[] recordSource); void sendMhlVendorCommand(int portId, int offset, int length, in byte[] data); void addHdmiMhlVendorCommandListener(IHdmiMhlVendorCommandListener listener); + //send cec command + void sendControlCommand(int src, int targetAddress, int opCode, in byte[] params); + //get local address for specific type + int getLocalAddress(int type); + //get power status + int getPowerStatus(); }
4.在HdmiCecLocalDevice.java广播电视的待机状态,激活盒子作为输入源,控制盒子待机
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java old mode 100644 new mode 100755 index 7999321..e66d0d1 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java @@ -22,7 +22,9 @@ import android.os.Handler; import android.os.Looper; import android.os.Message; import android.os.SystemClock; +import android.os.SystemProperties; import android.util.Slog; +import android.util.Log; import android.view.InputDevice; import android.view.KeyCharacterMap; import android.view.KeyEvent; @@ -35,7 +37,8 @@ import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; - +import android.util.Log; +import android.hardware.hdmi.HdmiControlManager; /** * Class that models a logical CEC device hosted in this system. Handles initialization, * CEC commands that call for actions customized per device type. @@ -222,10 +225,12 @@ abstract class HdmiCecLocalDevice { @ServiceThreadOnly boolean dispatchMessage(HdmiCecMessage message) { assertRunOnServiceThread(); + Log.i(TAG, "dispatchMessage->message:" + message); int dest = message.getDestination(); if (dest != mAddress && dest != Constants.ADDR_BROADCAST) { return false; } + // Cache incoming message. Note that it caches only white-listed one. mCecMessageCache.cacheMessage(message); return onMessage(message); @@ -234,7 +239,11 @@ abstract class HdmiCecLocalDevice { @ServiceThreadOnly protected final boolean onMessage(HdmiCecMessage message) { assertRunOnServiceThread(); + if(message.getOpcode() == Constants.MESSAGE_REPORT_POWER_STATUS && message.getSource() == 0){ + mService.sendPowerStatusChanged(HdmiControlManager.TYPE_HDMI_CEC_TV, (int)(message.getParams()[0])); + } if (dispatchMessageToAction(message)) { + Log.i(TAG, "onMessage->dispatchMessageToAction->message:" + message); return true; } switch (message.getOpcode()) { @@ -314,6 +323,7 @@ abstract class HdmiCecLocalDevice { @ServiceThreadOnly private boolean dispatchMessageToAction(HdmiCecMessage message) { assertRunOnServiceThread(); + Log.i(TAG, "dispatchMessageToAction->message:" + message); boolean processed = false; // Use copied action list in that processCommand may remove itself. for (HdmiCecFeatureAction action : new ArrayList<>(mActions)) { @@ -367,7 +377,20 @@ abstract class HdmiCecLocalDevice { @ServiceThreadOnly protected boolean handleRequestActiveSource(HdmiCecMessage message) { - return false; + assertRunOnServiceThread(); + // Note that since this method is called after physical address allocation is done, + // mDeviceInfo should not be null. + HdmiCecMessage cecMessage = HdmiCecMessageBuilder.buildActiveSource( + mAddress, mDeviceInfo.getPhysicalAddress()); + if (cecMessage != null) { + Log.i(TAG, "handleRequestActiveSource->cecMessage:" + message); + mService.sendCecCommand(cecMessage); + } else { + Log.i(TAG, "Failed to build <Request Active Source>:" + mDeviceInfo.getPhysicalAddress()); + //Slog.w(TAG, "Failed to build <Request Active Source>:" + mDeviceInfo.getPhysicalAddress()); + } + return true; + }
5.HdmiControlService.java实现IHdmiControlService.aidl添加的三个接口方法,监听HDMI的插拔事件,激活输入源,实现控制电视待机,唤醒的方法
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java old mode 100644 new mode 100755 index cfc5f7d..23a9698 --- a/services/core/java/com/android/server/hdmi/HdmiControlService.java +++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java @@ -28,7 +28,7 @@ import static com.android.server.hdmi.Constants.OPTION_MHL_ENABLE; import static com.android.server.hdmi.Constants.OPTION_MHL_INPUT_SWITCHING; import static com.android.server.hdmi.Constants.OPTION_MHL_POWER_CHARGE; import static com.android.server.hdmi.Constants.OPTION_MHL_SERVICE_CONTROL; import android.annotation.Nullable; import android.content.BroadcastReceiver; import android.content.ContentResolver; @@ -49,6 +49,8 @@ import android.hardware.hdmi.IHdmiMhlVendorCommandListener; import android.hardware.hdmi.IHdmiRecordListener; import android.hardware.hdmi.IHdmiSystemAudioModeChangeListener; import android.hardware.hdmi.IHdmiVendorCommandListener; +import android.hardware.hdmi.HdmiPlaybackClient.OneTouchPlayCallback; +import android.hardware.hdmi.HdmiPlaybackClient; import android.media.AudioManager; import android.media.tv.TvInputManager; import android.media.tv.TvInputManager.TvInputCallback; @@ -69,7 +71,7 @@ import android.util.ArraySet; import android.util.Slog; import android.util.SparseArray; import android.util.SparseIntArray; +import android.hardware.display.DisplayManager; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.IndentingPrintWriter; import com.android.server.SystemService; @@ -77,9 +79,8 @@ import com.android.server.hdmi.HdmiAnnotations.ServiceThreadOnly; import com.android.server.hdmi.HdmiCecController.AllocateAddressCallback; import com.android.server.hdmi.HdmiCecLocalDevice.ActiveSource; import com.android.server.hdmi.HdmiCecLocalDevice.PendingActionClearedCallback; +import android.view.Display; import libcore.util.EmptyArray; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; @@ -87,7 +88,14 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Locale; +import android.util.Log; +import android.view.KeyEvent; +import android.view.InputEvent; +import android.view.InputChannel; +import android.view.InputDevice; +import android.hardware.input.InputManager; +import android.hardware.input.InputManager.InputDeviceListener; /** * Provides a service for sending and processing HDMI control messages, * HDMI-CEC and MHL control command, and providing the information on both standard. @@ -146,15 +154,21 @@ public final class HdmiControlService extends SystemService { @Override public void onReceive(Context context, Intent intent) { assertRunOnServiceThread(); switch (intent.getAction()) { case Intent.ACTION_SCREEN_OFF: if (isPowerOnOrTransient()) { onStandby(STANDBY_SCREEN_OFF); } break; case Intent.ACTION_SCREEN_ON: if (isPowerStandbyOrTransient()) { onWakeUp(); + touchTv(); } break; case Intent.ACTION_CONFIGURATION_CHANGED: @@ -292,7 +306,14 @@ public final class HdmiControlService extends SystemService { @Nullable private PowerManager mPowerManager; - + + private DisplayManager mDisplayManager; + + private HDMIListener mHdmiListener = new HDMIListener(); + + private InputManager mInputManager; + // 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. @@ -422,10 +451,25 @@ public final class HdmiControlService extends SystemService { registerContentObserver(); } mMhlController.setOption(OPTION_MHL_SERVICE_CONTROL, ENABLED); + + mDisplayManager = (DisplayManager) getContext().getSystemService(Context.DISPLAY_SERVICE); + + if(mDisplayManager != null){ + mDisplayManager.registerDisplayListener(mHdmiListener, null); + } + } @@ -455,8 +503,10 @@ public final class HdmiControlService extends SystemService { * Called when the initialization of local devices is complete. */ private void onInitializeCecComplete(int initiatedBy) { + Log.i(TAG, "HdmiControlService8"); if (mPowerStatus == HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON) { mPowerStatus = HdmiControlManager.POWER_STATUS_ON; + sendPowerStatusChanged(HdmiControlManager.TYPE_HDMI_CEC_BOX, mPowerStatus); } mWakeUpMessageReceived = false; @@ -814,12 +890,15 @@ public final class HdmiControlService extends SystemService { * @param command CEC command to send out * @param callback interface used to the result of send command */ - @ServiceThreadOnly + //@ServiceThreadOnly void sendCecCommand(HdmiCecMessage command, @Nullable SendMessageCallback callback) { - assertRunOnServiceThread(); + //assertRunOnServiceThread(); + Log.i(TAG, "sendCecCommand->HdmiControlService35"); if (mMessageValidator.isValid(command) == HdmiCecMessageValidator.OK) { + Log.i(TAG, "sendCecCommand->valid message type"); mCecController.sendCommand(command, callback); } else { + Log.i(TAG, "sendCecCommand->Invalid message type:" + command); HdmiLogger.error("Invalid message type:" + command); if (callback != null) { callback.onSendCompleted(Constants.SEND_RESULT_FAILURE); @@ -827,9 +906,10 @@ public final class HdmiControlService extends SystemService { } } - @ServiceThreadOnly + //@ServiceThreadOnly void sendCecCommand(HdmiCecMessage command) { - assertRunOnServiceThread(); + //assertRunOnServiceThread(); + Log.i(TAG, "HdmiControlService36"); sendCecCommand(command, null); } @@ -842,13 +922,17 @@ public final class HdmiControlService extends SystemService { @ServiceThreadOnly void maySendFeatureAbortCommand(HdmiCecMessage command, int reason) { assertRunOnServiceThread(); + Log.i(TAG, "HdmiControlService37"); mCecController.maySendFeatureAbortCommand(command, reason); } @ServiceThreadOnly boolean handleCecCommand(HdmiCecMessage message) { assertRunOnServiceThread(); + Log.i(TAG, "HdmiControlService38"); + Log.i(TAG, "handleCecCommand:" + message); if (!mAddressAllocated) { + Log.i(TAG, "handleCecCommand->mAddressAllocated is not allocate"); mCecMessageBuffer.bufferMessage(message); return true; } @@ -1656,11 +1756,31 @@ public final class HdmiControlService extends SystemService { pw.decreaseIndent(); pw.println("mPowerStatus: " + mPowerStatus); } + + @Override + public void sendControlCommand(int src, int targetAddress, int opCode, byte[] params){ + HdmiCecMessage cecMessage = new HdmiCecMessage(src, targetAddress, opCode, params); + sendCecCommand(cecMessage); + } + + @Override + public int getLocalAddress(int type){ + HdmiCecLocalDevice device = mCecController.getLocalDevice(type); + if(device != null) + return device.getLogicAddress(); + return -1; + } + + @Override + public int getPowerStatus(){ + return HdmiControlService.this.getPowerStatus(); + } } @ServiceThreadOnly private void oneTouchPlay(final IHdmiControlCallback callback) { assertRunOnServiceThread(); + Log.i(TAG, "HdmiControlService54"); HdmiCecLocalDevicePlayback source = playback(); if (source == null) { Slog.w(TAG, "Local playback device not available"); @@ -1986,7 +2136,9 @@ public final class HdmiControlService extends SystemService { @ServiceThreadOnly private void onWakeUp() { assertRunOnServiceThread(); + Log.i(TAG, "HdmiControlService85"); mPowerStatus = HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON; + sendPowerStatusChanged(HdmiControlManager.TYPE_HDMI_CEC_BOX, mPowerStatus); if (mCecController != null) { if (mHdmiControlEnabled) { int startReason = INITIATED_BY_SCREEN_ON; @@ -2004,8 +2156,12 @@ public final class HdmiControlService extends SystemService { @ServiceThreadOnly private void onStandby(final int standbyAction) { assertRunOnServiceThread(); + Log.i(TAG, "HdmiControlService86"); + Log.i(TAG, "onStandby:" + 0); if (!canGoToStandby()) return; + Log.i(TAG, "onStandby:" + 1); mPowerStatus = HdmiControlManager.POWER_STATUS_TRANSIENT_TO_STANDBY; + sendPowerStatusChanged(HdmiControlManager.TYPE_HDMI_CEC_BOX, mPowerStatus); invokeVendorCommandListenersOnControlStateChanged(false, HdmiControlManager.CONTROL_STATE_CHANGED_REASON_STANDBY); @@ -2026,6 +2182,7 @@ public final class HdmiControlService extends SystemService { } private boolean canGoToStandby() { + Log.i(TAG, "HdmiControlService87"); for (HdmiCecLocalDevice device : mCecController.getLocalDeviceList()) { if (!device.canGoToStandby()) return false; } @@ -2035,6 +2192,7 @@ public final class HdmiControlService extends SystemService { @ServiceThreadOnly private void onLanguageChanged(String language) { assertRunOnServiceThread(); + Log.i(TAG, "HdmiControlService88"); mLanguage = language; if (isTvDeviceEnabled()) { @@ -2046,10 +2204,12 @@ public final class HdmiControlService extends SystemService { @ServiceThreadOnly String getLanguage() { assertRunOnServiceThread(); + Log.i(TAG, "HdmiControlService89"); return mLanguage; } private void disableDevices(PendingActionClearedCallback callback) { + Log.i(TAG, "HdmiControlService90"); if (mCecController != null) { for (HdmiCecLocalDevice device : mCecController.getLocalDeviceList()) { device.disableDevice(mStandbyMessageReceived, callback); @@ -2062,6 +2222,7 @@ public final class HdmiControlService extends SystemService { @ServiceThreadOnly private void clearLocalDevices() { assertRunOnServiceThread(); + Log.i(TAG, "HdmiControlService91"); if (mCecController == null) { return; } @@ -2072,12 +2233,14 @@ public final class HdmiControlService extends SystemService { @ServiceThreadOnly private void onStandbyCompleted(int standbyAction) { assertRunOnServiceThread(); + Log.i(TAG, "HdmiControlService92"); Slog.v(TAG, "onStandbyCompleted"); if (mPowerStatus != HdmiControlManager.POWER_STATUS_TRANSIENT_TO_STANDBY) { return; } mPowerStatus = HdmiControlManager.POWER_STATUS_STANDBY; + sendPowerStatusChanged(HdmiControlManager.TYPE_HDMI_CEC_BOX, mPowerStatus); for (HdmiCecLocalDevice device : mCecController.getLocalDeviceList()) { device.onStandby(mStandbyMessageReceived, standbyAction); } @@ -2317,10 +2496,136 @@ public final class HdmiControlService extends SystemService { @ServiceThreadOnly void displayOsd(int messageId, int extra) { assertRunOnServiceThread(); + Log.i(TAG, "HdmiControlService111"); Intent intent = new Intent(HdmiControlManager.ACTION_OSD_MESSAGE); intent.putExtra(HdmiControlManager.EXTRA_MESSAGE_ID, messageId); intent.putExtra(HdmiControlManager.EXTRA_MESSAGE_EXTRA_PARAM1, extra); getContext().sendBroadcastAsUser(intent, UserHandle.ALL, HdmiControlService.PERMISSION); } + + + public void standbyTv(){ + if(mCecController != null){ + HdmiCecLocalDevice playBackDevice = mCecController.getLocalDevice(HdmiDeviceInfo.DEVICE_PLAYBACK); + int playBackAddrss = playBackDevice.getLogicAddress(); + byte[] cecParam = new byte[0]; + final HdmiCecMessage cecMessage = new HdmiCecMessage(playBackAddrss, 0, 0x36, cecParam); + sendCecCommand(cecMessage, new SendMessageCallback(){ + public void onSendCompleted(int error){ + if(error == Constants.SEND_RESULT_SUCCESS){ + sendPowerStatusChanged(HdmiControlManager.TYPE_HDMI_CEC_TV, HdmiControlManager.POWER_STATUS_STANDBY); + Log.i(TAG, "standbyTv->sendCecCommand success"); + } + else + Log.i(TAG, "standbyTv->sendCecCommand failed"); + } + }); + } + } + + + public void touchTv(){ + Log.i(TAG, "touchTv-1"); + HdmiControlManager controlManager = (HdmiControlManager)getContext().getSystemService(Context.HDMI_CONTROL_SERVICE); + if(controlManager == null) + return; + Log.i(TAG, "touchTv-2"); + HdmiPlaybackClient playbackClient = controlManager.getPlaybackClient(); + if(playbackClient == null) + return; + Log.i(TAG, "touchTv-3"); + playbackClient.oneTouchPlay(new OneTouchPlayCallback() { + @Override + public void onComplete(int result) { + if (result != HdmiControlManager.RESULT_SUCCESS) { + Log.i(TAG, "One touch play failed: " + result); + } else { + Log.i(TAG, "One touch play succeed: " + result); + + } + } + }); + } + + public void sendActiveSource(){ + if(mCecController != null){ + HdmiCecLocalDevice playBackDevice = mCecController.getLocalDevice(HdmiDeviceInfo.DEVICE_PLAYBACK); + int playBackAddrss = playBackDevice.getLogicAddress(); + byte[] cecParam = new byte[0]; + HdmiCecMessage cecMessageToTv = new HdmiCecMessage(playBackAddrss, 0, 0x85, cecParam); + HdmiCecMessage cecMessageToPlayBack = new HdmiCecMessage(0, playBackAddrss, 0x85, cecParam); + sendCecCommand(cecMessageToTv, new SendMessageCallback(){ + public void onSendCompleted(int error){ + if(error == Constants.SEND_RESULT_SUCCESS) + Log.i(TAG, "sendActiveSource->sendCecCommand to tv success"); + else + Log.i(TAG, "sendActiveSource->sendCecCommand to tv failed"); + } + }); + + sendCecCommand(cecMessageToPlayBack, new SendMessageCallback(){ + public void onSendCompleted(int error){ + if(error == Constants.SEND_RESULT_SUCCESS) + Log.i(TAG, "sendActiveSource->sendCecCommand to playback success"); + else + Log.i(TAG, "sendActiveSource->sendCecCommand to playback failed"); + } + }); + } + + } + + public void sendPowerStatusChanged(int deviceType, int powerStatus){ + Log.i(TAG, "sendPowerStatusChanged"); + Intent intent = new Intent(HdmiControlManager.POWER_STATUS_CHANGED); + intent.putExtra(HdmiControlManager.HDMI_CEC_POWER_STATUS, powerStatus); + intent.putExtra(HdmiControlManager.HDMI_CEC_DEVICE_TYPE, deviceType); + intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); + getContext().sendBroadcast(intent); + } + + class HDMIListener implements DisplayManager.DisplayListener { + + @Override + public void onDisplayAdded(int displayId) { + Display display = mDisplayManager.getDisplay(displayId); + Log.i(TAG, "HDMI Add:" + display); + sendActiveSource(); + touchTv(); + } + + @Override + public void onDisplayRemoved(int displayId) { + Display display = mDisplayManager.getDisplay(displayId); + Log.i(TAG, "HDMI removed:" + display); + } + + @Override + public void onDisplayChanged(int displayId) { + + } + + } }
6.PowerManagerService.java在盒子待机的时候,也让电视待机
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java index 9a20aa2..d5bf708 100755 --- a/services/core/java/com/android/server/power/PowerManagerService.java +++ b/services/core/java/com/android/server/power/PowerManagerService.java @@ -89,6 +89,9 @@ import static android.os.PowerManagerInternal.WAKEFULNESS_ASLEEP; import static android.os.PowerManagerInternal.WAKEFULNESS_AWAKE; import static android.os.PowerManagerInternal.WAKEFULNESS_DREAMING; import static android.os.PowerManagerInternal.WAKEFULNESS_DOZING; +//FOR CEC +import android.hardware.hdmi.*; +import android.os.ServiceManager; /** * The power manager service is responsible for coordinating power management @@ -1166,6 +1169,17 @@ public final class PowerManagerService extends SystemService } Trace.traceBegin(Trace.TRACE_TAG_POWER, "goToSleep"); + //FOR CEC standbyTv + IBinder playBinder = ServiceManager.getService(Context.HDMI_CONTROL_SERVICE); + IHdmiControlService mControlService = IHdmiControlService.Stub.asInterface(playBinder); + try { + Slog.i(TAG, "send cec standby command to TV"); + mControlService.sendControlCommand(mControlService.getLocalAddress(HdmiDeviceInfo.DEVICE_PLAYBACK), 0 , 0x36, new byte[]{}); + } catch (Exception e) { + Slog.i(TAG, "发送待机指令出错" + e); + } + + try { switch (reason) { case PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN:
至此,HDMI-CEC基本的功能(待机,唤醒,获取电源状态)已经实现。
觉得文章对您有益,打赏一下?
相关文章推荐
- Android Tv HDMI-CEC框架层移植
- HDMI-CEC Control Service (Android TV 二)
- VLC android 3.0解码器使用及移植TV项目调研
- Android HDMI CEC控制服务
- 将Android移植到FS2410开发板上
- 移植google操作系统android的5个步骤之(一)
- s3c2410/2440(armv4t) 移植android
- Android已经移植到PC上了。下一代PC操作系统!
- lumaQQ移植到Android之消息篇
- 平安夜,移植LWC到Android成功!
- 基于Windows手机的android移植可行性分析
- Android移植之文件系统总结
- Android成功移植到手机上了
- 移植android系统到mini2440
- 牛蹄印章 阿牛是个好青年/内核移植,android
- 启动Android系统移植计划
- 将Android移植到FS2410开发板上
- lumaQQ移植到Android之重构篇
- Android移植到VirtualBox及详细流程
- 基于Windows手机的android移植可行性分析收藏