Merge "Replace osd message for record status with IHdmiRecordCallback." into lmp-dev
diff --git a/Android.mk b/Android.mk
index 278e67f..0d71150 100644
--- a/Android.mk
+++ b/Android.mk
@@ -155,7 +155,7 @@
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/IHdmiRecordListener.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/HdmiControlManager.java b/core/java/android/hardware/hdmi/HdmiControlManager.java
index 521a439..55db1df 100644
--- a/core/java/android/hardware/hdmi/HdmiControlManager.java
+++ b/core/java/android/hardware/hdmi/HdmiControlManager.java
@@ -69,69 +69,71 @@
public static final int RESULT_INCORRECT_MODE = 6;
public static final int RESULT_COMMUNICATION_FAILED = 7;
- // -- Message ids for display osd.
-
- /** Place holder for recording status message. Indicates the status of a recording. */
- public static final int MESSAGE_RECORDING_STATUS_MESSAGE_START = 0x100;
+ // --- One Touch Recording success result
/** Recording currently selected source. Indicates the status of a recording. */
- public static final int MESSAGE_RECORDING_CURRENTLY_SELECTED_SOURCE = 0x101;
+ public static final int ONE_TOUCH_RECORD_RECORDING_CURRENTLY_SELECTED_SOURCE = 0x01;
/** Recording Digital Service. Indicates the status of a recording. */
- public static final int MESSAGE_RECORDING_DIGITAL_SERVICE = 0x102;
+ public static final int ONE_TOUCH_RECORD_RECORDING_DIGITAL_SERVICE = 0x02;
/** Recording Analogue Service. Indicates the status of a recording. */
- public static final int MESSAGE_RECORDING_ANALOGUE_SERVICE = 0x103;
+ public static final int ONE_TOUCH_RECORD_RECORDING_ANALOGUE_SERVICE = 0x03;
/** Recording External input. Indicates the status of a recording. */
- public static final int MESSAGE_RECORDING_EXTERNAL_INPUT = 0x104;
+ public static final int ONE_TOUCH_RECORD_RECORDING_EXTERNAL_INPUT = 0x04;
+
+ // --- One Touch Record failure result
/** No recording – unable to record Digital Service. No suitable tuner. */
- public static final int MESSAGE_NO_RECORDNIG_UNABLE_DIGITAL_SERVICE = 0x105;
+ public static final int ONE_TOUCH_RECORD_UNABLE_DIGITAL_SERVICE = 0x05;
/** No recording – unable to record Analogue Service. No suitable tuner. */
- public static final int MESSAGE_NO_RECORDNIG_UNABLE_ANALOGUE_SERVICE = 0x106;
+ public static final int ONE_TOUCH_RECORD_UNABLE_ANALOGUE_SERVICE = 0x06;
/**
* No recording – unable to select required service. as suitable tuner, but the requested
* parameters are invalid or out of range for that tuner.
*/
- public static final int MESSAGE_NO_RECORDNIG_UNABLE_SELECTED_SERVICE = 0x107;
+ public static final int ONE_TOUCH_RECORD_UNABLE_SELECTED_SERVICE = 0x07;
/** No recording – invalid External plug number */
- public static final int MESSAGE_NO_RECORDNIG_INVALID_EXTERNAL_PLUG_NUMBER = 0x109;
+ public static final int ONE_TOUCH_RECORD_INVALID_EXTERNAL_PLUG_NUMBER = 0x09;
/** No recording – invalid External Physical Address */
- public static final int MESSAGE_NO_RECORDNIG_INVALID_EXTERNAL_PHYSICAL_ADDRESS = 0x10A;
+ public static final int ONE_TOUCH_RECORD_INVALID_EXTERNAL_PHYSICAL_ADDRESS = 0x0A;
/** No recording – CA system not supported */
- public static final int MESSAGE_NO_RECORDNIG_UNSUPPORTED_CA = 0x10B;
+ public static final int ONE_TOUCH_RECORD_UNSUPPORTED_CA = 0x0B;
/** No Recording – No or Insufficient CA Entitlements” */
- public static final int MESSAGE_NO_RECORDNIG_NO_OR_INSUFFICIENT_CA_ENTITLEMENTS = 0x10C;
+ public static final int ONE_TOUCH_RECORD_NO_OR_INSUFFICIENT_CA_ENTITLEMENTS = 0x0C;
/** No recording – Not allowed to copy source. Source is “copy never”. */
- public static final int MESSAGE_NO_RECORDNIG_DISALLOW_TO_COPY = 0x10D;
+ public static final int ONE_TOUCH_RECORD_DISALLOW_TO_COPY = 0x0D;
/** No recording – No further copies allowed */
- public static final int MESSAGE_NO_RECORDNIG_DISALLOW_TO_FUTHER_COPIES = 0x10E;
+ public static final int ONE_TOUCH_RECORD_DISALLOW_TO_FUTHER_COPIES = 0x0E;
/** No recording – No media */
- public static final int MESSAGE_NO_RECORDNIG_NO_MEDIA = 0x110;
+ public static final int ONE_TOUCH_RECORD_NO_MEDIA = 0x10;
/** No recording – playing */
- public static final int MESSAGE_NO_RECORDNIG_PLAYING = 0x111;
+ public static final int ONE_TOUCH_RECORD_PLAYING = 0x11;
/** No recording – already recording */
- public static final int MESSAGE_NO_RECORDNIG_ALREADY_RECORDING = 0x112;
+ public static final int ONE_TOUCH_RECORD_ALREADY_RECORDING = 0x12;
/** No recording – media protected */
- public static final int MESSAGE_NO_RECORDNIG_MEDIA_PROTECTED = 0x113;
+ public static final int ONE_TOUCH_RECORD_MEDIA_PROTECTED = 0x13;
/** No recording – no source signal */
- public static final int MESSAGE_NO_RECORDNIG_NO_SOURCE_SIGNAL = 0x114;
+ public static final int ONE_TOUCH_RECORD_NO_SOURCE_SIGNAL = 0x14;
/** No recording – media problem */
- public static final int MESSAGE_NO_RECORDNIG_MEDIA_PROBLEM = 0x115;
+ public static final int ONE_TOUCH_RECORD_MEDIA_PROBLEM = 0x15;
/** No recording – not enough space available */
- public static final int MESSAGE_NO_RECORDNIG_NOT_ENOUGH_SPACE = 0x116;
+ public static final int ONE_TOUCH_RECORD_NOT_ENOUGH_SPACE = 0x16;
/** No recording – Parental Lock On */
- public static final int MESSAGE_NO_RECORDNIG_PARENT_LOCK_ON = 0x117;
+ public static final int ONE_TOUCH_RECORD_PARENT_LOCK_ON = 0x17;
/** Recording terminated normally */
- public static final int MESSAGE_RECORDING_TERMINATED_NORMALLY = 0x11A;
+ public static final int ONE_TOUCH_RECORD_RECORDING_TERMINATED_NORMALLY = 0x1A;
/** Recording has already terminated */
- public static final int MESSAGE_RECORDING_ALREADY_TERMINATED = 0x11B;
+ public static final int ONE_TOUCH_RECORD_RECORDING_ALREADY_TERMINATED = 0x1B;
/** No recording – other reason */
- public static final int MESSAGE_NO_RECORDNIG_OTHER_REASON = 0x11F;
+ public static final int ONE_TOUCH_RECORD_OTHER_REASON = 0x1F;
// From here extra message for recording that is not mentioned in CEC spec
/** No recording. Previous recording request in progress. */
- public static final int MESSAGE_NO_RECORDING_PREVIOUS_RECORDING_IN_PROGRESS = 0x130;
+ public static final int ONE_TOUCH_RECORD_PREVIOUS_RECORDING_IN_PROGRESS = 0x30;
/** No recording. Please check recorder and connection. */
- public static final int MESSAGE_NO_RECORDING_CHECK_RECORDER_CONNECTION = 0x131;
+ public static final int ONE_TOUCH_RECORD_CHECK_RECORDER_CONNECTION = 0x31;
/** Cannot record currently displayed source. */
- public static final int MESSAGE_NO_RECORDING_FAIL_TO_RECORD_DISPLAYED_SCREEN = 0x132;
+ public static final int ONE_TOUCH_RECORD_FAIL_TO_RECORD_DISPLAYED_SCREEN = 0x32;
+ /** CEC is disabled. */
+ public static final int ONE_TOUCH_RECORD_CEC_DISABLED = 0x33;
+ // --- Types for timer recording
/** Timer recording type for digital service source. */
public static final int TIMER_RECORDING_TYPE_DIGITAL = 1;
/** Timer recording type for analogue service source. */
@@ -139,6 +141,14 @@
/** Timer recording type for external source. */
public static final int TIMER_RECORDING_TYPE_EXTERNAL = 3;
+ // --- Extra result value for timer recording.
+ /** No timer recording - check recorder and connection. */
+ public static final int TIME_RECORDING_RESULT_EXTRA_CHECK_RECORDER_CONNECTION = 0x01;
+ /** No timer recording - cannot record selected source. */
+ public static final int TIME_RECORDING_RESULT_EXTRA_FAIL_TO_RECORD_SELECTED_SOURCE = 0x02;
+ /** CEC is disabled. */
+ public static final int TIME_RECORDING_RESULT_EXTRA_CEC_DISABLED = 0x33;
+
// True if we have a logical device of type playback hosted in the system.
private final boolean mHasPlaybackDevice;
// True if we have a logical device of type TV hosted in the system.
diff --git a/core/java/android/hardware/hdmi/HdmiRecordListener.java b/core/java/android/hardware/hdmi/HdmiRecordListener.java
new file mode 100644
index 0000000..0b1166b
--- /dev/null
+++ b/core/java/android/hardware/hdmi/HdmiRecordListener.java
@@ -0,0 +1,67 @@
+/*
+ * 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.SystemApi;
+import android.hardware.hdmi.HdmiRecordSources.RecordSource;
+
+/**
+ * Listener for hdmi record feature including one touch record and timer recording.
+ * @hide
+ */
+@SystemApi
+public abstract class HdmiRecordListener {
+ protected HdmiRecordListener() {}
+
+ /**
+ * Called when TV received one touch record request from record device. The client of this
+ * should use {@link HdmiRecordSources} to return it.
+ *
+ * @param recorderAddress
+ * @return record source to be used for recording. Null if no device is available.
+ */
+ public abstract RecordSource getOneTouchRecordSource(int recorderAddress);
+
+ /**
+ * Called when one touch record is started or failed during initialization.
+ *
+ * @param result result code. For more details, please look at all constants starting with
+ * "ONE_TOUCH_RECORD_". Only
+ * {@link HdmiControlManager#ONE_TOUCH_RECORD_RECORDING_CURRENTLY_SELECTED_SOURCE},
+ * {@link HdmiControlManager#ONE_TOUCH_RECORD_RECORDING_DIGITAL_SERVICE},
+ * {@link HdmiControlManager#ONE_TOUCH_RECORD_RECORDING_ANALOGUE_SERVICE}, and
+ * {@link HdmiControlManager#ONE_TOUCH_RECORD_RECORDING_EXTERNAL_INPUT} mean normal
+ * start of recording; otherwise, describes failure.
+ */
+ public void onOneTouchRecordResult(int result) {
+ }
+
+ /**
+ * Called when timer recording is started or failed during initialization.
+ *
+ * @param result The most significant three bytes may contain result of <Timer Status>
+ * while the least significant byte may have error message like
+ * {@link HdmiControlManager#TIME_RECORDING_RESULT_EXTRA_CHECK_RECORDER_CONNECTION}
+ * or
+ * {@link HdmiControlManager #TIME_RECORDING_RESULT_EXTRA_FAIL_TO_RECORD_SELECTED_SOURCE}
+ * . If the least significant byte has non zero value the most significant three bytes
+ * may have 0 value.
+ */
+ // TODO: implement result parser.
+ public void onTimerRecordingResult(int result) {
+ }
+}
diff --git a/core/java/android/hardware/hdmi/HdmiRecordSources.java b/core/java/android/hardware/hdmi/HdmiRecordSources.java
index 296cae6..917d1d9 100644
--- a/core/java/android/hardware/hdmi/HdmiRecordSources.java
+++ b/core/java/android/hardware/hdmi/HdmiRecordSources.java
@@ -492,7 +492,7 @@
/** 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;
+ static final int EXTRA_DATA_SIZE = 7;
/**
* Type of identification. It should be one of DIGITAL_SERVICE_IDENTIFIED_BY_DIGITAL_ID and
@@ -609,7 +609,7 @@
*/
@SystemApi
public static final class AnalogueServiceSource extends RecordSource {
- private static final int EXTRA_DATA_SIZE = 4;
+ static final int EXTRA_DATA_SIZE = 4;
/** Indicates the Analogue broadcast type. */
private final int mBroadcastType;
@@ -668,7 +668,7 @@
*/
@SystemApi
public static final class ExternalPlugData extends RecordSource {
- private static final int EXTRA_DATA_SIZE = 1;
+ static final int EXTRA_DATA_SIZE = 1;
/** External Plug number on the Recording Device. */
private final int mPlugNumber;
@@ -713,7 +713,7 @@
*/
@SystemApi
public static final class ExternalPhysicalAddress extends RecordSource {
- private static final int EXTRA_DATA_SIZE = 2;
+ static final int EXTRA_DATA_SIZE = 2;
private final int mPhysicalAddress;
@@ -751,6 +751,7 @@
* Check the byte array of record source.
* @hide
*/
+ @SystemApi
public static boolean checkRecordSource(byte[] recordSource) {
int recordSourceType = recordSource[0];
int extraDataSize = recordSource.length - 1;
diff --git a/core/java/android/hardware/hdmi/HdmiTimerRecordSources.java b/core/java/android/hardware/hdmi/HdmiTimerRecordSources.java
index 3e5e49b..01b4dd3 100644
--- a/core/java/android/hardware/hdmi/HdmiTimerRecordSources.java
+++ b/core/java/android/hardware/hdmi/HdmiTimerRecordSources.java
@@ -16,6 +16,10 @@
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;
@@ -420,4 +424,35 @@
return getDataSize(false);
}
}
+
+ /**
+ * Check 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;
+ }
+ }
}
diff --git a/core/java/android/hardware/hdmi/HdmiTvClient.java b/core/java/android/hardware/hdmi/HdmiTvClient.java
index 6080914..3436287 100644
--- a/core/java/android/hardware/hdmi/HdmiTvClient.java
+++ b/core/java/android/hardware/hdmi/HdmiTvClient.java
@@ -15,10 +15,9 @@
*/
package android.hardware.hdmi;
-import static android.hardware.hdmi.HdmiRecordSources.RecordSource;
-import static android.hardware.hdmi.HdmiTimerRecordSources.TimerRecordSource;
-
import android.annotation.SystemApi;
+import android.hardware.hdmi.HdmiRecordSources.RecordSource;
+import android.hardware.hdmi.HdmiTimerRecordSources.TimerRecordSource;
import android.os.RemoteException;
import android.util.Log;
@@ -155,27 +154,15 @@
}
/**
- * Callback interface to used to get notified when a record request from recorder device.
+ * Set record listener
+ *
+ * @param listener
*/
- 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
- */
- RecordSource onRecordRequestReceived(int recorderAddress);
- }
-
- /**
- * Set {@link RecordRequestListener} to hdmi control service.
- */
- public void setOneTouchRecordRequestListener(RecordRequestListener listener) {
+ public void setRecordListener(HdmiRecordListener listener) {
try {
- mService.setOneTouchRecordRequestListener(getCallbackWrapper(listener));
+ mService.setHdmiRecordListener(getListenerWrapper(listener));
} catch (RemoteException e) {
- Log.e(TAG, "failed to set record request listener: ", e);
+ Log.e(TAG, "failed to set record listener.", e);
}
}
@@ -282,13 +269,12 @@
};
}
- private static IHdmiRecordRequestListener getCallbackWrapper(
- final RecordRequestListener listener) {
- return new IHdmiRecordRequestListener.Stub() {
+ private static IHdmiRecordListener getListenerWrapper(final HdmiRecordListener callback) {
+ return new IHdmiRecordListener.Stub() {
@Override
- public byte[] onRecordRequestReceived(int recorderAddress) throws RemoteException {
+ public byte[] getOneTouchRecordSource(int recorderAddress) {
HdmiRecordSources.RecordSource source =
- listener.onRecordRequestReceived(recorderAddress);
+ callback.getOneTouchRecordSource(recorderAddress);
if (source == null) {
return EmptyArray.BYTE;
}
@@ -296,6 +282,16 @@
source.toByteArray(true, data, 0);
return data;
}
+
+ @Override
+ public void onOneTouchRecordResult(int result) {
+ callback.onOneTouchRecordResult(result);
+ }
+
+ @Override
+ public void onTimerRecordingResult(int result) {
+ callback.onTimerRecordingResult(result);
+ }
};
}
}
diff --git a/core/java/android/hardware/hdmi/IHdmiControlService.aidl b/core/java/android/hardware/hdmi/IHdmiControlService.aidl
index 95e0ee0..808e0c9 100644
--- a/core/java/android/hardware/hdmi/IHdmiControlService.aidl
+++ b/core/java/android/hardware/hdmi/IHdmiControlService.aidl
@@ -22,7 +22,7 @@
import android.hardware.hdmi.IHdmiDeviceEventListener;
import android.hardware.hdmi.IHdmiHotplugEventListener;
import android.hardware.hdmi.IHdmiInputChangeListener;
-import android.hardware.hdmi.IHdmiRecordRequestListener;
+import android.hardware.hdmi.IHdmiRecordListener;
import android.hardware.hdmi.IHdmiSystemAudioModeChangeListener;
import android.hardware.hdmi.IHdmiVendorCommandListener;
@@ -62,7 +62,7 @@
void sendVendorCommand(int deviceType, int targetAddress, in byte[] params,
boolean hasVendorId);
void addVendorCommandListener(IHdmiVendorCommandListener listener, int deviceType);
- void setOneTouchRecordRequestListener(IHdmiRecordRequestListener listener);
+ void setHdmiRecordListener(IHdmiRecordListener callback);
void startOneTouchRecord(int recorderAddress, in byte[] recordSource);
void stopOneTouchRecord(int recorderAddress);
void startTimerRecording(int recorderAddress, int sourceType, in byte[] recordSource);
diff --git a/core/java/android/hardware/hdmi/IHdmiRecordListener.aidl b/core/java/android/hardware/hdmi/IHdmiRecordListener.aidl
new file mode 100644
index 0000000..fba4b05
--- /dev/null
+++ b/core/java/android/hardware/hdmi/IHdmiRecordListener.aidl
@@ -0,0 +1,42 @@
+/*
+ * 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;
+
+/**
+ * @hide
+ */
+ interface IHdmiRecordListener {
+ /**
+ * Called when TV received one touch record request from record device.
+ *
+ * @param recorderAddress
+ * @return record source in byte array.
+ */
+ byte[] getOneTouchRecordSource(int recorderAddress);
+
+ /**
+ * Called when one touch record is started or failed during initialization.
+ *
+ * @param result result code for one touch record
+ */
+ void onOneTouchRecordResult(int result);
+ /**
+ * Called when timer recording is started or failed during initialization.
+ * @param result result code for timer recording
+ */
+ void onTimerRecordingResult(int result);
+ }
\ No newline at end of file
diff --git a/core/java/android/hardware/hdmi/IHdmiRecordRequestListener.aidl b/core/java/android/hardware/hdmi/IHdmiRecordRequestListener.aidl
deleted file mode 100644
index f8f9e5f..0000000
--- a/core/java/android/hardware/hdmi/IHdmiRecordRequestListener.aidl
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * 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/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
index bbecafa..5da8aef 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
@@ -16,10 +16,18 @@
package com.android.server.hdmi;
+import static android.hardware.hdmi.HdmiControlManager.ONE_TOUCH_RECORD_CEC_DISABLED;
+import static android.hardware.hdmi.HdmiControlManager.ONE_TOUCH_RECORD_CHECK_RECORDER_CONNECTION;
+import static android.hardware.hdmi.HdmiControlManager.ONE_TOUCH_RECORD_FAIL_TO_RECORD_DISPLAYED_SCREEN;
+import static android.hardware.hdmi.HdmiControlManager.TIME_RECORDING_RESULT_EXTRA_CEC_DISABLED;
+import static android.hardware.hdmi.HdmiControlManager.TIME_RECORDING_RESULT_EXTRA_CHECK_RECORDER_CONNECTION;
+import static android.hardware.hdmi.HdmiControlManager.TIME_RECORDING_RESULT_EXTRA_FAIL_TO_RECORD_SELECTED_SOURCE;
+
import android.content.Intent;
import android.hardware.hdmi.HdmiCecDeviceInfo;
import android.hardware.hdmi.HdmiControlManager;
import android.hardware.hdmi.HdmiRecordSources;
+import android.hardware.hdmi.HdmiTimerRecordSources;
import android.hardware.hdmi.IHdmiControlCallback;
import android.media.AudioManager;
import android.media.AudioSystem;
@@ -47,7 +55,7 @@
final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
private static final String TAG = "HdmiCecLocalDeviceTv";
- // Whether ARC is available or not. "true" means that ARC is estabilished between TV and
+ // Whether ARC is available or not. "true" means that ARC is established between TV and
// AVR as audio receiver.
@ServiceThreadOnly
private boolean mArcEstablished = false;
@@ -819,7 +827,8 @@
// Assumes only one OneTouchRecordAction.
OneTouchRecordAction action = actions.get(0);
if (action.getRecorderAddress() != message.getSource()) {
- displayOsd(HdmiControlManager.MESSAGE_NO_RECORDING_PREVIOUS_RECORDING_IN_PROGRESS);
+ announceOneTouchRecordResult(
+ HdmiControlManager.ONE_TOUCH_RECORD_PREVIOUS_RECORDING_IN_PROGRESS);
}
return super.handleRecordTvScreen(message);
}
@@ -830,6 +839,14 @@
return true;
}
+ void announceOneTouchRecordResult(int result) {
+ mService.invokeOneTouchRecordResult(result);
+ }
+
+ void announceTimerRecordingResult(int result) {
+ mService.invokeTimerRecordingResult(result);
+ }
+
private boolean isMessageForSystemAudio(HdmiCecMessage message) {
if (message.getSource() != Constants.ADDR_AUDIO_SYSTEM
|| message.getDestination() != Constants.ADDR_TV
@@ -1241,16 +1258,19 @@
assertRunOnServiceThread();
if (!mService.isControlEnabled()) {
Slog.w(TAG, "Can not start one touch record. CEC control is disabled.");
+ announceOneTouchRecordResult(ONE_TOUCH_RECORD_CEC_DISABLED);
return;
}
if (!checkRecorder(recorderAddress)) {
Slog.w(TAG, "Invalid recorder address:" + recorderAddress);
+ announceOneTouchRecordResult(ONE_TOUCH_RECORD_CHECK_RECORDER_CONNECTION);
return;
}
if (!checkRecordSource(recordSource)) {
Slog.w(TAG, "Invalid record source." + Arrays.toString(recordSource));
+ announceOneTouchRecordResult(ONE_TOUCH_RECORD_FAIL_TO_RECORD_DISPLAYED_SCREEN);
return;
}
@@ -1264,11 +1284,13 @@
assertRunOnServiceThread();
if (!mService.isControlEnabled()) {
Slog.w(TAG, "Can not stop one touch record. CEC control is disabled.");
+ announceOneTouchRecordResult(ONE_TOUCH_RECORD_CEC_DISABLED);
return;
}
if (!checkRecorder(recorderAddress)) {
Slog.w(TAG, "Invalid recorder address:" + recorderAddress);
+ announceOneTouchRecordResult(ONE_TOUCH_RECORD_CHECK_RECORDER_CONNECTION);
return;
}
@@ -1292,8 +1314,35 @@
@ServiceThreadOnly
void startTimerRecording(int recorderAddress, int sourceType, byte[] recordSource) {
assertRunOnServiceThread();
+ if (!mService.isControlEnabled()) {
+ Slog.w(TAG, "Can not start one touch record. CEC control is disabled.");
+ announceTimerRecordingResult(TIME_RECORDING_RESULT_EXTRA_CEC_DISABLED);
+ return;
+ }
- // TODO: implement this.
+ if (!checkRecorder(recorderAddress)) {
+ Slog.w(TAG, "Invalid recorder address:" + recorderAddress);
+ announceTimerRecordingResult(
+ TIME_RECORDING_RESULT_EXTRA_CHECK_RECORDER_CONNECTION);
+ return;
+ }
+
+ if (!checkTimerRecordingSource(sourceType, recordSource)) {
+ Slog.w(TAG, "Invalid record source." + Arrays.toString(recordSource));
+ announceTimerRecordingResult(
+ TIME_RECORDING_RESULT_EXTRA_FAIL_TO_RECORD_SELECTED_SOURCE);
+ return;
+ }
+
+ addAndStartAction(
+ new TimerRecordingAction(this, recorderAddress, sourceType, recordSource));
+ Slog.i(TAG, "Start [Timer Recording]-Target:" + recorderAddress + ", SourceType:"
+ + sourceType + ", RecordSource:" + Arrays.toString(recordSource));
+ }
+
+ private boolean checkTimerRecordingSource(int sourceType, byte[] recordSource) {
+ return (recordSource != null)
+ && HdmiTimerRecordSources.checkTimerRecordSource(sourceType, recordSource);
}
@ServiceThreadOnly
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecMessageBuilder.java b/services/core/java/com/android/server/hdmi/HdmiCecMessageBuilder.java
index 79f1964..0855bfa 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecMessageBuilder.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecMessageBuilder.java
@@ -478,6 +478,78 @@
return buildCommand(src, dest, Constants.MESSAGE_RECORD_OFF);
}
+ /**
+ * Build <Set Digital Timer> command.
+ *
+ * @param src source address of command
+ * @param dest destination address of command
+ * @param params byte array of timing information and digital service information to be recorded
+ * @return newly created {@link HdmiCecMessage}
+ */
+ static HdmiCecMessage buildSetDigitalTimer(int src, int dest, byte[] params) {
+ return buildCommand(src, dest, Constants.MESSAGE_SET_DIGITAL_TIMER, params);
+ }
+
+ /**
+ * Build <Set Analogue Timer> command.
+ *
+ * @param src source address of command
+ * @param dest destination address of command
+ * @param params byte array of timing information and analog service information to be recorded
+ * @return newly created {@link HdmiCecMessage}
+ */
+ static HdmiCecMessage buildSetAnalogueTimer(int src, int dest, byte[] params) {
+ return buildCommand(src, dest, Constants.MESSAGE_SET_ANALOG_TIMER, params);
+ }
+
+ /**
+ * Build <Set External Timer> command.
+ *
+ * @param src source address of command
+ * @param dest destination address of command
+ * @param params byte array of timing information and external source information to be recorded
+ * @return newly created {@link HdmiCecMessage}
+ */
+ static HdmiCecMessage buildSetExternalTimer(int src, int dest, byte[] params) {
+ return buildCommand(src, dest, Constants.MESSAGE_SET_EXTERNAL_TIMER, params);
+ }
+
+ /**
+ * Build <Clear Digital Timer> command.
+ *
+ * @param src source address of command
+ * @param dest destination address of command
+ * @param params byte array of timing information and digital service information to be cleared
+ * @return newly created {@link HdmiCecMessage}
+ */
+ static HdmiCecMessage buildClearDigitalTimer(int src, int dest, byte[] params) {
+ return buildCommand(src, dest, Constants.MESSAGE_CLEAR_DIGITAL_TIMER, params);
+ }
+
+ /**
+ * Build <Clear Analog Timer> command.
+ *
+ * @param src source address of command
+ * @param dest destination address of command
+ * @param params byte array of timing information and analog service information to be cleared
+ * @return newly created {@link HdmiCecMessage}
+ */
+ static HdmiCecMessage buildClearAnalogueTimer(int src, int dest, byte[] params) {
+ return buildCommand(src, dest, Constants.MESSAGE_CLEAR_ANALOG_TIMER, params);
+ }
+
+ /**
+ * Build <Clear Digital Timer> command.
+ *
+ * @param src source address of command
+ * @param dest destination address of command
+ * @param params byte array of timing information and external source information to be cleared
+ * @return newly created {@link HdmiCecMessage}
+ */
+ static HdmiCecMessage buildClearExternalTimer(int src, int dest, byte[] params) {
+ return buildCommand(src, dest, Constants.MESSAGE_CLEAR_EXTERNAL_TIMER, params);
+ }
+
/***** Please ADD new buildXXX() methods above. ******/
/**
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 7672232..60421e3 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -32,7 +32,7 @@
import android.hardware.hdmi.IHdmiDeviceEventListener;
import android.hardware.hdmi.IHdmiHotplugEventListener;
import android.hardware.hdmi.IHdmiInputChangeListener;
-import android.hardware.hdmi.IHdmiRecordRequestListener;
+import android.hardware.hdmi.IHdmiRecordListener;
import android.hardware.hdmi.IHdmiSystemAudioModeChangeListener;
import android.hardware.hdmi.IHdmiVendorCommandListener;
import android.media.AudioManager;
@@ -160,10 +160,10 @@
private InputChangeListenerRecord mInputChangeListenerRecord;
@GuardedBy("mLock")
- private IHdmiRecordRequestListener mRecordRequestListener;
+ private IHdmiRecordListener mRecordListener;
@GuardedBy("mLock")
- private HdmiRecordRequestListenerRecord mRecordRequestListenerRecord;
+ private HdmiRecordListenerRecord mRecordListenerRecord;
// Set to true while HDMI control is enabled. If set to false, HDMI-CEC/MHL protocol
// handling will be disabled and no request will be handled.
@@ -692,11 +692,11 @@
}
}
- private class HdmiRecordRequestListenerRecord implements IBinder.DeathRecipient {
+ private class HdmiRecordListenerRecord implements IBinder.DeathRecipient {
@Override
public void binderDied() {
synchronized (mLock) {
- mRecordRequestListener = null;
+ mRecordListener = null;
}
}
}
@@ -1027,11 +1027,11 @@
}
}
});
- }
+ }
@Override
- public void setOneTouchRecordRequestListener(IHdmiRecordRequestListener listener) {
- HdmiControlService.this.setOneTouchRecordRequestListener(listener);
+ public void setHdmiRecordListener(IHdmiRecordListener listener) {
+ HdmiControlService.this.setHdmiRecordListener(listener);
}
@Override
@@ -1234,32 +1234,55 @@
}
}
- private void setOneTouchRecordRequestListener(IHdmiRecordRequestListener listener) {
+ private void setHdmiRecordListener(IHdmiRecordListener listener) {
synchronized (mLock) {
- mRecordRequestListenerRecord = new HdmiRecordRequestListenerRecord();
+ mRecordListenerRecord = new HdmiRecordListenerRecord();
try {
- listener.asBinder().linkToDeath(mRecordRequestListenerRecord, 0);
+ listener.asBinder().linkToDeath(mRecordListenerRecord, 0);
} catch (RemoteException e) {
- Slog.w(TAG, "Listener already died", e);
- return;
+ Slog.w(TAG, "Listener already died.", e);
}
- mRecordRequestListener = listener;
+ mRecordListener = listener;
}
}
byte[] invokeRecordRequestListener(int recorderAddress) {
synchronized (mLock) {
- try {
- if (mRecordRequestListener != null) {
- return mRecordRequestListener.onRecordRequestReceived(recorderAddress);
+ if (mRecordListener != null) {
+ try {
+ return mRecordListener.getOneTouchRecordSource(recorderAddress);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Failed to start record.", e);
}
- } catch (RemoteException e) {
- Slog.w(TAG, "Failed to start record.", e);
}
return EmptyArray.BYTE;
}
}
+ void invokeOneTouchRecordResult(int result) {
+ synchronized (mLock) {
+ if (mRecordListener != null) {
+ try {
+ mRecordListener.onOneTouchRecordResult(result);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Failed to call onOneTouchRecordResult.", e);
+ }
+ }
+ }
+ }
+
+ void invokeTimerRecordingResult(int result) {
+ synchronized (mLock) {
+ if (mRecordListener != null) {
+ try {
+ mRecordListener.onTimerRecordingResult(result);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Failed to call onOneTouchRecordResult.", e);
+ }
+ }
+ }
+ }
+
private void invokeCallback(IHdmiControlCallback callback, int result) {
try {
callback.onComplete(result);
diff --git a/services/core/java/com/android/server/hdmi/OneTouchRecordAction.java b/services/core/java/com/android/server/hdmi/OneTouchRecordAction.java
index 9ecbc5e..befc640 100644
--- a/services/core/java/com/android/server/hdmi/OneTouchRecordAction.java
+++ b/services/core/java/com/android/server/hdmi/OneTouchRecordAction.java
@@ -16,26 +16,24 @@
package com.android.server.hdmi;
-import static android.hardware.hdmi.HdmiControlManager.MESSAGE_NO_RECORDING_CHECK_RECORDER_CONNECTION;
-import static android.hardware.hdmi.HdmiControlManager.MESSAGE_RECORDING_ANALOGUE_SERVICE;
-import static android.hardware.hdmi.HdmiControlManager.MESSAGE_RECORDING_CURRENTLY_SELECTED_SOURCE;
-import static android.hardware.hdmi.HdmiControlManager.MESSAGE_RECORDING_DIGITAL_SERVICE;
-import static android.hardware.hdmi.HdmiControlManager.MESSAGE_RECORDING_EXTERNAL_INPUT;
-import static android.hardware.hdmi.HdmiControlManager.MESSAGE_RECORDING_STATUS_MESSAGE_START;
+import static android.hardware.hdmi.HdmiControlManager.ONE_TOUCH_RECORD_CHECK_RECORDER_CONNECTION;
+import static android.hardware.hdmi.HdmiControlManager.ONE_TOUCH_RECORD_RECORDING_ANALOGUE_SERVICE;
+import static android.hardware.hdmi.HdmiControlManager.ONE_TOUCH_RECORD_RECORDING_CURRENTLY_SELECTED_SOURCE;
+import static android.hardware.hdmi.HdmiControlManager.ONE_TOUCH_RECORD_RECORDING_DIGITAL_SERVICE;
+import static android.hardware.hdmi.HdmiControlManager.ONE_TOUCH_RECORD_RECORDING_EXTERNAL_INPUT;
import android.util.Slog;
import com.android.server.hdmi.HdmiControlService.SendMessageCallback;
/**
- * Feature action that performs one touch record. This class only provides a skeleton of one touch
- * play and has no detail implementation.
+ * Feature action that performs one touch record.
*/
public class OneTouchRecordAction extends FeatureAction {
private static final String TAG = "OneTouchRecordAction";
- // Timer out for waiting <Record Status>
- private static final int RECORD_STATUS_TIMEOUT = 120000;
+ // Timer out for waiting <Record Status> 120s
+ private static final int RECORD_STATUS_TIMEOUT_MS = 120000;
// State that waits for <Record Status> once sending <Record On>
private static final int STATE_WAITING_FOR_RECORD_STATUS = 1;
@@ -65,13 +63,14 @@
public void onSendCompleted(int error) {
// if failed to send <Record On>, display error message and finish action.
if (error != Constants.SEND_RESULT_SUCCESS) {
- tv().displayOsd(MESSAGE_NO_RECORDING_CHECK_RECORDER_CONNECTION);
+ tv().announceOneTouchRecordResult(
+ ONE_TOUCH_RECORD_CHECK_RECORDER_CONNECTION);
finish();
return;
}
mState = STATE_WAITING_FOR_RECORD_STATUS;
- addTimer(mState, RECORD_STATUS_TIMEOUT);
+ addTimer(mState, RECORD_STATUS_TIMEOUT_MS);
}
});
}
@@ -97,18 +96,16 @@
}
int recordStatus = cmd.getParams()[0];
+ tv().announceOneTouchRecordResult(recordStatus);
Slog.i(TAG, "Got record status:" + recordStatus + " from " + cmd.getSource());
- int recordStatusMessageCode = recordStatus + MESSAGE_RECORDING_STATUS_MESSAGE_START;
- tv().displayOsd(recordStatusMessageCode);
-
// If recording started successfully, change state and keep this action until <Record Off>
// received. Otherwise, finish action.
- switch (recordStatusMessageCode) {
- case MESSAGE_RECORDING_CURRENTLY_SELECTED_SOURCE:
- case MESSAGE_RECORDING_DIGITAL_SERVICE:
- case MESSAGE_RECORDING_ANALOGUE_SERVICE:
- case MESSAGE_RECORDING_EXTERNAL_INPUT:
+ switch (recordStatus) {
+ case ONE_TOUCH_RECORD_RECORDING_CURRENTLY_SELECTED_SOURCE:
+ case ONE_TOUCH_RECORD_RECORDING_DIGITAL_SERVICE:
+ case ONE_TOUCH_RECORD_RECORDING_ANALOGUE_SERVICE:
+ case ONE_TOUCH_RECORD_RECORDING_EXTERNAL_INPUT:
mState = STATE_RECORDING_IN_PROGRESS;
mActionTimer.clearTimerMessage();
break;
@@ -126,7 +123,7 @@
return;
}
- tv().displayOsd(MESSAGE_NO_RECORDING_CHECK_RECORDER_CONNECTION);
+ tv().announceOneTouchRecordResult(ONE_TOUCH_RECORD_CHECK_RECORDER_CONNECTION);
finish();
}
diff --git a/services/core/java/com/android/server/hdmi/TimerRecordingAction.java b/services/core/java/com/android/server/hdmi/TimerRecordingAction.java
new file mode 100644
index 0000000..1dc26f1
--- /dev/null
+++ b/services/core/java/com/android/server/hdmi/TimerRecordingAction.java
@@ -0,0 +1,169 @@
+/*
+ * 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 com.android.server.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 static android.hardware.hdmi.HdmiControlManager.TIME_RECORDING_RESULT_EXTRA_CHECK_RECORDER_CONNECTION;
+
+import android.util.Slog;
+
+import com.android.server.hdmi.HdmiControlService.SendMessageCallback;
+
+import java.util.Arrays;
+
+/**
+ * Feature action that performs timer recording.
+ */
+public class TimerRecordingAction extends FeatureAction {
+ private static final String TAG = "TimerRecordingAction";
+
+ // Timer out for waiting <Timer Status> 120s.
+ private static final int TIMER_STATUS_TIMEOUT_MS = 120000;
+
+ // State that waits for <Timer Status> once sending <Set XXX Timer>
+ private static final int STATE_WAITING_FOR_TIMER_STATUS = 1;
+
+ private final int mRecorderAddress;
+ private final int mSourceType;
+ private final byte[] mRecordSource;
+
+ TimerRecordingAction(HdmiCecLocalDevice source, int recorderAddress, int sourceType,
+ byte[] recordSource) {
+ super(source);
+ mRecorderAddress = recorderAddress;
+ mSourceType = sourceType;
+ mRecordSource = recordSource;
+ }
+
+ @Override
+ boolean start() {
+ sendTimerMessage();
+ return true;
+ }
+
+ private void sendTimerMessage() {
+ HdmiCecMessage message = null;
+ switch (mSourceType) {
+ case TIMER_RECORDING_TYPE_DIGITAL:
+ message = HdmiCecMessageBuilder.buildSetDigitalTimer(getSourceAddress(),
+ mRecorderAddress, mRecordSource);
+ break;
+ case TIMER_RECORDING_TYPE_ANALOGUE:
+ message = HdmiCecMessageBuilder.buildSetAnalogueTimer(getSourceAddress(),
+ mRecorderAddress, mRecordSource);
+ break;
+ case TIMER_RECORDING_TYPE_EXTERNAL:
+ message = HdmiCecMessageBuilder.buildSetExternalTimer(getSourceAddress(),
+ mRecorderAddress, mRecordSource);
+ break;
+ default:
+ tv().announceTimerRecordingResult(
+ TIME_RECORDING_RESULT_EXTRA_CHECK_RECORDER_CONNECTION);
+ finish();
+ return;
+ }
+ sendCommand(message, new SendMessageCallback() {
+ @Override
+ public void onSendCompleted(int error) {
+ if (error != Constants.SEND_RESULT_SUCCESS) {
+ mState = STATE_WAITING_FOR_TIMER_STATUS;
+ addTimer(mState, TIMER_STATUS_TIMEOUT_MS);
+ finish();
+ return;
+ }
+ }
+ });
+ }
+
+ @Override
+ boolean processCommand(HdmiCecMessage cmd) {
+ if (mState != STATE_WAITING_FOR_TIMER_STATUS) {
+ return false;
+ }
+
+ if (cmd.getSource() != mRecorderAddress) {
+ return false;
+ }
+
+ switch (cmd.getOpcode()) {
+ case Constants.MESSAGE_TIMER_STATUS:
+ return handleTimerStatus(cmd);
+ case Constants.MESSAGE_FEATURE_ABORT:
+ return handleFeatureAbort(cmd);
+ }
+ return false;
+ }
+
+ private boolean handleTimerStatus(HdmiCecMessage cmd) {
+ byte[] timerStatusData = cmd.getParams();
+ // [Timer Status Data] should be one or three bytes.
+ if (timerStatusData.length == 1 || timerStatusData.length == 3) {
+ tv().announceTimerRecordingResult(bytesToInt(timerStatusData));
+ Slog.i(TAG, "Received [Timer Status Data]:" + Arrays.toString(timerStatusData));
+ } else {
+ Slog.w(TAG, "Invalid [Timer Status Data]:" + Arrays.toString(timerStatusData));
+ }
+
+ // Unlike one touch record, finish timer record when <Timer Status> is received.
+ finish();
+ return true;
+ }
+
+ private boolean handleFeatureAbort(HdmiCecMessage cmd) {
+ byte[] params = cmd.getParams();
+ int messageType = params[0];
+ switch (messageType) {
+ case Constants.MESSAGE_SET_DIGITAL_TIMER: // fall through
+ case Constants.MESSAGE_SET_ANALOG_TIMER: // fall through
+ case Constants.MESSAGE_SET_EXTERNAL_TIMER: // fall through
+ break;
+ default:
+ return false;
+ }
+ int reason = params[1];
+ Slog.i(TAG, "[Feature Abort] for " + messageType + " reason:" + reason);
+ tv().announceTimerRecordingResult(TIME_RECORDING_RESULT_EXTRA_CHECK_RECORDER_CONNECTION);
+ finish();
+ return true;
+ }
+
+ // Convert byte array to int.
+ private static int bytesToInt(byte[] data) {
+ if (data.length > 4) {
+ throw new IllegalArgumentException("Invalid data size:" + Arrays.toString(data));
+ }
+ int result = 0;
+ for (int i = 0; i < data.length; ++i) {
+ int shift = (3 - i) * 8;
+ result |= ((data[i] & 0xFF) << shift);
+ }
+ return result;
+ }
+
+ @Override
+ void handleTimerEvent(int state) {
+ if (mState != state) {
+ Slog.w(TAG, "Timeout in invalid state:[Expected:" + mState + ", Actual:" + state + "]");
+ return;
+ }
+
+ tv().announceTimerRecordingResult(TIME_RECORDING_RESULT_EXTRA_CHECK_RECORDER_CONNECTION);
+ finish();
+ }
+}