diff options
8 files changed, 879 insertions, 5 deletions
@@ -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; |