/*
 * 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 static android.hardware.hdmi.HdmiControlManager.TIMER_RECORDING_TYPE_ANALOGUE;
import static android.hardware.hdmi.HdmiControlManager.TIMER_RECORDING_TYPE_DIGITAL;
import static android.hardware.hdmi.HdmiControlManager.TIMER_RECORDING_TYPE_EXTERNAL;

import android.annotation.SystemApi;
import android.hardware.hdmi.HdmiRecordSources.AnalogueServiceSource;
import android.hardware.hdmi.HdmiRecordSources.DigitalServiceSource;
import android.hardware.hdmi.HdmiRecordSources.ExternalPhysicalAddress;
import android.hardware.hdmi.HdmiRecordSources.ExternalPlugData;
import android.hardware.hdmi.HdmiRecordSources.RecordSource;
import android.util.Log;

Container for timer record source used for timer recording. Timer source consists of two parts, timer info and record source.

Timer info contains all timing information used for recording. It consists of the following values.

  • [Day of Month]
  • [Month of Year]
  • [Start Time]
  • [Duration]
  • [Recording Sequence]

Record source containers all program information used for recording. For more details, look at HdmiRecordSources.

Usage

TimeOrDuration startTime = HdmiTimerRecordSources.ofTime(18, 00);  // 6PM.
TimeOrDuration duration = HdmiTimerRecordSource.ofDuration(1, 00);  // 1 hour duration.
// For 1 hour from 6PM, August 10th every SaturDay and Sunday.
TimerInfo timerInfo = HdmiTimerRecordSource.timerInfoOf(10, 8, starTime, duration,
           HdmiTimerRecordSource.RECORDING_SEQUENCE_REPEAT_SATURDAY |
           HdmiTimerRecordSource.RECORDING_SEQUENCE_REPEAT_SUNDAY);
// create digital source.
DigitalServiceSource recordSource = HdmiRecordSource.ofDvb(...);
TimerRecordSource source = ofDigitalSource(timerInfo, recordSource);
@hide
/** * Container for timer record source used for timer recording. Timer source consists of two parts, * timer info and record source. * <p> * Timer info contains all timing information used for recording. It consists of the following * values. * <ul> * <li>[Day of Month] * <li>[Month of Year] * <li>[Start Time] * <li>[Duration] * <li>[Recording Sequence] * </ul> * <p> * Record source containers all program information used for recording. * For more details, look at {@link HdmiRecordSources}. * <p> * Usage * <pre> * TimeOrDuration startTime = HdmiTimerRecordSources.ofTime(18, 00); // 6PM. * TimeOrDuration duration = HdmiTimerRecordSource.ofDuration(1, 00); // 1 hour duration. * // For 1 hour from 6PM, August 10th every SaturDay and Sunday. * TimerInfo timerInfo = HdmiTimerRecordSource.timerInfoOf(10, 8, starTime, duration, * HdmiTimerRecordSource.RECORDING_SEQUENCE_REPEAT_SATURDAY | * HdmiTimerRecordSource.RECORDING_SEQUENCE_REPEAT_SUNDAY); * // create digital source. * DigitalServiceSource recordSource = HdmiRecordSource.ofDvb(...); * TimerRecordSource source = ofDigitalSource(timerInfo, recordSource); * </pre> * * @hide */
@SystemApi public class HdmiTimerRecordSources { private static final String TAG = "HdmiTimerRecordingSources"; private HdmiTimerRecordSources() {}
Creates TimerRecordSource for digital source which is used for <Set Digital Timer>.
Params:
  • timerInfo – timer info used for timer recording
  • source – digital source used for timer recording
Throws:
Returns:TimerRecordSource
/** * Creates {@link TimerRecordSource} for digital source which is used for &lt;Set Digital * Timer&gt;. * * @param timerInfo timer info used for timer recording * @param source digital source used for timer recording * @return {@link TimerRecordSource} * @throws IllegalArgumentException if {@code timerInfo} or {@code source} is null */
public static TimerRecordSource ofDigitalSource(TimerInfo timerInfo, DigitalServiceSource source) { checkTimerRecordSourceInputs(timerInfo, source); return new TimerRecordSource(timerInfo, source); }
Creates TimerRecordSource for analogue source which is used for <Set Analogue Timer>.
Params:
  • timerInfo – timer info used for timer recording
  • source – digital source used for timer recording
Throws:
Returns:TimerRecordSource
/** * Creates {@link TimerRecordSource} for analogue source which is used for &lt;Set Analogue * Timer&gt;. * * @param timerInfo timer info used for timer recording * @param source digital source used for timer recording * @return {@link TimerRecordSource} * @throws IllegalArgumentException if {@code timerInfo} or {@code source} is null */
public static TimerRecordSource ofAnalogueSource(TimerInfo timerInfo, AnalogueServiceSource source) { checkTimerRecordSourceInputs(timerInfo, source); return new TimerRecordSource(timerInfo, source); }
Creates TimerRecordSource for external plug which is used for <Set External Timer>.
Params:
  • timerInfo – timer info used for timer recording
  • source – digital source used for timer recording
Throws:
Returns:TimerRecordSource
/** * Creates {@link TimerRecordSource} for external plug which is used for &lt;Set External * Timer&gt;. * * @param timerInfo timer info used for timer recording * @param source digital source used for timer recording * @return {@link TimerRecordSource} * @throws IllegalArgumentException if {@code timerInfo} or {@code source} is null */
public static TimerRecordSource ofExternalPlug(TimerInfo timerInfo, ExternalPlugData source) { checkTimerRecordSourceInputs(timerInfo, source); return new TimerRecordSource(timerInfo, new ExternalSourceDecorator(source, EXTERNAL_SOURCE_SPECIFIER_EXTERNAL_PLUG)); }
Creates TimerRecordSource for external physical address which is used for <Set External Timer>.
Params:
  • timerInfo – timer info used for timer recording
  • source – digital source used for timer recording
Throws:
Returns:TimerRecordSource
/** * Creates {@link TimerRecordSource} for external physical address which is used for &lt;Set * External Timer&gt;. * * @param timerInfo timer info used for timer recording * @param source digital source used for timer recording * @return {@link TimerRecordSource} * @throws IllegalArgumentException if {@code timerInfo} or {@code source} is null */
public static TimerRecordSource ofExternalPhysicalAddress(TimerInfo timerInfo, ExternalPhysicalAddress source) { checkTimerRecordSourceInputs(timerInfo, source); return new TimerRecordSource(timerInfo, new ExternalSourceDecorator(source, EXTERNAL_SOURCE_SPECIFIER_EXTERNAL_PHYSICAL_ADDRESS)); } private static void checkTimerRecordSourceInputs(TimerInfo timerInfo, RecordSource source) { if (timerInfo == null) { Log.w(TAG, "TimerInfo should not be null."); throw new IllegalArgumentException("TimerInfo should not be null."); } if (source == null) { Log.w(TAG, "source should not be null."); throw new IllegalArgumentException("source should not be null."); } }
Creates Duration for time value.
Params:
  • hour – hour in range of [0, 23]
  • minute – minute in range of [0, 60]
Throws:
Returns:Duration
/** * Creates {@link Duration} for time value. * * @param hour hour in range of [0, 23] * @param minute minute in range of [0, 60] * @return {@link Duration} * @throws IllegalArgumentException if hour or minute is out of range */
public static Time timeOf(int hour, int minute) { checkTimeValue(hour, minute); return new Time(hour, minute); } private static void checkTimeValue(int hour, int minute) { if (hour < 0 || hour > 23) { throw new IllegalArgumentException("Hour should be in rage of [0, 23]:" + hour); } if (minute < 0 || minute > 59) { throw new IllegalArgumentException("Minute should be in rage of [0, 59]:" + minute); } }
Creates Duration for duration value.
Params:
  • hour – hour in range of [0, 99]
  • minute – minute in range of [0, 59]
Throws:
Returns:Duration
/** * Creates {@link Duration} for duration value. * * @param hour hour in range of [0, 99] * @param minute minute in range of [0, 59] * @return {@link Duration} * @throws IllegalArgumentException if hour or minute is out of range */
public static Duration durationOf(int hour, int minute) { checkDurationValue(hour, minute); return new Duration(hour, minute); } private static void checkDurationValue(int hour, int minute) { if (hour < 0 || hour > 99) { throw new IllegalArgumentException("Hour should be in rage of [0, 99]:" + hour); } if (minute < 0 || minute > 59) { throw new IllegalArgumentException("minute should be in rage of [0, 59]:" + minute); } }
Base class for time-related information.
@hide
/** * Base class for time-related information. * @hide */
/* package */ static class TimeUnit { /* package */ final int mHour; /* package */ final int mMinute; /* package */ TimeUnit(int hour, int minute) { mHour = hour; mMinute = minute; } /* package */ int toByteArray(byte[] data, int index) { data[index] = toBcdByte(mHour); data[index + 1] = toBcdByte(mMinute); return 2; } /* package */ static byte toBcdByte(int value) { int digitOfTen = (value / 10) % 10; int digitOfOne = value % 10; return (byte) ((digitOfTen << 4) | digitOfOne); } }
Place holder for time value.
@hide
/** * Place holder for time value. * @hide */
@SystemApi public static final class Time extends TimeUnit { private Time(int hour, int minute) { super(hour, minute); } }
Place holder for duration value.
@hide
/** * Place holder for duration value. * @hide */
@SystemApi public static final class Duration extends TimeUnit { private Duration(int hour, int minute) { super(hour, minute); } }
Fields for recording sequence. The following can be merged by OR(|) operation.
/** * Fields for recording sequence. * The following can be merged by OR(|) operation. */
public static final int RECORDING_SEQUENCE_REPEAT_ONCE_ONLY = 0; public static final int RECORDING_SEQUENCE_REPEAT_SUNDAY = 1 << 0; public static final int RECORDING_SEQUENCE_REPEAT_MONDAY = 1 << 1; public static final int RECORDING_SEQUENCE_REPEAT_TUESDAY = 1 << 2; public static final int RECORDING_SEQUENCE_REPEAT_WEDNESDAY = 1 << 3; public static final int RECORDING_SEQUENCE_REPEAT_THURSDAY = 1 << 4; public static final int RECORDING_SEQUENCE_REPEAT_FRIDAY = 1 << 5; public static final int RECORDING_SEQUENCE_REPEAT_SATUREDAY = 1 << 6; private static final int RECORDING_SEQUENCE_REPEAT_MASK = (RECORDING_SEQUENCE_REPEAT_SUNDAY | RECORDING_SEQUENCE_REPEAT_MONDAY | RECORDING_SEQUENCE_REPEAT_TUESDAY | RECORDING_SEQUENCE_REPEAT_WEDNESDAY | RECORDING_SEQUENCE_REPEAT_THURSDAY | RECORDING_SEQUENCE_REPEAT_FRIDAY | RECORDING_SEQUENCE_REPEAT_SATUREDAY);
Creates TimerInfo with the given information.
Params:
Throws:
Returns:TimerInfo.
/** * Creates {@link TimerInfo} with the given information. * * @param dayOfMonth day of month * @param monthOfYear month of year * @param startTime start time in {@link Time} * @param duration duration in {@link Duration} * @param recordingSequence recording sequence. Use RECORDING_SEQUENCE_REPEAT_ONCE_ONLY for no * repeat. Otherwise use combination of {@link #RECORDING_SEQUENCE_REPEAT_SUNDAY}, * {@link #RECORDING_SEQUENCE_REPEAT_MONDAY}, * {@link #RECORDING_SEQUENCE_REPEAT_TUESDAY}, * {@link #RECORDING_SEQUENCE_REPEAT_WEDNESDAY}, * {@link #RECORDING_SEQUENCE_REPEAT_THURSDAY}, * {@link #RECORDING_SEQUENCE_REPEAT_FRIDAY}, * {@link #RECORDING_SEQUENCE_REPEAT_SATUREDAY}. * @return {@link TimerInfo}. * @throws IllegalArgumentException if input value is invalid */
public static TimerInfo timerInfoOf(int dayOfMonth, int monthOfYear, Time startTime, Duration duration, int recordingSequence) { if (dayOfMonth < 0 || dayOfMonth > 31) { throw new IllegalArgumentException( "Day of month should be in range of [0, 31]:" + dayOfMonth); } if (monthOfYear < 1 || monthOfYear > 12) { throw new IllegalArgumentException( "Month of year should be in range of [1, 12]:" + monthOfYear); } checkTimeValue(startTime.mHour, startTime.mMinute); checkDurationValue(duration.mHour, duration.mMinute); // Recording sequence should use least 7 bits or no bits. if ((recordingSequence != 0) && ((recordingSequence & ~RECORDING_SEQUENCE_REPEAT_MASK) != 0)) { throw new IllegalArgumentException( "Invalid reecording sequence value:" + recordingSequence); } return new TimerInfo(dayOfMonth, monthOfYear, startTime, duration, recordingSequence); }
Container basic timer information. It consists of the following fields.
  • [Day of Month]
  • [Month of Year]
  • [Start Time]
  • [Duration]
  • [Recording Sequence]
@hide
/** * Container basic timer information. It consists of the following fields. * <ul> * <li>[Day of Month] * <li>[Month of Year] * <li>[Start Time] * <li>[Duration] * <li>[Recording Sequence] * </ul> * @hide */
@SystemApi public static final class TimerInfo { private static final int DAY_OF_MONTH_SIZE = 1; private static final int MONTH_OF_YEAR_SIZE = 1; private static final int START_TIME_SIZE = 2; // 1byte for hour and 1byte for minute. private static final int DURATION_SIZE = 2; // 1byte for hour and 1byte for minute. private static final int RECORDING_SEQUENCE_SIZE = 1; private static final int BASIC_INFO_SIZE = DAY_OF_MONTH_SIZE + MONTH_OF_YEAR_SIZE + START_TIME_SIZE + DURATION_SIZE + RECORDING_SEQUENCE_SIZE;
Day of month.
/** Day of month. */
private final int mDayOfMonth;
Month of year.
/** Month of year. */
private final int mMonthOfYear;
Time of day. [Hour][Minute]. 0 <= Hour <= 24, 0 <= Minute <= 60 in BCD format.
/** * Time of day. * [Hour][Minute]. 0 &lt;= Hour &lt;= 24, 0 &lt;= Minute &lt;= 60 in BCD format. */
private final Time mStartTime;
Duration. [Hour][Minute]. 0 <= Hour <= 99, 0 <= Minute <= 60 in BCD format.
/** * Duration. [Hour][Minute]. * 0 &lt;= Hour &lt;= 99, 0 &lt;= Minute &lt;= 60 in BCD format. * */
private final Duration mDuration;
Indicates if recording is repeated and, if so, on which days. For repeated recordings, the recording sequence value is the bitwise OR of the days when recordings are required. [Recording Sequence] shall be set to 0x00 when the recording is not repeated. Bit 7 is reserved and shall be set to zero.
/** * Indicates if recording is repeated and, if so, on which days. For repeated recordings, * the recording sequence value is the bitwise OR of the days when recordings are required. * [Recording Sequence] shall be set to 0x00 when the recording is not repeated. Bit 7 is * reserved and shall be set to zero. */
private final int mRecordingSequence; private TimerInfo(int dayOfMonth, int monthOfYear, Time startTime, Duration duration, int recordingSequence) { mDayOfMonth = dayOfMonth; mMonthOfYear = monthOfYear; mStartTime = startTime; mDuration = duration; mRecordingSequence = recordingSequence; } int toByteArray(byte[] data, int index) { // [Day of Month] data[index] = (byte) mDayOfMonth; index += DAY_OF_MONTH_SIZE; // [Month of Year] data[index] = (byte) mMonthOfYear; index += MONTH_OF_YEAR_SIZE; // [Start Time] index += mStartTime.toByteArray(data, index); index += mDuration.toByteArray(data, index); // [Duration] // [Recording Sequence] data[index] = (byte) mRecordingSequence; return getDataSize(); } int getDataSize() { return BASIC_INFO_SIZE; } }
Record source container for timer record. This is used to set parameter for <Set Digital Timer>, <Set Analogue Timer>, and <Set External Timer> message.

In order to create this from each source type, use one of helper method.

  • ofDigitalSource for digital source
  • ofAnalogueSource for analogue source
  • ofExternalPlug for external plug type
  • ofExternalPhysicalAddress for external physical address type.
@hide
/** * Record source container for timer record. This is used to set parameter for &lt;Set Digital * Timer&gt;, &lt;Set Analogue Timer&gt;, and &lt;Set External Timer&gt; message. * <p> * In order to create this from each source type, use one of helper method. * <ul> * <li>{@link #ofDigitalSource} for digital source * <li>{@link #ofAnalogueSource} for analogue source * <li>{@link #ofExternalPlug} for external plug type * <li>{@link #ofExternalPhysicalAddress} for external physical address type. * </ul> * @hide */
@SystemApi public static final class TimerRecordSource { private final RecordSource mRecordSource; private final TimerInfo mTimerInfo; private TimerRecordSource(TimerInfo timerInfo, RecordSource recordSource) { mTimerInfo = timerInfo; mRecordSource = recordSource; } int getDataSize() { return mTimerInfo.getDataSize() + mRecordSource.getDataSize(false); } int toByteArray(byte[] data, int index) { // Basic infos including [Day of Month] [Month of Year] [Start Time] [Duration] // [Recording Sequence] index += mTimerInfo.toByteArray(data, index); // [Record Source] mRecordSource.toByteArray(false, data, index); return getDataSize(); } }
External source specifier types.
/** * External source specifier types. */
private static final int EXTERNAL_SOURCE_SPECIFIER_EXTERNAL_PLUG = 4; private static final int EXTERNAL_SOURCE_SPECIFIER_EXTERNAL_PHYSICAL_ADDRESS = 5;
Decorator for external source. Beside digital or analogue source, external source starts with [External Source Specifier] because it covers both external plug type and external specifier.
/** * Decorator for external source. Beside digital or analogue source, external source starts with * [External Source Specifier] because it covers both external plug type and external specifier. */
private static class ExternalSourceDecorator extends RecordSource { private final RecordSource mRecordSource; private final int mExternalSourceSpecifier; private ExternalSourceDecorator(RecordSource recordSource, int externalSourceSpecifier) { // External source has one byte field for [External Source Specifier]. super(recordSource.mSourceType, recordSource.getDataSize(false) + 1); mRecordSource = recordSource; mExternalSourceSpecifier = externalSourceSpecifier; } @Override int extraParamToByteArray(byte[] data, int index) { data[index] = (byte) mExternalSourceSpecifier; mRecordSource.toByteArray(false, data, index + 1); return getDataSize(false); } }
Checks the byte array of timer record source.
Params:
  • sourcetype –
  • recordSource –
@hide
/** * Checks the byte array of timer record source. * @param sourcetype * @param recordSource * @hide */
@SystemApi public static boolean checkTimerRecordSource(int sourcetype, byte[] recordSource) { int recordSourceSize = recordSource.length - TimerInfo.BASIC_INFO_SIZE; switch (sourcetype) { case TIMER_RECORDING_TYPE_DIGITAL: return DigitalServiceSource.EXTRA_DATA_SIZE == recordSourceSize; case TIMER_RECORDING_TYPE_ANALOGUE: return AnalogueServiceSource.EXTRA_DATA_SIZE == recordSourceSize; case TIMER_RECORDING_TYPE_EXTERNAL: int specifier = recordSource[TimerInfo.BASIC_INFO_SIZE]; if (specifier == EXTERNAL_SOURCE_SPECIFIER_EXTERNAL_PLUG) { // One byte for specifier. return ExternalPlugData.EXTRA_DATA_SIZE + 1 == recordSourceSize; } else if (specifier == EXTERNAL_SOURCE_SPECIFIER_EXTERNAL_PHYSICAL_ADDRESS) { // One byte for specifier. return ExternalPhysicalAddress.EXTRA_DATA_SIZE + 1 == recordSourceSize; } else { // Invalid specifier. return false; } default: return false; } } }