Android Tv HDMI-CEC框架层移植

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

[java]  view plain  copy
  1. diff --git a/core/java/android/hardware/hdmi/HdmiDeviceInfo.java b/core/java/android/hardware/hdmi/HdmiDeviceInfo.java  
  2. index 48ea9a6..a921ebb 100644  
  3. --- a/core/java/android/hardware/hdmi/HdmiDeviceInfo.java  
  4. +++ b/core/java/android/hardware/hdmi/HdmiDeviceInfo.java  
  5. @@ -19,6 +19,7 @@ package android.hardware.hdmi;  
  6.  import android.annotation.SystemApi;  
  7.  import android.os.Parcel;  
  8.  import android.os.Parcelable;  
  9. +import android.os.SystemProperties;  
  10.    
  11.  /** 
  12.   * A class to encapsulate device information for HDMI devices including CEC and MHL. In terms of 
  13. @@ -407,7 +408,10 @@ public class HdmiDeviceInfo implements Parcelable { 
  14.       * Returns display (OSD) name of the device. 
  15.       */  
  16.      public String getDisplayName() {  
  17. -        return mDisplayName;  
  18. +  
  19. +        mDisplayName = SystemProperties.get("persist.sys.exdevicename""box");  
  20. +        return mDisplayName;  
  21.      }  

2.在HdmiControlManager.java添加广播动作,主要用于发送广播获取电视,盒子的待机状态,第三方应用可以通过接受广播获取盒子和电视的待机状态

[java]  view plain  copy
  1. diff --git a/core/java/android/hardware/hdmi/HdmiControlManager.java b/core/java/android/hardware/hdmi/HdmiControlManager.java  
  2. old mode 100644  
  3. new mode 100755  
  4. index 308a219..4043e2e  
  5. --- a/core/java/android/hardware/hdmi/HdmiControlManager.java  
  6. +++ b/core/java/android/hardware/hdmi/HdmiControlManager.java  
  7. @@ -254,6 +254,16 @@ public final class HdmiControlManager {  
  8.      // True if we have a logical device of type TV hosted in the system.  
  9.      private final boolean mHasTvDevice;  
  10.    
  11. +   //Broadcast action for power status changed  
  12. +   public static final String POWER_STATUS_CHANGED = "com.rockchip.hdmicec.power_status_changed";  
  13. +   //The key for box power status  
  14. +   public static final String HDMI_CEC_POWER_STATUS = "hdmi_cec_power_status";  
  15. +   //The key for hdmi cec device type  
  16. +   public static final String HDMI_CEC_DEVICE_TYPE = "hdmi_cec_device_type";  
  17. +   //box type  
  18. +   public static final int TYPE_HDMI_CEC_BOX = 0;  
  19. +   //tv type  
  20. +   public static final int TYPE_HDMI_CEC_TV= 1;  

3.IHdmiControlService.aidl添加发送CEC命令,获取电视或盒子的逻辑地址,获取盒子电源状态等接口,这些接口在service端的HdmiControlService.java文件实现,第三方应用可以通过Binder机制去发送CEC控制命令,获取盒子电源状态等

[java]  view plain  copy
  1. diff --git a/core/java/android/hardware/hdmi/IHdmiControlService.aidl b/core/java/android/hardware/hdmi/IHdmiControlService.aidl  
  2. old mode 100644  
  3. new mode 100755  
  4. index c1e924e..62dea8a  
  5. --- a/core/java/android/hardware/hdmi/IHdmiControlService.aidl  
  6. +++ b/core/java/android/hardware/hdmi/IHdmiControlService.aidl  
  7. @@ -71,4 +71,10 @@ interface IHdmiControlService {  
  8.      void clearTimerRecording(int recorderAddress, int sourceType, in byte[] recordSource);  
  9.      void sendMhlVendorCommand(int portId, int offset, int length, in byte[] data);  
  10.      void addHdmiMhlVendorCommandListener(IHdmiMhlVendorCommandListener listener);  
  11. +   //send cec command  
  12. +   void sendControlCommand(int src, int targetAddress, int opCode, in byte[] params);  
  13. +   //get local address for specific type  
  14. +   int getLocalAddress(int type);  
  15. +   //get power status  
  16. +   int getPowerStatus();  
  17.  }  

4.在HdmiCecLocalDevice.java广播电视的待机状态,激活盒子作为输入源,控制盒子待机

[java]  view plain  copy
  1. diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java  
  2. old mode 100644  
  3. new mode 100755  
  4. index 7999321..e66d0d1  
  5. --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java  
  6. +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java  
  7. @@ -22,7 +22,9 @@ import android.os.Handler;  
  8.  import android.os.Looper;  
  9.  import android.os.Message;  
  10.  import android.os.SystemClock;  
  11. +import android.os.SystemProperties;  
  12.  import android.util.Slog;  
  13. +import android.util.Log;  
  14.  import android.view.InputDevice;  
  15.  import android.view.KeyCharacterMap;  
  16.  import android.view.KeyEvent;  
  17. @@ -35,7 +37,8 @@ import java.util.ArrayList;  
  18.  import java.util.Collections;  
  19.  import java.util.Iterator;  
  20.  import java.util.List;  
  21. -  
  22. +import android.util.Log;  
  23. +import android.hardware.hdmi.HdmiControlManager;  
  24.  /**  
  25.   * Class that models a logical CEC device hosted in this system. Handles initialization,  
  26.   * CEC commands that call for actions customized per device type.  
  27. @@ -222,10 +225,12 @@ abstract class HdmiCecLocalDevice {  
  28.      @ServiceThreadOnly  
  29.      boolean dispatchMessage(HdmiCecMessage message) {  
  30.          assertRunOnServiceThread();  
  31. +       Log.i(TAG, "dispatchMessage->message:" + message);  
  32.          int dest = message.getDestination();  
  33.          if (dest != mAddress && dest != Constants.ADDR_BROADCAST) {  
  34.              return false;  
  35.          }  
  36. +         
  37.          // Cache incoming message. Note that it caches only white-listed one.  
  38.          mCecMessageCache.cacheMessage(message);  
  39.          return onMessage(message);  
  40. @@ -234,7 +239,11 @@ abstract class HdmiCecLocalDevice {  
  41.      @ServiceThreadOnly  
  42.      protected final boolean onMessage(HdmiCecMessage message) {  
  43.          assertRunOnServiceThread();  
  44. +       if(message.getOpcode() == Constants.MESSAGE_REPORT_POWER_STATUS && message.getSource() == 0){  
  45. +           mService.sendPowerStatusChanged(HdmiControlManager.TYPE_HDMI_CEC_TV, (int)(message.getParams()[0]));  
  46. +       }  
  47.          if (dispatchMessageToAction(message)) {  
  48. +           Log.i(TAG, "onMessage->dispatchMessageToAction->message:" + message);  
  49.              return true;  
  50.          }  
  51.          switch (message.getOpcode()) {  
  52. @@ -314,6 +323,7 @@ abstract class HdmiCecLocalDevice {  
  53.      @ServiceThreadOnly  
  54.      private boolean dispatchMessageToAction(HdmiCecMessage message) {  
  55.          assertRunOnServiceThread();  
  56. +       Log.i(TAG, "dispatchMessageToAction->message:" + message);  
  57.          boolean processed = false;  
  58.          // Use copied action list in that processCommand may remove itself.  
  59.          for (HdmiCecFeatureAction action : new ArrayList<>(mActions)) {  
  60. @@ -367,7 +377,20 @@ abstract class HdmiCecLocalDevice {  
  61.    
  62.      @ServiceThreadOnly  
  63.      protected boolean handleRequestActiveSource(HdmiCecMessage message) {  
  64. -        return false;  
  65. +        assertRunOnServiceThread();  
  66. +        // Note that since this method is called after physical address allocation is done,  
  67. +        // mDeviceInfo should not be null.  
  68. +        HdmiCecMessage cecMessage = HdmiCecMessageBuilder.buildActiveSource(  
  69. +                mAddress, mDeviceInfo.getPhysicalAddress());  
  70. +        if (cecMessage != null) {  
  71. +           Log.i(TAG, "handleRequestActiveSource->cecMessage:" + message);  
  72. +            mService.sendCecCommand(cecMessage);  
  73. +        } else {  
  74. +           Log.i(TAG, "Failed to build <Request Active Source>:" + mDeviceInfo.getPhysicalAddress());  
  75. +            //Slog.w(TAG, "Failed to build <Request Active Source>:" + mDeviceInfo.getPhysicalAddress());  
  76. +        }  
  77. +        return true;  
  78. +  
  79.      }  

5.HdmiControlService.java实现IHdmiControlService.aidl添加的三个接口方法,监听HDMI的插拔事件,激活输入源,实现控制电视待机,唤醒的方法

[java]  view plain  copy
  1. diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java  
  2. old mode 100644  
  3. new mode 100755  
  4. index cfc5f7d..23a9698  
  5. --- a/services/core/java/com/android/server/hdmi/HdmiControlService.java  
  6. +++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java  
  7. @@ -28,7 +28,7 @@ import static com.android.server.hdmi.Constants.OPTION_MHL_ENABLE;  
  8.  import static com.android.server.hdmi.Constants.OPTION_MHL_INPUT_SWITCHING;  
  9.  import static com.android.server.hdmi.Constants.OPTION_MHL_POWER_CHARGE;  
  10.  import static com.android.server.hdmi.Constants.OPTION_MHL_SERVICE_CONTROL;  
  11.  import android.annotation.Nullable;  
  12.  import android.content.BroadcastReceiver;  
  13.  import android.content.ContentResolver;  
  14. @@ -49,6 +49,8 @@ import android.hardware.hdmi.IHdmiMhlVendorCommandListener;  
  15.  import android.hardware.hdmi.IHdmiRecordListener;  
  16.  import android.hardware.hdmi.IHdmiSystemAudioModeChangeListener;  
  17.  import android.hardware.hdmi.IHdmiVendorCommandListener;  
  18. +import android.hardware.hdmi.HdmiPlaybackClient.OneTouchPlayCallback;  
  19. +import android.hardware.hdmi.HdmiPlaybackClient;  
  20.  import android.media.AudioManager;  
  21.  import android.media.tv.TvInputManager;  
  22.  import android.media.tv.TvInputManager.TvInputCallback;  
  23. @@ -69,7 +71,7 @@ import android.util.ArraySet;  
  24.  import android.util.Slog;  
  25.  import android.util.SparseArray;  
  26.  import android.util.SparseIntArray;  
  27. +import android.hardware.display.DisplayManager;  
  28.  import com.android.internal.annotations.GuardedBy;  
  29.  import com.android.internal.util.IndentingPrintWriter;  
  30.  import com.android.server.SystemService;  
  31. @@ -77,9 +79,8 @@ import com.android.server.hdmi.HdmiAnnotations.ServiceThreadOnly;  
  32.  import com.android.server.hdmi.HdmiCecController.AllocateAddressCallback;  
  33.  import com.android.server.hdmi.HdmiCecLocalDevice.ActiveSource;  
  34.  import com.android.server.hdmi.HdmiCecLocalDevice.PendingActionClearedCallback;  
  35. +import android.view.Display;  
  36.  import libcore.util.EmptyArray;  
  37.  import java.io.FileDescriptor;  
  38.  import java.io.PrintWriter;  
  39.  import java.util.ArrayList;  
  40. @@ -87,7 +88,14 @@ import java.util.Arrays;  
  41.  import java.util.Collections;  
  42.  import java.util.List;  
  43.  import java.util.Locale;  
  44. +import android.util.Log;  
  45. +import android.view.KeyEvent;  
  46. +import android.view.InputEvent;  
  47. +import android.view.InputChannel;  
  48. +import android.view.InputDevice;  
  49. +import android.hardware.input.InputManager;  
  50. +import android.hardware.input.InputManager.InputDeviceListener;  
  51.  /** 
  52.   * Provides a service for sending and processing HDMI control messages, 
  53.   * HDMI-CEC and MHL control command, and providing the information on both standard. 
  54. @@ -146,15 +154,21 @@ public final class HdmiControlService extends SystemService { 
  55.          @Override 
  56.          public void onReceive(Context context, Intent intent) { 
  57.              assertRunOnServiceThread(); 
  58.              switch (intent.getAction()) { 
  59.                  case Intent.ACTION_SCREEN_OFF: 
  60.                      if (isPowerOnOrTransient()) { 
  61.                          onStandby(STANDBY_SCREEN_OFF); 
  62.                      } 
  63.                      break; 
  64.                  case Intent.ACTION_SCREEN_ON: 
  65.                      if (isPowerStandbyOrTransient()) { 
  66.                          onWakeUp(); 
  67. +                        touchTv(); 
  68.                      } 
  69.                      break; 
  70.                  case Intent.ACTION_CONFIGURATION_CHANGED: 
  71. @@ -292,7 +306,14 @@ public final class HdmiControlService extends SystemService { 
  72.   
  73.      @Nullable 
  74.      private PowerManager mPowerManager; 
  75. - 
  76. +    
  77. +   private DisplayManager mDisplayManager; 
  78. +    
  79. +   private HDMIListener mHdmiListener = new HDMIListener(); 
  80. +    
  81. +   private InputManager mInputManager; 
  82. +    
  83.      // Last input port before switching to the MHL port. Should switch back to this port 
  84.      // when the mobile device sends the request one touch play with off. 
  85.      // Gets invalidated if we go to other port/input. 
  86.  
  87.   
  88. @@ -422,10 +451,25 @@ public final class HdmiControlService extends SystemService { 
  89.              registerContentObserver(); 
  90.          } 
  91.          mMhlController.setOption(OPTION_MHL_SERVICE_CONTROL, ENABLED); 
  92. +        
  93. +       mDisplayManager = (DisplayManager) getContext().getSystemService(Context.DISPLAY_SERVICE); 
  94. +        
  95. +       if(mDisplayManager != null){ 
  96. +           mDisplayManager.registerDisplayListener(mHdmiListener, null); 
  97. +       } 
  98. +        
  99.      } 
  100.   
  101. @@ -455,8 +503,10 @@ public final class HdmiControlService extends SystemService { 
  102.       * Called when the initialization of local devices is complete. 
  103.       */  
  104.      private void onInitializeCecComplete(int initiatedBy) {  
  105. +       Log.i(TAG, "HdmiControlService8");  
  106.          if (mPowerStatus == HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON) {  
  107.              mPowerStatus = HdmiControlManager.POWER_STATUS_ON;  
  108. +           sendPowerStatusChanged(HdmiControlManager.TYPE_HDMI_CEC_BOX, mPowerStatus);  
  109.          }  
  110.          mWakeUpMessageReceived = false;  
  111.    
  112. @@ -814,12 +890,15 @@ public final class HdmiControlService extends SystemService {  
  113.       * @param command CEC command to send out  
  114.       * @param callback interface used to the result of send command  
  115.       */  
  116. -    @ServiceThreadOnly  
  117. +    //@ServiceThreadOnly  
  118.      void sendCecCommand(HdmiCecMessage command, @Nullable SendMessageCallback callback) {  
  119. -        assertRunOnServiceThread();  
  120. +        //assertRunOnServiceThread();  
  121. +       Log.i(TAG, "sendCecCommand->HdmiControlService35");  
  122.          if (mMessageValidator.isValid(command) == HdmiCecMessageValidator.OK) {  
  123. +           Log.i(TAG, "sendCecCommand->valid message type");  
  124.              mCecController.sendCommand(command, callback);  
  125.          } else {  
  126. +           Log.i(TAG, "sendCecCommand->Invalid message type:" + command);  
  127.              HdmiLogger.error("Invalid message type:" + command);  
  128.              if (callback != null) {  
  129.                  callback.onSendCompleted(Constants.SEND_RESULT_FAILURE);  
  130. @@ -827,9 +906,10 @@ public final class HdmiControlService extends SystemService {  
  131.          }  
  132.      }  
  133.    
  134. -    @ServiceThreadOnly  
  135. +    //@ServiceThreadOnly  
  136.      void sendCecCommand(HdmiCecMessage command) {  
  137. -        assertRunOnServiceThread();  
  138. +        //assertRunOnServiceThread();  
  139. +       Log.i(TAG, "HdmiControlService36");  
  140.          sendCecCommand(command, null);  
  141.      }  
  142.    
  143. @@ -842,13 +922,17 @@ public final class HdmiControlService extends SystemService {  
  144.      @ServiceThreadOnly  
  145.      void maySendFeatureAbortCommand(HdmiCecMessage command, int reason) {  
  146.          assertRunOnServiceThread();  
  147. +       Log.i(TAG, "HdmiControlService37");  
  148.          mCecController.maySendFeatureAbortCommand(command, reason);  
  149.      }  
  150.    
  151.      @ServiceThreadOnly  
  152.      boolean handleCecCommand(HdmiCecMessage message) {  
  153.          assertRunOnServiceThread();  
  154. +       Log.i(TAG, "HdmiControlService38");  
  155. +       Log.i(TAG, "handleCecCommand:" + message);  
  156.          if (!mAddressAllocated) {  
  157. +           Log.i(TAG, "handleCecCommand->mAddressAllocated is not allocate");  
  158.              mCecMessageBuffer.bufferMessage(message);  
  159.              return true;  
  160.          }  
  161.    
  162. @@ -1656,11 +1756,31 @@ public final class HdmiControlService extends SystemService {  
  163.              pw.decreaseIndent();  
  164.              pw.println("mPowerStatus: " + mPowerStatus);  
  165.          }  
  166. +         
  167. +       @Override  
  168. +       public void sendControlCommand(int src, int targetAddress, int opCode, byte[] params){  
  169. +           HdmiCecMessage cecMessage = new HdmiCecMessage(src, targetAddress, opCode, params);  
  170. +           sendCecCommand(cecMessage);  
  171. +       }  
  172. +         
  173. +       @Override  
  174. +       public int getLocalAddress(int type){  
  175. +           HdmiCecLocalDevice device = mCecController.getLocalDevice(type);  
  176. +           if(device != null)  
  177. +               return device.getLogicAddress();  
  178. +           return -1;  
  179. +       }  
  180. +         
  181. +       @Override  
  182. +       public int getPowerStatus(){  
  183. +           return HdmiControlService.this.getPowerStatus();  
  184. +       }  
  185.      }  
  186.    
  187.      @ServiceThreadOnly  
  188.      private void oneTouchPlay(final IHdmiControlCallback callback) {  
  189.          assertRunOnServiceThread();  
  190. +       Log.i(TAG, "HdmiControlService54");  
  191.          HdmiCecLocalDevicePlayback source = playback();  
  192.          if (source == null) {  
  193.              Slog.w(TAG, "Local playback device not available");  
  194. @@ -1986,7 +2136,9 @@ public final class HdmiControlService extends SystemService {  
  195.      @ServiceThreadOnly  
  196.      private void onWakeUp() {  
  197.          assertRunOnServiceThread();  
  198. +       Log.i(TAG, "HdmiControlService85");  
  199.          mPowerStatus = HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON;  
  200. +       sendPowerStatusChanged(HdmiControlManager.TYPE_HDMI_CEC_BOX, mPowerStatus);  
  201.          if (mCecController != null) {  
  202.              if (mHdmiControlEnabled) {  
  203.                  int startReason = INITIATED_BY_SCREEN_ON;  
  204. @@ -2004,8 +2156,12 @@ public final class HdmiControlService extends SystemService {  
  205.      @ServiceThreadOnly  
  206.      private void onStandby(final int standbyAction) {  
  207.          assertRunOnServiceThread();  
  208. +       Log.i(TAG, "HdmiControlService86");  
  209. +       Log.i(TAG, "onStandby:" + 0);  
  210.          if (!canGoToStandby()) return;  
  211. +       Log.i(TAG, "onStandby:" + 1);  
  212.          mPowerStatus = HdmiControlManager.POWER_STATUS_TRANSIENT_TO_STANDBY;  
  213. +       sendPowerStatusChanged(HdmiControlManager.TYPE_HDMI_CEC_BOX, mPowerStatus);  
  214.          invokeVendorCommandListenersOnControlStateChanged(false,  
  215.                  HdmiControlManager.CONTROL_STATE_CHANGED_REASON_STANDBY);  
  216.    
  217. @@ -2026,6 +2182,7 @@ public final class HdmiControlService extends SystemService {  
  218.      }  
  219.    
  220.      private boolean canGoToStandby() {  
  221. +       Log.i(TAG, "HdmiControlService87");  
  222.          for (HdmiCecLocalDevice device : mCecController.getLocalDeviceList()) {  
  223.              if (!device.canGoToStandby()) return false;  
  224.          }  
  225. @@ -2035,6 +2192,7 @@ public final class HdmiControlService extends SystemService {  
  226.      @ServiceThreadOnly  
  227.      private void onLanguageChanged(String language) {  
  228.          assertRunOnServiceThread();  
  229. +       Log.i(TAG, "HdmiControlService88");  
  230.          mLanguage = language;  
  231.    
  232.          if (isTvDeviceEnabled()) {  
  233. @@ -2046,10 +2204,12 @@ public final class HdmiControlService extends SystemService {  
  234.      @ServiceThreadOnly  
  235.      String getLanguage() {  
  236.          assertRunOnServiceThread();  
  237. +       Log.i(TAG, "HdmiControlService89");  
  238.          return mLanguage;  
  239.      }  
  240.    
  241.      private void disableDevices(PendingActionClearedCallback callback) {  
  242. +       Log.i(TAG, "HdmiControlService90");  
  243.          if (mCecController != null) {  
  244.              for (HdmiCecLocalDevice device : mCecController.getLocalDeviceList()) {  
  245.                  device.disableDevice(mStandbyMessageReceived, callback);  
  246. @@ -2062,6 +2222,7 @@ public final class HdmiControlService extends SystemService {  
  247.      @ServiceThreadOnly  
  248.      private void clearLocalDevices() {  
  249.          assertRunOnServiceThread();  
  250. +       Log.i(TAG, "HdmiControlService91");  
  251.          if (mCecController == null) {  
  252.              return;  
  253.          }  
  254. @@ -2072,12 +2233,14 @@ public final class HdmiControlService extends SystemService {  
  255.      @ServiceThreadOnly  
  256.      private void onStandbyCompleted(int standbyAction) {  
  257.          assertRunOnServiceThread();  
  258. +       Log.i(TAG, "HdmiControlService92");  
  259.          Slog.v(TAG, "onStandbyCompleted");  
  260.    
  261.          if (mPowerStatus != HdmiControlManager.POWER_STATUS_TRANSIENT_TO_STANDBY) {  
  262.              return;  
  263.          }  
  264.          mPowerStatus = HdmiControlManager.POWER_STATUS_STANDBY;  
  265. +       sendPowerStatusChanged(HdmiControlManager.TYPE_HDMI_CEC_BOX, mPowerStatus);  
  266.          for (HdmiCecLocalDevice device : mCecController.getLocalDeviceList()) {  
  267.              device.onStandby(mStandbyMessageReceived, standbyAction);  
  268.          }  
  269. @@ -2317,10 +2496,136 @@ public final class HdmiControlService extends SystemService {  
  270.      @ServiceThreadOnly  
  271.      void displayOsd(int messageId, int extra) {  
  272.          assertRunOnServiceThread();  
  273. +       Log.i(TAG, "HdmiControlService111");  
  274.          Intent intent = new Intent(HdmiControlManager.ACTION_OSD_MESSAGE);  
  275.          intent.putExtra(HdmiControlManager.EXTRA_MESSAGE_ID, messageId);  
  276.          intent.putExtra(HdmiControlManager.EXTRA_MESSAGE_EXTRA_PARAM1, extra);  
  277.          getContext().sendBroadcastAsUser(intent, UserHandle.ALL,  
  278.                  HdmiControlService.PERMISSION);  
  279.      }  
  280. +  
  281. +  
  282. +   public void standbyTv(){  
  283. +       if(mCecController != null){  
  284. +           HdmiCecLocalDevice playBackDevice = mCecController.getLocalDevice(HdmiDeviceInfo.DEVICE_PLAYBACK);  
  285. +           int playBackAddrss = playBackDevice.getLogicAddress();  
  286. +           byte[] cecParam = new byte[0];  
  287. +           final HdmiCecMessage cecMessage = new HdmiCecMessage(playBackAddrss, 00x36, cecParam);  
  288. +           sendCecCommand(cecMessage, new SendMessageCallback(){  
  289. +               public void onSendCompleted(int error){  
  290. +                   if(error == Constants.SEND_RESULT_SUCCESS){  
  291. +                       sendPowerStatusChanged(HdmiControlManager.TYPE_HDMI_CEC_TV, HdmiControlManager.POWER_STATUS_STANDBY);  
  292. +                       Log.i(TAG, "standbyTv->sendCecCommand success");  
  293. +                   }     
  294. +                   else  
  295. +                       Log.i(TAG, "standbyTv->sendCecCommand failed");  
  296. +               }  
  297. +           });  
  298. +       }  
  299. +   }  
  300. +     
  301. +     
  302. +   public void touchTv(){  
  303. +       Log.i(TAG, "touchTv-1");  
  304. +       HdmiControlManager controlManager = (HdmiControlManager)getContext().getSystemService(Context.HDMI_CONTROL_SERVICE);  
  305. +       if(controlManager == null)  
  306. +           return;  
  307. +       Log.i(TAG, "touchTv-2");  
  308. +       HdmiPlaybackClient playbackClient = controlManager.getPlaybackClient();  
  309. +       if(playbackClient == null)  
  310. +           return;  
  311. +       Log.i(TAG, "touchTv-3");  
  312. +       playbackClient.oneTouchPlay(new OneTouchPlayCallback() {  
  313. +           @Override  
  314. +           public void onComplete(int result) {  
  315. +               if (result != HdmiControlManager.RESULT_SUCCESS) {  
  316. +                   Log.i(TAG, "One touch play failed: " + result);  
  317. +               } else {  
  318. +                   Log.i(TAG, "One touch play succeed: " + result);  
  319. +  
  320. +               }  
  321. +           }  
  322. +       });  
  323. +   }  
  324. +     
  325. +   public void sendActiveSource(){  
  326. +       if(mCecController != null){  
  327. +           HdmiCecLocalDevice playBackDevice = mCecController.getLocalDevice(HdmiDeviceInfo.DEVICE_PLAYBACK);  
  328. +           int playBackAddrss = playBackDevice.getLogicAddress();  
  329. +           byte[] cecParam = new byte[0];  
  330. +           HdmiCecMessage cecMessageToTv = new HdmiCecMessage(playBackAddrss, 00x85, cecParam);  
  331. +           HdmiCecMessage cecMessageToPlayBack = new HdmiCecMessage(0, playBackAddrss, 0x85, cecParam);  
  332. +           sendCecCommand(cecMessageToTv, new SendMessageCallback(){  
  333. +               public void onSendCompleted(int error){  
  334. +                   if(error == Constants.SEND_RESULT_SUCCESS)  
  335. +                       Log.i(TAG, "sendActiveSource->sendCecCommand to tv success");  
  336. +                   else  
  337. +                       Log.i(TAG, "sendActiveSource->sendCecCommand to tv failed");  
  338. +               }  
  339. +           });  
  340. +             
  341. +           sendCecCommand(cecMessageToPlayBack, new SendMessageCallback(){  
  342. +               public void onSendCompleted(int error){  
  343. +                   if(error == Constants.SEND_RESULT_SUCCESS)  
  344. +                       Log.i(TAG, "sendActiveSource->sendCecCommand to playback success");  
  345. +                   else  
  346. +                       Log.i(TAG, "sendActiveSource->sendCecCommand to playback failed");  
  347. +               }  
  348. +           });  
  349. +       }  
  350. +         
  351. +   }  
  352. +     
  353. +   public void sendPowerStatusChanged(int deviceType, int powerStatus){  
  354. +       Log.i(TAG, "sendPowerStatusChanged");  
  355. +       Intent intent = new Intent(HdmiControlManager.POWER_STATUS_CHANGED);  
  356. +       intent.putExtra(HdmiControlManager.HDMI_CEC_POWER_STATUS, powerStatus);  
  357. +       intent.putExtra(HdmiControlManager.HDMI_CEC_DEVICE_TYPE, deviceType);  
  358. +                intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);  
  359. +       getContext().sendBroadcast(intent);  
  360. +   }  
  361. +     
  362. +   class HDMIListener implements DisplayManager.DisplayListener {  
  363. +  
  364. +       @Override  
  365. +       public void onDisplayAdded(int displayId) {  
  366. +           Display display = mDisplayManager.getDisplay(displayId);  
  367. +           Log.i(TAG, "HDMI Add:" + display);  
  368. +           sendActiveSource();  
  369. +           touchTv();  
  370. +       }  
  371. +  
  372. +       @Override  
  373. +       public void onDisplayRemoved(int displayId) {  
  374. +           Display display = mDisplayManager.getDisplay(displayId);  
  375. +           Log.i(TAG, "HDMI removed:" + display);  
  376. +       }  
  377. +  
  378. +       @Override  
  379. +       public void onDisplayChanged(int displayId) {  
  380. +  
  381. +       }  
  382. +  
  383. +   }     
  384.       
  385.  }  

6.PowerManagerService.java在盒子待机的时候,也让电视待机

[java]  view plain  copy
  1. diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java  
  2. index 9a20aa2..d5bf708 100755  
  3. --- a/services/core/java/com/android/server/power/PowerManagerService.java  
  4. +++ b/services/core/java/com/android/server/power/PowerManagerService.java  
  5. @@ -89,6 +89,9 @@ import static android.os.PowerManagerInternal.WAKEFULNESS_ASLEEP;  
  6.  import static android.os.PowerManagerInternal.WAKEFULNESS_AWAKE;  
  7.  import static android.os.PowerManagerInternal.WAKEFULNESS_DREAMING;  
  8.  import static android.os.PowerManagerInternal.WAKEFULNESS_DOZING;  
  9. +//FOR CEC  
  10. +import android.hardware.hdmi.*;  
  11. +import android.os.ServiceManager;  
  12.    
  13.  /**  
  14.   * The power manager service is responsible for coordinating power management  
  15. @@ -1166,6 +1169,17 @@ public final class PowerManagerService extends SystemService  
  16.          }  
  17.    
  18.          Trace.traceBegin(Trace.TRACE_TAG_POWER, "goToSleep");  
  19. +        //FOR CEC standbyTv  
  20. +        IBinder playBinder = ServiceManager.getService(Context.HDMI_CONTROL_SERVICE);  
  21. +        IHdmiControlService mControlService = IHdmiControlService.Stub.asInterface(playBinder);  
  22. +        try {  
  23. +           Slog.i(TAG, "send cec standby command to TV");  
  24. +           mControlService.sendControlCommand(mControlService.getLocalAddress(HdmiDeviceInfo.DEVICE_PLAYBACK), 0 , 0x36new byte[]{});  
  25. +        } catch (Exception e) {  
  26. +                        Slog.i(TAG, "发送待机指令出错" + e);  
  27. +        }  
  28. +  
  29. +  
  30.          try {  
  31.              switch (reason) {  
  32.                  case PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN:  

至此,HDMI-CEC基本的功能(待机,唤醒,获取电源状态)已经实现

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值