diff options
7 files changed, 109 insertions, 21 deletions
diff --git a/api/current.txt b/api/current.txt index 92b729c..29dffc5 100644 --- a/api/current.txt +++ b/api/current.txt @@ -12158,6 +12158,7 @@ package android.hardware.hdmi { public final class HdmiCecClient { method public boolean isTvOn(); method public void sendActiveSource(); + method public void sendGiveDevicePowerStatus(int); method public void sendImageViewOn(); method public void sendInactiveSource(); method public void sendTextViewOn(); diff --git a/core/java/android/hardware/hdmi/HdmiCecClient.java b/core/java/android/hardware/hdmi/HdmiCecClient.java index 1f382e6..cd86cd8 100644 --- a/core/java/android/hardware/hdmi/HdmiCecClient.java +++ b/core/java/android/hardware/hdmi/HdmiCecClient.java @@ -88,7 +88,7 @@ public final class HdmiCecClient { } /** - * Send <TextViewOn> message. + * Send <Text View On> message. */ public void sendTextViewOn() { try { @@ -99,7 +99,7 @@ public final class HdmiCecClient { } /** - * Send <ImageViewOn> message. + * Send <Image View On> message. */ public void sendImageViewOn() { try { @@ -110,6 +110,20 @@ public final class HdmiCecClient { } /** + * Send <Give Device Power Status> message. + * + * @param address logical address of the device to send the message to, such as + * {@link HdmiCec#ADDR_TV}. + */ + public void sendGiveDevicePowerStatus(int address) { + try { + mService.sendGiveDevicePowerStatus(mBinder, address); + } catch (RemoteException e) { + Log.e(TAG, "sendGiveDevicePowerStatus threw exception ", e); + } + } + + /** * Returns true if the TV or attached display is powered on. * <p> * The result of this method is only meaningful on playback devices (where the device diff --git a/core/java/android/hardware/hdmi/IHdmiCecService.aidl b/core/java/android/hardware/hdmi/IHdmiCecService.aidl index b5df131..ecdd345 100644 --- a/core/java/android/hardware/hdmi/IHdmiCecService.aidl +++ b/core/java/android/hardware/hdmi/IHdmiCecService.aidl @@ -33,6 +33,7 @@ interface IHdmiCecService { void sendInactiveSource(IBinder b); void sendImageViewOn(IBinder b); void sendTextViewOn(IBinder b); + void sendGiveDevicePowerStatus(IBinder b, int address); boolean isTvOn(IBinder b); void sendMessage(IBinder b, in HdmiCecMessage message); } diff --git a/services/core/java/com/android/server/hdmi/HdmiCecDevice.java b/services/core/java/com/android/server/hdmi/HdmiCecDevice.java index 64b51c9..baae1d9 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecDevice.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecDevice.java @@ -182,11 +182,49 @@ abstract class HdmiCecDevice { } /** + * Send <Active Source> command. The default implementation does nothing. Should be + * overriden by subclass. + */ + public void sendActiveSource(int physicalAddress) { + logWarning("<Active Source> not valid for the device type: " + mType + + " address:" + physicalAddress); + } + + /** + * Send <Inactive Source> command. The default implementation does nothing. Should be + * overriden by subclass. + */ + public void sendInactiveSource(int physicalAddress) { + logWarning("<Inactive Source> not valid for the device type: " + mType + + " address:" + physicalAddress); + } + + /** + * Send <Image View On> command. The default implementation does nothing. Should be + * overriden by subclass. + */ + public void sendImageViewOn() { + logWarning("<Image View On> not valid for the device type: " + mType); + } + + /** + * Send <Text View On> command. The default implementation does nothing. Should be + * overriden by subclass. + */ + public void sendTextViewOn() { + logWarning("<Text View On> not valid for the device type: " + mType); + } + + /** * Check if the connected sink device is in powered-on state. The default implementation * simply returns false. Should be overriden by subclass to report the correct state. */ public boolean isSinkDeviceOn() { - Log.w(TAG, "Not valid for the device type: " + mType); + logWarning("isSinkDeviceOn() not valid for the device type: " + mType); return false; } + + private void logWarning(String msg) { + Log.w(TAG, msg); + } } diff --git a/services/core/java/com/android/server/hdmi/HdmiCecDevicePlayback.java b/services/core/java/com/android/server/hdmi/HdmiCecDevicePlayback.java index 0310264..f8cf11d 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecDevicePlayback.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecDevicePlayback.java @@ -66,14 +66,11 @@ final class HdmiCecDevicePlayback extends HdmiCecDevice { // 1) Response for the queried power status request arrives. Update the status. // 2) Broadcast or direct <Standby> command from TV, which is sent as TV itself is going // into standby mode too. - // 3) Broadcast <Report Physical Address> command from TV, which is sent while it boots up. if (opcode == HdmiCec.MESSAGE_REPORT_POWER_STATUS) { mSinkDevicePowerStatus = params[0]; } else if (srcAddress == HdmiCec.ADDR_TV) { if (opcode == HdmiCec.MESSAGE_STANDBY) { mSinkDevicePowerStatus = HdmiCec.POWER_STATUS_STANDBY; - } else if (opcode == HdmiCec.MESSAGE_REPORT_PHYSICAL_ADDRESS) { - mSinkDevicePowerStatus = HdmiCec.POWER_STATUS_ON; } } super.handleMessage(srcAddress, dstAddress, opcode, params); @@ -95,4 +92,38 @@ final class HdmiCecDevicePlayback extends HdmiCecDevice { public boolean isSinkDeviceOn() { return mSinkDevicePowerStatus == HdmiCec.POWER_STATUS_ON; } + + @Override + public void sendActiveSource(int physicalAddress) { + setIsActiveSource(true); + byte[] param = new byte[] { + (byte) ((physicalAddress >> 8) & 0xff), + (byte) (physicalAddress & 0xff) + }; + getService().sendMessage(getType(), HdmiCec.ADDR_BROADCAST, HdmiCec.MESSAGE_ACTIVE_SOURCE, + param); + } + + @Override + public void sendInactiveSource(int physicalAddress) { + setIsActiveSource(false); + byte[] param = new byte[] { + (byte) ((physicalAddress >> 8) & 0xff), + (byte) (physicalAddress & 0xff) + }; + getService().sendMessage(getType(), HdmiCec.ADDR_TV, HdmiCec.MESSAGE_INACTIVE_SOURCE, + param); + } + + @Override + public void sendImageViewOn() { + getService().sendMessage(getType(), HdmiCec.ADDR_TV, HdmiCec.MESSAGE_IMAGE_VIEW_ON, + HdmiCecService.EMPTY_PARAM); + } + + @Override + public void sendTextViewOn() { + getService().sendMessage(getType(), HdmiCec.ADDR_TV, HdmiCec.MESSAGE_TEXT_VIEW_ON, + HdmiCecService.EMPTY_PARAM); + } } diff --git a/services/core/java/com/android/server/hdmi/HdmiCecService.java b/services/core/java/com/android/server/hdmi/HdmiCecService.java index aa496c5..0a4c719 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecService.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecService.java @@ -277,14 +277,7 @@ public final class HdmiCecService extends SystemService { enforceAccessPermission(); synchronized (mLock) { HdmiCecDevice device = getLogicalDeviceLocked(b); - device.setIsActiveSource(true); - int physicalAddress = nativeGetPhysicalAddress(mNativePtr); - byte[] param = new byte[] { - (byte) ((physicalAddress >> 8) & 0xff), - (byte) (physicalAddress & 0xff) - }; - nativeSendMessage(mNativePtr, device.getType(), HdmiCec.ADDR_BROADCAST, - HdmiCec.MESSAGE_ACTIVE_SOURCE, param); + device.sendActiveSource(nativeGetPhysicalAddress(mNativePtr)); } } @@ -293,9 +286,7 @@ public final class HdmiCecService extends SystemService { enforceAccessPermission(); synchronized (mLock) { HdmiCecDevice device = getLogicalDeviceLocked(b); - device.setIsActiveSource(false); - nativeSendMessage(mNativePtr, device.getType(), HdmiCec.ADDR_BROADCAST, - HdmiCec.MESSAGE_INACTIVE_SOURCE, EMPTY_PARAM); + device.sendInactiveSource(nativeGetPhysicalAddress(mNativePtr)); } } @@ -304,8 +295,7 @@ public final class HdmiCecService extends SystemService { enforceAccessPermission(); synchronized (mLock) { HdmiCecDevice device = getLogicalDeviceLocked(b); - nativeSendMessage(mNativePtr, device.getType(), HdmiCec.ADDR_TV, - HdmiCec.MESSAGE_IMAGE_VIEW_ON, EMPTY_PARAM); + device.sendImageViewOn(); } } @@ -314,8 +304,16 @@ public final class HdmiCecService extends SystemService { enforceAccessPermission(); synchronized (mLock) { HdmiCecDevice device = getLogicalDeviceLocked(b); - nativeSendMessage(mNativePtr, device.getType(), HdmiCec.ADDR_TV, - HdmiCec.MESSAGE_TEXT_VIEW_ON, EMPTY_PARAM); + device.sendTextViewOn(); + } + } + + public void sendGiveDevicePowerStatus(IBinder b, int address) { + enforceAccessPermission(); + synchronized (mLock) { + HdmiCecDevice device = getLogicalDeviceLocked(b); + nativeSendMessage(mNativePtr, device.getType(), address, + HdmiCec.MESSAGE_GIVE_DEVICE_POWER_STATUS, EMPTY_PARAM); } } diff --git a/services/core/jni/com_android_server_hdmi_HdmiCecService.cpp b/services/core/jni/com_android_server_hdmi_HdmiCecService.cpp index a00aaa8..54c9755 100644 --- a/services/core/jni/com_android_server_hdmi_HdmiCecService.cpp +++ b/services/core/jni/com_android_server_hdmi_HdmiCecService.cpp @@ -204,6 +204,11 @@ cec_logical_address_t HdmiCecHandler::initLogicalDevice(cec_device_type_t type) } else { ALOGV("Logical Address Allocation success: %d", addr); mLogicalDevices.insert(std::pair<cec_device_type_t, cec_logical_address_t>(type, addr)); + + // Broadcast <Report Physical Address> when a new logical address was allocated to let + // other devices discover the new logical device and its logical - physical address + // association. + sendReportPhysicalAddress(); } return addr; } |