本文介绍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.修改盒子名称在电视显示的名字

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 {@ServiceThreadOnlyboolean 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 {@ServiceThreadOnlyprotected 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 {@ServiceThreadOnlyprivate 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 {@ServiceThreadOnlyprotected 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 {@Overridepublic 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 {@Nullableprivate 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
+    //@ServiceThreadOnlyvoid 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
+    //@ServiceThreadOnlyvoid sendCecCommand(HdmiCecMessage command) {
-        assertRunOnServiceThread();
+        //assertRunOnServiceThread();
+      Log.i(TAG, "HdmiControlService36");sendCecCommand(command, null);}@@ -842,13 +922,17 @@ public final class HdmiControlService extends SystemService {@ServiceThreadOnlyvoid maySendFeatureAbortCommand(HdmiCecMessage command, int reason) {assertRunOnServiceThread();
+      Log.i(TAG, "HdmiControlService37");mCecController.maySendFeatureAbortCommand(command, reason);}@ServiceThreadOnlyboolean 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();
+      }}@ServiceThreadOnlyprivate 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 {@ServiceThreadOnlyprivate 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 {@ServiceThreadOnlyprivate 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 {@ServiceThreadOnlyprivate void onLanguageChanged(String language) {assertRunOnServiceThread();
+      Log.i(TAG, "HdmiControlService88");mLanguage = language;if (isTvDeviceEnabled()) {
@@ -2046,10 +2204,12 @@ public final class HdmiControlService extends SystemService {@ServiceThreadOnlyString 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 {@ServiceThreadOnlyprivate void clearLocalDevices() {assertRunOnServiceThread();
+      Log.i(TAG, "HdmiControlService91");if (mCecController == null) {return;}
@@ -2072,12 +2233,14 @@ public final class HdmiControlService extends SystemService {@ServiceThreadOnlyprivate 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 {@ServiceThreadOnlyvoid 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框架层移植相关推荐

  1. java逆向框架,Android逆向之逆向框架层

    前言 使用开源工具出现问题而且很难在网上查找到解决方案的时候,最好的解决方法就是研究它的源码,因为那样能为我们提供更多的信息. 搭建调试环境 首先我们在github上拉取smali/baksmali的 ...

  2. Android cec设备,Android和HDMI CEC

    是的,这是完全有可能做的,但它是非常可笑的. HDMI CEC像公共汽车一样工作.通常在两个方向. 你的问题: >是的.虽然我使用JNI访问实际工作的本机代码.您可能可以纯粹在Java中执行此操 ...

  3. android tv ko,Android TV 键值修改流程

    有的时候,我们需要增加一些新的按键,那么需要修改哪些地方呢? 1.Java层的修改:KeyEvent.java 修改了keyevent.java需要编译出android.policy.jar这个需要拷 ...

  4. binder 从c到java_Android系统进程间通信Binder机制在应用程序框架层的Java接口源代码分析...

    在前面几篇文章中,我们详细介绍了Android系统进程间通信机制Binder的原理,并且深入分析了系统提供的Binder运行库和驱动程序的源代码.细心的读者会发现,这几篇文章分析的Binder接口都是 ...

  5. Android TV框架 TIF(Android TV Input Framework)入门实践

    Tamic/CSDN http://blog.csdn.net/sk719887916/article/details/53645615 做TV开发一段时间了,国内目前关于这方面的资料并不多,这里我来 ...

  6. android调频收音机代码,android 收音机 FM 驱动 hal层 框架层以及应用层代码

    [实例简介] android 收音机 FM 驱动 hal层 框架层以及应用层代码 方法一 不需要framework部分 1.fm放到 \hardware\rk2x 2.FmRadio 放到 packa ...

  7. android 短信ril移植,将Android平台的RIL层移植到基于LINUX的通用平台的研究与实现...

    摘要:本文通过对Android RIL层代码分析,将android RIL层功能在纯LINUX平台上实现,完全脱离了Android系统.为基于LINUX的通用平台实现一套成熟的RIL层代码,并开发出相 ...

  8. Android HDMI CEC控制服务

    HDMI-CEC标准允许多媒体消费产品之间沟通和交换信息,HDMI-CEC支持许多功能,比如遥控器直通,系统音频控制,一键播放等等.Android通过HdmiControlService这个系统服务来 ...

  9. Android cec设备,Android HDMI CEC控制服务

    HDMI-CEC标准允许多媒体消费产品之间沟通和交换信息,HDMI-CEC支持许多功能,比如遥控器直通,系统音频控制,一键播放等等.Android通过HdmiControlService这个系统服务来 ...

最新文章

  1. java io 缓冲流_记忆系列-Java IO的缓存输入输出流(高效流)
  2. Eclipse导入项目常见问题----服务器版本问题02
  3. Linux脚本让我选择文件,linux – 用于选择文件和打印文件大小的Awk脚本
  4. SAP OData Service group - get entity set
  5. 用户信息填写web代码_Web前端常见问题汇总
  6. 译:重置/还原Windows IIs设置为默认设置
  7. python程序设计常见运算符号_python常用运算符
  8. 外卖小哥到底是一群什么样的人?答案超乎你想象
  9. Python之Numpy操作基础
  10. Beanutils基本用法
  11. 五、数据类型(1):整数带小数点的数
  12. 制造业数字化转型-项目案例合集
  13. stylegan2报错“undefined symbol: _ZN10tensorflow12OpDefBuilder6OutputESs”的解决方案
  14. 2021-01-16
  15. 用Python画论文折线图、曲线图?几个代码模板轻松搞定!
  16. 盘点3大智能家居系统|苹果HomeKit、亚马逊Alexa、谷歌Home?
  17. 功能性与非功能性需求
  18. android 4.4 flac,如何在Android中将音频原始转换为FLAC
  19. 云存储是什么?云存储的常见三种类型
  20. mysql marked crashed_MySQL解决is marked as crashed and should be repaired故障

热门文章

  1. 如何用大数据提升政府招商引资效能
  2. Android应用加固产品使用对比
  3. 模电笔记9 差分放大电路
  4. AR 预测模型的 Matlab 实现(超详细建模流程)
  5. html加入背景音乐放不出来,我设置好了背景音乐,为什么播放不出来呢?
  6. 员工休息时间被领导安排工作直接回怼,网友看后:大早上极度舒适
  7. STM32按键中断控制led亮灭
  8. [深度学习论文笔记]使用多模态MR成像分割脑肿瘤的HNF-Netv2
  9. php企业微信发送微信群组消息,企业微信可以给群成员单独群发消息吗?怎么给企业微信群里所有成员群发消息?...
  10. 34枚金币时间管理法