summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Android.mk1
-rw-r--r--core/java/android/hardware/hdmi/HdmiRecordSources.java743
-rw-r--r--core/java/android/hardware/hdmi/HdmiTvClient.java67
-rw-r--r--core/java/android/hardware/hdmi/IHdmiControlService.aidl3
-rw-r--r--core/java/android/hardware/hdmi/IHdmiRecordRequestListener.aidl27
-rw-r--r--services/core/java/com/android/server/hdmi/Constants.java5
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiControlService.java11
-rw-r--r--services/core/java/com/android/server/hdmi/OneTouchRecordAction.java27
8 files changed, 879 insertions, 5 deletions
diff --git a/Android.mk b/Android.mk
index 3b01f70..0d02be7 100644
--- a/Android.mk
+++ b/Android.mk
@@ -155,6 +155,7 @@ LOCAL_SRC_FILES += \
core/java/android/hardware/hdmi/IHdmiDeviceEventListener.aidl \
core/java/android/hardware/hdmi/IHdmiHotplugEventListener.aidl \
core/java/android/hardware/hdmi/IHdmiInputChangeListener.aidl \
+ core/java/android/hardware/hdmi/IHdmiRecordRequestListener.aidl \
core/java/android/hardware/hdmi/IHdmiSystemAudioModeChangeListener.aidl \
core/java/android/hardware/hdmi/IHdmiVendorCommandListener.aidl \
core/java/android/hardware/input/IInputManager.aidl \
diff --git a/core/java/android/hardware/hdmi/HdmiRecordSources.java b/core/java/android/hardware/hdmi/HdmiRecordSources.java
new file mode 100644
index 0000000..5a02c34
--- /dev/null
+++ b/core/java/android/hardware/hdmi/HdmiRecordSources.java
@@ -0,0 +1,743 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.hdmi;
+
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.util.Log;
+
+/**
+ * Container for record source used for one touch record.
+ * Use one of helper method by source type.
+ * <ul>
+ * <li>Own source: {@link #ofOwnSource()}
+ * <li>Digital service(channel id): {@link #ofDigitalChannelId(int, DigitalChannelData)}
+ * <li>Digital service(ARIB): {@link #ofArib(int, AribData)}
+ * <li>Digital service(ATSC): {@link #ofAtsc(int, AtscData)}
+ * <li>Digital service(DVB): {@link #ofDvb(int, DvbData)}
+ * <li>Analogue: {@link #ofAnalogue(int, int, int)}
+ * <li>External plug: {@link #ofExternalPlug(int)}
+ * <li>External physical address: {@link #ofExternalPhysicalAddress(int)}.
+ * <ul>
+ *
+ * @hide
+ */
+@SystemApi
+public final class HdmiRecordSources {
+ private static final String TAG = "HdmiRecordSources";
+
+ /** Record source type for "Own Source". */
+ private static final int RECORD_SOURCE_TYPE_OWN_SOURCE = 1;
+ /** Record source type for "Digital Service". */
+ private static final int RECORD_SOURCE_TYPE_DIGITAL_SERVICE = 2;
+ /** Record source type for "Analogue Service". */
+ private static final int RECORD_SOURCE_TYPE_ANALOGUE_SERVICE = 3;
+ /** Record source type for "Exteranl Plug". */
+ private static final int RECORD_SOURCE_TYPE_EXTERNAL_PLUG = 4;
+ /** Record source type for "External Physical Address". */
+ private static final int RECORD_SOURCE_TYPE_EXTERNAL_PHYSICAL_ADDRESS = 5;
+
+ private HdmiRecordSources() {}
+
+ /**
+ * Base class for each record source.
+ */
+ static abstract class RecordSource {
+ protected final int mSourceType;
+ protected final int mExtraDataSize;
+
+ protected RecordSource(int sourceType, int extraDataSize) {
+ mSourceType = sourceType;
+ mExtraDataSize = extraDataSize;
+ }
+
+ abstract int extraParamToByteArray(byte[] data, int index);
+
+ final int getDataSize(boolean includeType) {
+ return includeType ? mExtraDataSize + 1 : mExtraDataSize;
+ }
+
+ public final int toByteArray(boolean includeType, byte[] data, int index) {
+ if (includeType) {
+ // 1 to 8 bytes (depends on source).
+ // {[Record Source Type]} |
+ // {[Record Source Type] [Digital Service Identification]} |
+ // {[Record Source Type] [Analogue Broadcast Type] [Analogue Frequency]
+ // [Broadcast System]} |
+ // {[Record Source Type] [External Plug]} |
+ // {[Record Source Type] [External Physical Address]}
+ // The first byte is used for record source type.
+ data[index++] = (byte) mSourceType;
+ }
+ extraParamToByteArray(data, index);
+ return getDataSize(includeType);
+ }
+ }
+
+ // ---------------------------------------------------------------------------------------------
+ // ---- Own source -----------------------------------------------------------------------------
+ // ---------------------------------------------------------------------------------------------
+ /**
+ * Create {@link OwnSource} of own source.
+ */
+ public static OwnSource ofOwnSource() {
+ return new OwnSource();
+ }
+
+ /**
+ * @hide
+ */
+ @SystemApi
+ public static final class OwnSource extends RecordSource {
+ protected OwnSource() {
+ super(RECORD_SOURCE_TYPE_OWN_SOURCE, 0);
+ }
+
+ @Override
+ int extraParamToByteArray(byte[] data, int index) {
+ return 0;
+ }
+ }
+
+
+ // ---------------------------------------------------------------------------------------------
+ // ---- Digital service data -------------------------------------------------------------------
+ // ---------------------------------------------------------------------------------------------
+ /**
+ * Digital broadcast general types
+ */
+ /** @hide */
+ public static final int DIGITAL_BROADCAST_TYPE_ARIB = 0x0;
+ /** @hide */
+ public static final int DIGITAL_BROADCAST_TYPE_ATSC = 0x1;
+ /** @hide */
+ public static final int DIGITAL_BROADCAST_TYPE_DVB = 0x2;
+
+ /**
+ * Digital broadcast specific types
+ */
+ /** @hide */
+ public static final int DIGITAL_BROADCAST_TYPE_ARIB_BS = 0x8;
+ /** @hide */
+ public static final int DIGITAL_BROADCAST_TYPE_ARIB_CS = 0x9;
+ /** @hide */
+ public static final int DIGITAL_BROADCAST_TYPE_ARIB_T = 0xA;
+ /** @hide */
+ public static final int DIGITAL_BROADCAST_TYPE_ATSC_CABLE = 0x10;
+ /** @hide */
+ public static final int DIGITAL_BROADCAST_TYPE_ATSC_SATELLITE = 0x11;
+ /** @hide */
+ public static final int DIGITAL_BROADCAST_TYPE_ATSC_TERRESTRIAL = 0x12;
+ /** @hide */
+ public static final int DIGITAL_BROADCAST_TYPE_DVB_C = 0x18;
+ /** @hide */
+ public static final int DIGITAL_BROADCAST_TYPE_DVB_S = 0x19;
+ /** @hide */
+ public static final int DIGITAL_BROADCAST_TYPE_DVB_S2 = 0x1A;
+ /** @hide */
+ public static final int DIGITAL_BROADCAST_TYPE_DVB_T = 0x1B;
+
+ /** Channel number formats. */
+ private static final int CHANNEL_NUMBER_FORMAT_1_PART = 0x01;
+ private static final int CHANNEL_NUMBER_FORMAT_2_PART = 0x02;
+
+ /**
+ * Interface for digital source identification.
+ */
+ private interface DigitalServiceIdentification {
+ void toByteArray(byte[] data, int index);
+ }
+
+ /**
+ * Digital service identification for ARIB.
+ * <p>
+ * It consists of the following fields
+ * <ul>
+ * <li>transport stream id: 2bytes
+ * <li>service id: 2bytes
+ * <li>original network id: 2bytes
+ * </ul>
+ * @hide
+ */
+ public static final class AribData implements DigitalServiceIdentification {
+ /** The transport_stream_ID of the transport stream carrying the required service */
+ private final int mTransportStreamId;
+ /** The service_ID of the required service */
+ private final int mServiceId;
+ /**
+ * The original_network_ID of the network carrying the transport stream for the required
+ * service
+ */
+ private final int mOriginalNetworkId;
+
+ public AribData(int transportStreamId, int serviceId, int originalNetworkId) {
+ mTransportStreamId = transportStreamId;
+ mServiceId = serviceId;
+ mOriginalNetworkId = originalNetworkId;
+ }
+
+ @Override
+ public void toByteArray(byte[] data, int index) {
+ threeFieldsToSixBytes(mTransportStreamId, mServiceId, mOriginalNetworkId, data, index);
+ }
+ }
+
+ /**
+ * Digital service identification for ATSC.
+ * <p>
+ * It consists of the following fields
+ * <ul>
+ * <li>transport stream id: 2bytes
+ * <li>program number: 2bytes
+ * <li>reserved: 2bytes
+ * </ul>
+ * @hide
+ */
+ public static final class AtscData implements DigitalServiceIdentification {
+ /** The transport_stream_ID of the transport stream carrying the required service */
+ private final int mTransportStreamId;
+ /** The Program_number of the required service */
+ private final int mProgramNumber;
+
+ public AtscData(int transportStreamId, int programNumber) {
+ mTransportStreamId = transportStreamId;
+ mProgramNumber = programNumber;
+ }
+
+ @Override
+ public void toByteArray(byte[] data, int index) {
+ threeFieldsToSixBytes(mTransportStreamId, mProgramNumber, 0, data, index);
+ }
+ }
+
+ /**
+ * Digital service identification for DVB.
+ * <p>
+ * It consists of the following fields
+ * <ul>
+ * <li>transport stream id: 2bytes
+ * <li>service id: 2bytes
+ * <li>original network id: 2bytes
+ * </ul>
+ * @hide
+ */
+ public static final class DvbData implements DigitalServiceIdentification {
+ /** The transport_stream_ID of the transport stream carrying the required service */
+ private final int mTransportStreamId;
+ /** The service_ID of the required service */
+ private final int mServiceId;
+ /**
+ * The original_network_ID of the network carrying the transport stream for the required
+ * service
+ */
+ private final int mOriginalNetworkId;
+
+ public DvbData(int transportStreamId, int serviceId, int originalNetworkId) {
+ mTransportStreamId = transportStreamId;
+ mServiceId = serviceId;
+ mOriginalNetworkId = originalNetworkId;
+ }
+
+ @Override
+ public void toByteArray(byte[] data, int index) {
+ threeFieldsToSixBytes(mTransportStreamId, mServiceId, mOriginalNetworkId, data, index);
+ }
+ }
+
+ /**
+ * Identifies a 1-part Logical or Virtual Channel Number or a 2-part Major and Minor channel
+ * combination.
+ */
+ private static final class ChannelIdentifier {
+ /** Identifies Channel Format */
+ private final int mChannelNumberFormat;
+ /**
+ * Major Channel Number (if Channel Number Format is 2-part). If format is
+ * CHANNEL_NUMBER_FORMAT_1_PART, this will be ignored(0).
+ */
+ private final int mMajorChannelNumber;
+ /**
+ * 1-part Channel Number, or a Minor Channel Number (if Channel Number Format is 2-part).
+ */
+ private final int mMinorChannelNumber;
+
+ private ChannelIdentifier(int format, int majorNumber, int minorNumer) {
+ mChannelNumberFormat = format;
+ mMajorChannelNumber = majorNumber;
+ mMinorChannelNumber = minorNumer;
+ }
+
+ private void toByteArray(byte[] data, int index) {
+ // The first 6 bits for format, the 10 bits for major number.
+ data[index] = (byte) (((mChannelNumberFormat << 2) | (mMajorChannelNumber >>> 8) & 0x3));
+ data[index + 1] = (byte) (mMajorChannelNumber & 0xFF);
+ // Minor number uses the next 16 bits.
+ shortToByteArray((short) mMinorChannelNumber, data, index + 2);
+ }
+ }
+
+ /**
+ * Digital channel id.
+ * <p>
+ * It consists of the following fields
+ * <ul>
+ * <li>channel number format: 6bits
+ * <li>major number: 10bits
+ * <li>minor number: 16bits
+ * <li>reserved: 2bytes
+ * </ul>
+ * @hide
+ */
+ public static final class DigitalChannelData implements DigitalServiceIdentification {
+ /** Identifies the logical or virtual channel number of a service. */
+ private ChannelIdentifier mChannelIdentifier;
+
+ public static DigitalChannelData ofTwoNumbers(int majorNumber, int minorNumber) {
+ return new DigitalChannelData(
+ new ChannelIdentifier(CHANNEL_NUMBER_FORMAT_2_PART, majorNumber, minorNumber));
+ }
+
+ public static DigitalChannelData ofOneNumber(int number) {
+ return new DigitalChannelData(
+ new ChannelIdentifier(CHANNEL_NUMBER_FORMAT_1_PART, 0, number));
+ }
+
+ private DigitalChannelData(ChannelIdentifier id) {
+ mChannelIdentifier = id;
+ }
+
+ @Override
+ public void toByteArray(byte[] data, int index) {
+ mChannelIdentifier.toByteArray(data, index);
+ // The last 2 bytes is reserved for future use.
+ data[index + 4] = 0;
+ data[index + 5] = 0;
+ }
+ }
+
+ /**
+ * Create {@link DigitalServiceSource} with channel type.
+ *
+ * @param broadcastSystem digital broadcast system. It should be one of
+ * <ul>
+ * <li>{@link #DIGITAL_BROADCAST_TYPE_ARIB}
+ * <li>{@link #DIGITAL_BROADCAST_TYPE_ATSC}
+ * <li>{@link #DIGITAL_BROADCAST_TYPE_DVB}
+ * <li>{@link #DIGITAL_BROADCAST_TYPE_ARIB_BS}
+ * <li>{@link #DIGITAL_BROADCAST_TYPE_ARIB_CS}
+ * <li>{@link #DIGITAL_BROADCAST_TYPE_ARIB_T}
+ * <li>{@link #DIGITAL_BROADCAST_TYPE_ATSC_CABLE}
+ * <li>{@link #DIGITAL_BROADCAST_TYPE_ATSC_SATELLITE}
+ * <li>{@link #DIGITAL_BROADCAST_TYPE_ATSC_TERRESTRIAL}
+ * <li>{@link #DIGITAL_BROADCAST_TYPE_DVB_C}
+ * <li>{@link #DIGITAL_BROADCAST_TYPE_DVB_S}
+ * <li>{@link #DIGITAL_BROADCAST_TYPE_DVB_S2}
+ * <li>{@link #DIGITAL_BROADCAST_TYPE_DVB_T}
+ * </ul>
+ * @hide
+ */
+ public static DigitalServiceSource ofDigitalChannelId(int broadcastSystem,
+ DigitalChannelData data) {
+ if (data == null) {
+ throw new IllegalArgumentException("data should not be null.");
+ }
+ switch (broadcastSystem) {
+ case DIGITAL_BROADCAST_TYPE_ARIB:
+ case DIGITAL_BROADCAST_TYPE_ATSC:
+ case DIGITAL_BROADCAST_TYPE_DVB:
+ case DIGITAL_BROADCAST_TYPE_ARIB_BS:
+ case DIGITAL_BROADCAST_TYPE_ARIB_CS:
+ case DIGITAL_BROADCAST_TYPE_ARIB_T:
+ case DIGITAL_BROADCAST_TYPE_ATSC_CABLE:
+ case DIGITAL_BROADCAST_TYPE_ATSC_SATELLITE:
+ case DIGITAL_BROADCAST_TYPE_ATSC_TERRESTRIAL:
+ case DIGITAL_BROADCAST_TYPE_DVB_C:
+ case DIGITAL_BROADCAST_TYPE_DVB_S:
+ case DIGITAL_BROADCAST_TYPE_DVB_S2:
+ case DIGITAL_BROADCAST_TYPE_DVB_T:
+ return new DigitalServiceSource(
+ DigitalServiceSource.DIGITAL_SERVICE_IDENTIFIED_BY_CHANNEL,
+ broadcastSystem,
+ data);
+ default:
+ Log.w(TAG, "Invalid broadcast type:" + broadcastSystem);
+ throw new IllegalArgumentException(
+ "Invalid broadcast system value:" + broadcastSystem);
+ }
+ }
+
+ /**
+ * Create {@link DigitalServiceSource} of ARIB type.
+ *
+ * @param aribType ARIB type. It should be one of
+ * <ul>
+ * <li>{@link #DIGITAL_BROADCAST_TYPE_ARIB}
+ * <li>{@link #DIGITAL_BROADCAST_TYPE_ARIB_BS}
+ * <li>{@link #DIGITAL_BROADCAST_TYPE_ARIB_CS}
+ * <li>{@link #DIGITAL_BROADCAST_TYPE_ARIB_T}
+ * </ul>
+ * @hide
+ */
+ @Nullable
+ public static DigitalServiceSource ofArib(int aribType, AribData data) {
+ if (data == null) {
+ throw new IllegalArgumentException("data should not be null.");
+ }
+ switch (aribType) {
+ case DIGITAL_BROADCAST_TYPE_ARIB:
+ case DIGITAL_BROADCAST_TYPE_ARIB_BS:
+ case DIGITAL_BROADCAST_TYPE_ARIB_CS:
+ case DIGITAL_BROADCAST_TYPE_ARIB_T:
+ return new DigitalServiceSource(
+ DigitalServiceSource.DIGITAL_SERVICE_IDENTIFIED_BY_DIGITAL_ID,
+ aribType, data);
+ default:
+ Log.w(TAG, "Invalid ARIB type:" + aribType);
+ throw new IllegalArgumentException("type should not be null.");
+ }
+ }
+
+ /**
+ * Create {@link DigitalServiceSource} of ATSC type.
+ *
+ * @param atscType ATSC type. It should be one of
+ * <ul>
+ * <li>{@link #DIGITAL_BROADCAST_TYPE_ATSC}
+ * <li>{@link #DIGITAL_BROADCAST_TYPE_ATSC_CABLE}
+ * <li>{@link #DIGITAL_BROADCAST_TYPE_ATSC_SATELLITE}
+ * <li>{@link #DIGITAL_BROADCAST_TYPE_ATSC_TERRESTRIAL}
+ * </ul>
+ * @hide
+ */
+ @Nullable
+ public static DigitalServiceSource ofAtsc(int atscType, AtscData data) {
+ if (data == null) {
+ throw new IllegalArgumentException("data should not be null.");
+ }
+ switch (atscType) {
+ case DIGITAL_BROADCAST_TYPE_ATSC:
+ case DIGITAL_BROADCAST_TYPE_ATSC_CABLE:
+ case DIGITAL_BROADCAST_TYPE_ATSC_SATELLITE:
+ case DIGITAL_BROADCAST_TYPE_ATSC_TERRESTRIAL:
+ return new DigitalServiceSource(
+ DigitalServiceSource.DIGITAL_SERVICE_IDENTIFIED_BY_DIGITAL_ID,
+ atscType, data);
+ default:
+ Log.w(TAG, "Invalid ATSC type:" + atscType);
+ throw new IllegalArgumentException("Invalid ATSC type:" + atscType);
+ }
+ }
+
+ /**
+ * Create {@link DigitalServiceSource} of ATSC type.
+ *
+ * @param dvbType DVB type. It should be one of
+ * <ul>
+ * <li>{@link #DIGITAL_BROADCAST_TYPE_DVB}
+ * <li>{@link #DIGITAL_BROADCAST_TYPE_DVB_C}
+ * <li>{@link #DIGITAL_BROADCAST_TYPE_DVB_S}
+ * <li>{@link #DIGITAL_BROADCAST_TYPE_DVB_S2}
+ * <li>{@link #DIGITAL_BROADCAST_TYPE_DVB_T}
+ * </ul>
+ * @hide
+ */
+ @Nullable
+ public static DigitalServiceSource ofDvb(int dvbType, DvbData data) {
+ if (data == null) {
+ throw new IllegalArgumentException("data should not be null.");
+ }
+ switch (dvbType) {
+ case DIGITAL_BROADCAST_TYPE_DVB:
+ case DIGITAL_BROADCAST_TYPE_DVB_C:
+ case DIGITAL_BROADCAST_TYPE_DVB_S:
+ case DIGITAL_BROADCAST_TYPE_DVB_S2:
+ case DIGITAL_BROADCAST_TYPE_DVB_T:
+ return new DigitalServiceSource(
+ DigitalServiceSource.DIGITAL_SERVICE_IDENTIFIED_BY_DIGITAL_ID,
+ dvbType, data);
+ default:
+ Log.w(TAG, "Invalid DVB type:" + dvbType);
+ throw new IllegalArgumentException("Invalid DVB type:" + dvbType);
+ }
+ }
+
+ /**
+ * Record source container for "Digital Service".
+ * <ul>
+ * <li>[Record Source Type] - 1 byte
+ * <li>[Digital Identification] - 7 bytes
+ * </ul>
+ * @hide
+ */
+ public static final class DigitalServiceSource extends RecordSource {
+ /** Indicates that a service is identified by digital service IDs. */
+ private static final int DIGITAL_SERVICE_IDENTIFIED_BY_DIGITAL_ID = 0;
+ /** Indicates that a service is identified by a logical or virtual channel number. */
+ private static final int DIGITAL_SERVICE_IDENTIFIED_BY_CHANNEL = 1;
+
+ private static final int EXTRA_DATA_SIZE = 7;
+
+ /**
+ * Type of identification. It should be one of DIGITAL_SERVICE_IDENTIFIED_BY_DIGITAL_ID and
+ * DIGITAL_SERVICE_IDENTIFIED_BY_CHANNEL
+ */
+ private final int mIdentificationMethod;
+ /**
+ * Indicates the Digital Broadcast System of required service. This is present irrespective
+ * of the state of [Service Identification Method].
+ */
+ private final int mBroadcastSystem;
+
+ /**
+ * Extra parameter for digital service identification.
+ */
+ private final DigitalServiceIdentification mIdentification;
+
+ private DigitalServiceSource(int identificatinoMethod, int broadcastSystem,
+ DigitalServiceIdentification identification) {
+ super(RECORD_SOURCE_TYPE_DIGITAL_SERVICE, EXTRA_DATA_SIZE);
+ mIdentificationMethod = identificatinoMethod;
+ mBroadcastSystem = broadcastSystem;
+ mIdentification = identification;
+ }
+
+ @Override
+ int extraParamToByteArray(byte[] data, int index) {
+ data[index] = (byte) ((mIdentificationMethod << 7) | (mBroadcastSystem & 0x7F));
+ mIdentification.toByteArray(data, index + 1);
+ return EXTRA_DATA_SIZE;
+
+ }
+ }
+
+
+ // ---------------------------------------------------------------------------------------------
+ // ---- Analogue service data ------------------------------------------------------------------
+ // ---------------------------------------------------------------------------------------------
+ /**
+ * Analogue broadcast types.
+ */
+ /** @hide */
+ public static final int ANALOGUE_BROADCAST_TYPE_CABLE = 0x0;
+ /** @hide */
+ public static final int ANALOGUE_BROADCAST_TYPE_SATELLITE = 0x1;
+ /** @hide */
+ public static final int ANALOGUE_BROADCAST_TYPE_TERRESTRIAL = 0x2;
+
+ /**
+ * Broadcast system values.
+ */
+ /** @hide */
+ public static final int BROADCAST_SYSTEM_PAL_BG = 0;
+ /** @hide */
+ public static final int BROADCAST_SYSTEM_SECAM_LP = 1;
+ /** @hide */
+ public static final int BROADCAST_SYSTEM_PAL_M = 2;
+ /** @hide */
+ public static final int BROADCAST_SYSTEM_NTSC_M = 3;
+ /** @hide */
+ public static final int BROADCAST_SYSTEM_PAL_I = 4;
+ /** @hide */
+ public static final int BROADCAST_SYSTEM_SECAM_DK = 5;
+ /** @hide */
+ public static final int BROADCAST_SYSTEM_SECAM_BG = 6;
+ /** @hide */
+ public static final int BROADCAST_SYSTEM_SECAM_L = 7;
+ /** @hide */
+ public static final int BROADCAST_SYSTEM_PAL_DK = 8;
+ /** @hide */
+ public static final int BROADCAST_SYSTEM_PAL_OTHER_SYSTEM = 31;
+
+ /**
+ * Create {@link AnalogueServiceSource} of analogue service.
+ *
+ * @param broadcastType
+ * @param frequency
+ * @param broadcastSystem
+ * @hide
+ */
+ @Nullable
+ public static AnalogueServiceSource ofAnalogue(int broadcastType, int frequency,
+ int broadcastSystem){
+ if (broadcastType < ANALOGUE_BROADCAST_TYPE_CABLE
+ || broadcastType > ANALOGUE_BROADCAST_TYPE_TERRESTRIAL) {
+ Log.w(TAG, "Invalid Broadcast type:" + broadcastType);
+ throw new IllegalArgumentException("Invalid Broadcast type:" + broadcastType);
+ }
+ if (frequency < 0 || frequency > 0xFFFF) {
+ Log.w(TAG, "Invalid frequency value[0x0000-0xFFFF]:" + frequency);
+ throw new IllegalArgumentException(
+ "Invalid frequency value[0x0000-0xFFFF]:" + frequency);
+ }
+ if (broadcastSystem < BROADCAST_SYSTEM_PAL_BG
+ || broadcastSystem > BROADCAST_SYSTEM_PAL_OTHER_SYSTEM) {
+
+ Log.w(TAG, "Invalid Broadcast system:" + broadcastSystem);
+ throw new IllegalArgumentException(
+ "Invalid Broadcast system:" + broadcastSystem);
+ }
+
+ return new AnalogueServiceSource(broadcastType, frequency, broadcastSystem);
+ }
+
+ /**
+ * Record source for analogue service data. It consists of
+ * <ul>
+ * <li>[Record Source Type] - 1 byte
+ * <li>[Analogue Broadcast Type] - 1 byte
+ * <li>[Analogue Frequency] - 2 bytes
+ * <li>[Broadcast System] - 1 byte
+ * </ul>
+ * @hide
+ */
+ public static final class AnalogueServiceSource extends RecordSource {
+ private static final int EXTRA_DATA_SIZE = 4;
+
+ /** Indicates the Analogue broadcast type. */
+ private final int mBroadcastType;
+ /** Used to specify the frequency used by an analogue tuner. 0x0000<N<0xFFFF. */
+ private final int mFrequency;
+ /**
+ * This specifies information about the color system, the sound carrier and the
+ * IF-frequency.
+ */
+ private final int mBroadcastSystem;
+
+ private AnalogueServiceSource(int broadcastType, int frequency, int broadcastSystem) {
+ super(RECORD_SOURCE_TYPE_ANALOGUE_SERVICE, EXTRA_DATA_SIZE);
+ mBroadcastType = broadcastType;
+ mFrequency = frequency;
+ mBroadcastSystem = broadcastSystem;
+ }
+
+ @Override
+ protected int extraParamToByteArray(byte[] data, int index) {
+ // [Analogue Broadcast Type] - 1 byte
+ data[index] = (byte) mBroadcastType;
+ // [Analogue Frequency] - 2 bytes
+ shortToByteArray((short) mFrequency, data, index + 1);
+ // [Broadcast System] - 1 byte
+ data[index + 3] = (byte) mBroadcastSystem;
+ return EXTRA_DATA_SIZE;
+ }
+ }
+
+
+ // ---------------------------------------------------------------------------------------------
+ // ---- External plug data ---------------------------------------------------------------------
+ // ---------------------------------------------------------------------------------------------
+ /**
+ * Create {@link ExternalPlugData} of external plug type.
+ *
+ * @param plugNumber plug number. It should be in range of [1, 255]
+ * @hide
+ */
+ public static ExternalPlugData ofExternalPlug(int plugNumber) {
+ if (plugNumber < 1 || plugNumber > 255) {
+ Log.w(TAG, "Invalid plug number[1-255]" + plugNumber);
+ throw new IllegalArgumentException("Invalid plug number[1-255]" + plugNumber);
+ }
+ return new ExternalPlugData(plugNumber);
+ }
+
+ /**
+ * Record source for external plug (external non-HDMI device connect) type.
+ * <ul>
+ * <li>[Record Source Type] - 1 byte
+ * <li>[External Plug] - 1 byte
+ * </ul>
+ * @hide
+ */
+ public static final class ExternalPlugData extends RecordSource {
+ private static final int EXTRA_DATA_SIZE = 1;
+
+ /** External Plug number on the Recording Device. */
+ private final int mPlugNumber;
+
+ private ExternalPlugData(int plugNumber) {
+ super(RECORD_SOURCE_TYPE_EXTERNAL_PLUG, EXTRA_DATA_SIZE);
+ mPlugNumber = plugNumber;
+ }
+
+ @Override
+ int extraParamToByteArray(byte[] data, int index) {
+ data[index] = (byte) mPlugNumber;
+ return EXTRA_DATA_SIZE;
+ }
+ }
+
+ // ---------------------------------------------------------------------------------------------
+ // ---- External physical address --------------------------------------------------------------
+ // ---------------------------------------------------------------------------------------------
+ /**
+ * Create {@link ExternalPhysicalAddress} of external physical address.
+ *
+ * @param physicalAddress
+ * @hide
+ */
+ public static ExternalPhysicalAddress ofExternalPhysicalAddress(int physicalAddress) {
+ if ((physicalAddress & ~0xFFFF) != 0) {
+ Log.w(TAG, "Invalid physical address:" + physicalAddress);
+ throw new IllegalArgumentException("Invalid physical address:" + physicalAddress);
+ }
+
+ return new ExternalPhysicalAddress(physicalAddress);
+ }
+
+ /**
+ * Record source for external physical address.
+ * <ul>
+ * <li>[Record Source Type] - 1 byte
+ * <li>[Physical address] - 2 byte
+ * </ul>
+ * @hide
+ */
+ public static final class ExternalPhysicalAddress extends RecordSource {
+ private static final int EXTRA_DATA_SIZE = 2;
+
+ private final int mPhysicalAddress;
+
+ private ExternalPhysicalAddress(int physicalAddress) {
+ super(RECORD_SOURCE_TYPE_EXTERNAL_PHYSICAL_ADDRESS, EXTRA_DATA_SIZE);
+ mPhysicalAddress = physicalAddress;
+ }
+
+ @Override
+ int extraParamToByteArray(byte[] data, int index) {
+ shortToByteArray((short) mPhysicalAddress, data, index);
+ return EXTRA_DATA_SIZE;
+ }
+ }
+
+
+ // ---------------------------------------------------------------------------------------------
+ // ------- Helper methods ----------------------------------------------------------------------
+ // ---------------------------------------------------------------------------------------------
+ private static int threeFieldsToSixBytes(int first, int second, int third, byte[] data,
+ int index) {
+ shortToByteArray((short) first, data, index);
+ shortToByteArray((short) second, data, index + 2);
+ shortToByteArray((short) third, data, index + 4);
+ return 6;
+ }
+
+ private static int shortToByteArray(short value, byte[] byteArray, int index) {
+ byteArray[index] = (byte) ((value >>> 8) & 0xFF);
+ byteArray[index + 1] = (byte) (value & 0xFF);
+ return 2;
+ }
+}
diff --git a/core/java/android/hardware/hdmi/HdmiTvClient.java b/core/java/android/hardware/hdmi/HdmiTvClient.java
index 1285ccb..6d64a1d 100644
--- a/core/java/android/hardware/hdmi/HdmiTvClient.java
+++ b/core/java/android/hardware/hdmi/HdmiTvClient.java
@@ -16,11 +16,11 @@
package android.hardware.hdmi;
import android.annotation.SystemApi;
-import android.hardware.hdmi.HdmiControlManager.VendorCommandListener;
-import android.hardware.hdmi.IHdmiVendorCommandListener;
import android.os.RemoteException;
import android.util.Log;
+import libcore.util.EmptyArray;
+
/**
* HdmiTvClient represents HDMI-CEC logical device of type TV in the Android system
* which acts as TV/Display. It provides with methods that manage, interact with other
@@ -91,6 +91,7 @@ public final class HdmiTvClient extends HdmiClient {
return new HdmiTvClient(service);
}
+ @Override
public int getDeviceType() {
return HdmiCecDeviceInfo.DEVICE_TV;
}
@@ -150,6 +151,51 @@ public final class HdmiTvClient extends HdmiClient {
}
}
+ /**
+ * Callback interface to used to get notified when a record request from recorder device.
+ */
+ public interface RecordRequestListener {
+ /**
+ * Called when tv receives request request from recorder device. When it's called,
+ * it should return record source in byte array so that hdmi control service
+ * can start recording with the given source info.
+ *
+ * @return {@link HdmiRecordSources} to be used to set recording info
+ */
+ HdmiRecordSources.RecordSource onRecordRequestReceived(int recorderAddress);
+ }
+
+ /**
+ * Set {@link RecordRequestListener} to hdmi control service.
+ */
+ public void setRecordRequestListener(RecordRequestListener listener) {
+ try {
+ mService.setRecordRequestListener(getCallbackWrapper(listener));
+ } catch (RemoteException e) {
+ Log.e(TAG, "failed to set record request listener: ", e);
+ }
+ }
+
+ /**
+ * Start recording with the given recorder address and recorder source.
+ * <p>Usage
+ * <pre>
+ * HdmiTvClient tvClient = ....;
+ * // for own source.
+ * OwnSource ownSource = ownHdmiRecordSources.ownSource();
+ * tvClient.startRecord(recorderAddress, ownSource);
+ * </pre>
+ */
+ public void startRecord(int recorderAddress, HdmiRecordSources.RecordSource source) {
+ try {
+ byte[] data = new byte[source.getDataSize(true)];
+ source.toByteArray(true, data, 0);
+ mService.startRecord(recorderAddress, data);
+ } catch (RemoteException e) {
+ Log.e(TAG, "failed to start record: ", e);
+ }
+ }
+
private static IHdmiControlCallback getCallbackWrapper(final SelectCallback callback) {
return new IHdmiControlCallback.Stub() {
@Override
@@ -158,4 +204,21 @@ public final class HdmiTvClient extends HdmiClient {
}
};
}
+
+ private static IHdmiRecordRequestListener getCallbackWrapper(
+ final RecordRequestListener listener) {
+ return new IHdmiRecordRequestListener.Stub() {
+ @Override
+ public byte[] onRecordRequestReceived(int recorderAddress) throws RemoteException {
+ HdmiRecordSources.RecordSource source =
+ listener.onRecordRequestReceived(recorderAddress);
+ if (source == null) {
+ return EmptyArray.BYTE;
+ }
+ byte[] data = new byte[source.getDataSize(true)];
+ source.toByteArray(true, data, 0);
+ return data;
+ }
+ };
+ }
}
diff --git a/core/java/android/hardware/hdmi/IHdmiControlService.aidl b/core/java/android/hardware/hdmi/IHdmiControlService.aidl
index f3931e3..6f3763b 100644
--- a/core/java/android/hardware/hdmi/IHdmiControlService.aidl
+++ b/core/java/android/hardware/hdmi/IHdmiControlService.aidl
@@ -22,6 +22,7 @@ import android.hardware.hdmi.IHdmiControlCallback;
import android.hardware.hdmi.IHdmiDeviceEventListener;
import android.hardware.hdmi.IHdmiHotplugEventListener;
import android.hardware.hdmi.IHdmiInputChangeListener;
+import android.hardware.hdmi.IHdmiRecordRequestListener;
import android.hardware.hdmi.IHdmiSystemAudioModeChangeListener;
import android.hardware.hdmi.IHdmiVendorCommandListener;
@@ -61,4 +62,6 @@ interface IHdmiControlService {
void sendVendorCommand(int deviceType, int targetAddress, in byte[] params,
boolean hasVendorId);
void addVendorCommandListener(IHdmiVendorCommandListener listener, int deviceType);
+ void setRecordRequestListener(IHdmiRecordRequestListener listener);
+ void startRecord(int recorderAddress, in byte[] recordSource);
}
diff --git a/core/java/android/hardware/hdmi/IHdmiRecordRequestListener.aidl b/core/java/android/hardware/hdmi/IHdmiRecordRequestListener.aidl
new file mode 100644
index 0000000..f8f9e5f
--- /dev/null
+++ b/core/java/android/hardware/hdmi/IHdmiRecordRequestListener.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.hdmi;
+
+/**
+ * Callback interface definition for HDMI client to fill record source info
+ * when it gets record start request.
+ *
+ * @hide
+ */
+interface IHdmiRecordRequestListener {
+ byte[] onRecordRequestReceived(int recorderAddress);
+} \ No newline at end of file
diff --git a/services/core/java/com/android/server/hdmi/Constants.java b/services/core/java/com/android/server/hdmi/Constants.java
index 384cd4a..85c7747 100644
--- a/services/core/java/com/android/server/hdmi/Constants.java
+++ b/services/core/java/com/android/server/hdmi/Constants.java
@@ -206,5 +206,10 @@ final class Constants {
static final String PROPERTY_PREFERRED_ADDRESS_PLAYBACK = "hdmi_cec.prefaddr.playback";
static final String PROPERTY_PREFERRED_ADDRESS_TV = "hdmi_cec.prefaddr.tv";
+ static final int RECORDING_TYPE_DIGITAL_RF = 1;
+ static final int RECORDING_TYPE_ANALOGUE_RF = 2;
+ static final int RECORDING_TYPE_EXTERNAL_PHYSICAL_ADDRESS = 3;
+ static final int RECORDING_TYPE_OWN_SOURCE = 4;
+
private Constants() { /* cannot be instantiated */ }
}
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 0239c83..560ee84 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -32,6 +32,7 @@ import android.hardware.hdmi.IHdmiControlService;
import android.hardware.hdmi.IHdmiDeviceEventListener;
import android.hardware.hdmi.IHdmiHotplugEventListener;
import android.hardware.hdmi.IHdmiInputChangeListener;
+import android.hardware.hdmi.IHdmiRecordRequestListener;
import android.hardware.hdmi.IHdmiSystemAudioModeChangeListener;
import android.hardware.hdmi.IHdmiVendorCommandListener;
import android.media.AudioManager;
@@ -1010,6 +1011,16 @@ public final class HdmiControlService extends SystemService {
}
});
}
+
+ @Override
+ public void setRecordRequestListener(IHdmiRecordRequestListener listener) {
+ // TODO: implement this.
+ }
+
+ @Override
+ public void startRecord(int recorderAddress, byte[] recordSource) {
+ // TODO: implement this.
+ }
}
@ServiceThreadOnly
diff --git a/services/core/java/com/android/server/hdmi/OneTouchRecordAction.java b/services/core/java/com/android/server/hdmi/OneTouchRecordAction.java
index 7646027..51aa984 100644
--- a/services/core/java/com/android/server/hdmi/OneTouchRecordAction.java
+++ b/services/core/java/com/android/server/hdmi/OneTouchRecordAction.java
@@ -16,16 +16,23 @@
package com.android.server.hdmi;
+import static com.android.server.hdmi.Constants.RECORDING_TYPE_ANALOGUE_RF;
+import static com.android.server.hdmi.Constants.RECORDING_TYPE_DIGITAL_RF;
+import static com.android.server.hdmi.Constants.RECORDING_TYPE_EXTERNAL_PHYSICAL_ADDRESS;
+import static com.android.server.hdmi.Constants.RECORDING_TYPE_OWN_SOURCE;
+
/**
- * Feature action that performs one touch record.
- * This class only provides a skeleton of one touch play and has no detail implementaion.
+ * Feature action that performs one touch record. This class only provides a skeleton of one touch
+ * play and has no detail implementation.
*/
public class OneTouchRecordAction extends FeatureAction {
private final int mRecorderAddress;
+ private final int mRecordingType;
- OneTouchRecordAction(HdmiCecLocalDevice source, int recorderAddress) {
+ OneTouchRecordAction(HdmiCecLocalDevice source, int recorderAddress, int recordingType) {
super(source);
mRecorderAddress = recorderAddress;
+ mRecordingType = recordingType;
}
@Override
@@ -33,6 +40,20 @@ public class OneTouchRecordAction extends FeatureAction {
return false;
}
+ private void sendRecordOn(int recordingType) {
+ switch (recordingType) {
+ case RECORDING_TYPE_DIGITAL_RF:
+ break;
+ case RECORDING_TYPE_ANALOGUE_RF:
+ break;
+ case RECORDING_TYPE_EXTERNAL_PHYSICAL_ADDRESS:
+ break;
+ case RECORDING_TYPE_OWN_SOURCE:
+ break;
+ // TODO: implement this.
+ }
+ }
+
@Override
boolean processCommand(HdmiCecMessage cmd) {
return false;