Add new features to tuner.
*) Support scan unlock event
*) Support get frontend hardware info.
*) Add scIndexMask to MediaEvent.
*) Support more AAC formats.
*) Move Lna to ITuner.
Bug: 203389496
Bug: 184017033
Bug: 202978951
Bug: 205265630
Bug: 203623028
Test: atest android.media.tv.tuner.cts on AIDL and HILD HALs.
Change-Id: Id1bf4f13e7afb5f4264bfc67ca7d822848c6e803
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index a33d0a2..33deeb8 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -6382,6 +6382,7 @@
method public int getAvSyncHwId(@NonNull android.media.tv.tuner.filter.Filter);
method public long getAvSyncTime(int);
method @Nullable public java.util.List<android.media.tv.tuner.frontend.FrontendInfo> getAvailableFrontendInfos();
+ method @Nullable public String getCurrentFrontendHardwardInfo();
method @Nullable public android.media.tv.tuner.DemuxCapabilities getDemuxCapabilities();
method @Nullable public android.media.tv.tuner.frontend.FrontendInfo getFrontendInfo();
method @Nullable public android.media.tv.tuner.frontend.FrontendStatus getFrontendStatus(@NonNull int[]);
@@ -6546,6 +6547,10 @@
method public boolean isPassthrough();
method public boolean useSecureMemory();
field public static final int AUDIO_STREAM_TYPE_AAC = 6; // 0x6
+ field public static final int AUDIO_STREAM_TYPE_AAC_ADTS = 16; // 0x10
+ field public static final int AUDIO_STREAM_TYPE_AAC_HE_ADTS = 18; // 0x12
+ field public static final int AUDIO_STREAM_TYPE_AAC_HE_LATM = 19; // 0x13
+ field public static final int AUDIO_STREAM_TYPE_AAC_LATM = 17; // 0x11
field public static final int AUDIO_STREAM_TYPE_AC3 = 7; // 0x7
field public static final int AUDIO_STREAM_TYPE_AC4 = 9; // 0x9
field public static final int AUDIO_STREAM_TYPE_DRA = 15; // 0xf
@@ -6707,6 +6712,7 @@
method @IntRange(from=0) public int getMpuSequenceNumber();
method public long getOffset();
method public long getPts();
+ method public int getScIndexMask();
method public int getStreamId();
method public boolean isDtsPresent();
method public boolean isPrivateData();
@@ -7819,6 +7825,7 @@
method public void onScanStopped();
method public void onSignalTypeReported(int);
method public void onSymbolRatesReported(@NonNull int[]);
+ method public default void onUnLocked();
}
}
diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java
index 255b391b..97fe1b1 100644
--- a/media/java/android/media/tv/tuner/Tuner.java
+++ b/media/java/android/media/tv/tuner/Tuner.java
@@ -687,6 +687,7 @@
private native FrontendInfo nativeGetFrontendInfo(int id);
private native Filter nativeOpenFilter(int type, int subType, long bufferSize);
private native TimeFilter nativeOpenTimeFilter();
+ private native String nativeGetFrontendHardwareInfo();
private native Lnb nativeOpenLnbByHandle(int handle);
private native Lnb nativeOpenLnbByName(String name);
@@ -1278,6 +1279,34 @@
return Arrays.asList(feInfoList);
}
+ /**
+ * Gets the currently initialized and activated frontend hardware information. The return values
+ * would differ per device makers. E.g. RF chip version, Demod chip version, detailed status of
+ * dvbs blind scan, etc
+ *
+ * <p>This API is only supported by Tuner HAL 2.0 or higher. Unsupported version would return
+ * {@code null}. Use {@link TunerVersionChecker#getTunerVersion()} to check the version.
+ *
+ * @return The active frontend hardware information. {@code null} if the operation failed.
+ * @throws IllegalStateException if there is no active frontend currently.
+ */
+ @Nullable
+ public String getCurrentFrontendHardwardInfo() {
+ mFrontendLock.lock();
+ try {
+ if (!TunerVersionChecker.checkHigherOrEqualVersionTo(
+ TunerVersionChecker.TUNER_VERSION_2_0, "Get Frontend hardware info")) {
+ return null;
+ }
+ if (mFrontend == null) {
+ throw new IllegalStateException("frontend is not initialized");
+ }
+ return nativeGetFrontendHardwareInfo();
+ } finally {
+ mFrontendLock.unlock();
+ }
+ }
+
/** @hide */
public FrontendInfo getFrontendInfoById(int id) {
mFrontendLock.lock();
@@ -1353,6 +1382,24 @@
}
}
+ private void onUnLocked() {
+ Log.d(TAG, "Wrote Stats Log for unlocked event from scanning.");
+ FrameworkStatsLog.write(FrameworkStatsLog.TV_TUNER_STATE_CHANGED, mUserId,
+ FrameworkStatsLog.TV_TUNER_STATE_CHANGED__STATE__LOCKED);
+
+ synchronized (mScanCallbackLock) {
+ if (mScanCallbackExecutor != null && mScanCallback != null) {
+ mScanCallbackExecutor.execute(() -> {
+ synchronized (mScanCallbackLock) {
+ if (mScanCallback != null) {
+ mScanCallback.onUnLocked();
+ }
+ }
+ });
+ }
+ }
+ }
+
private void onScanStopped() {
synchronized (mScanCallbackLock) {
if (mScanCallbackExecutor != null && mScanCallback != null) {
diff --git a/media/java/android/media/tv/tuner/filter/AvSettings.java b/media/java/android/media/tv/tuner/filter/AvSettings.java
index ed04754..15811d2 100644
--- a/media/java/android/media/tv/tuner/filter/AvSettings.java
+++ b/media/java/android/media/tv/tuner/filter/AvSettings.java
@@ -107,7 +107,8 @@
AUDIO_STREAM_TYPE_AAC, AUDIO_STREAM_TYPE_AC3, AUDIO_STREAM_TYPE_EAC3,
AUDIO_STREAM_TYPE_AC4, AUDIO_STREAM_TYPE_DTS, AUDIO_STREAM_TYPE_DTS_HD,
AUDIO_STREAM_TYPE_WMA, AUDIO_STREAM_TYPE_OPUS, AUDIO_STREAM_TYPE_VORBIS,
- AUDIO_STREAM_TYPE_DRA})
+ AUDIO_STREAM_TYPE_DRA, AUDIO_STREAM_TYPE_AAC_ADTS, AUDIO_STREAM_TYPE_AAC_LATM,
+ AUDIO_STREAM_TYPE_AAC_HE_ADTS, AUDIO_STREAM_TYPE_AAC_HE_LATM})
@Retention(RetentionPolicy.SOURCE)
public @interface AudioStreamType {}
@@ -182,6 +183,41 @@
*/
public static final int AUDIO_STREAM_TYPE_DRA = android.hardware.tv.tuner.AudioStreamType.DRA;
+ /*
+ * AAC with ADTS (Audio Data Transport Format).
+ *
+ * This API is only supported by Tuner HAL 2.0 or higher. Use
+ * {@link TunerVersionChecker#getTunerVersion()} to check the version.
+ */
+ public static final int AUDIO_STREAM_TYPE_AAC_ADTS =
+ android.hardware.tv.tuner.AudioStreamType.AAC_ADTS;
+
+ /*
+ * AAC with ADTS with LATM (Low-overhead MPEG-4 Audio Transport Multiplex).
+ *
+ * This API is only supported by Tuner HAL 2.0 or higher. Use
+ * {@link TunerVersionChecker#getTunerVersion()} to check the version.
+ */
+ public static final int AUDIO_STREAM_TYPE_AAC_LATM =
+ android.hardware.tv.tuner.AudioStreamType.AAC_LATM;
+
+ /*
+ * High-Efficiency AAC (HE-AAC) with ADTS (Audio Data Transport Format).
+ *
+ * This API is only supported by Tuner HAL 2.0 or higher. Use
+ * {@link TunerVersionChecker#getTunerVersion()} to check the version.
+ */
+ public static final int AUDIO_STREAM_TYPE_AAC_HE_ADTS =
+ android.hardware.tv.tuner.AudioStreamType.AAC_HE_ADTS;
+
+ /*
+ * High-Efficiency AAC (HE-AAC) with LATM (Low-overhead MPEG-4 Audio Transport Multiplex).
+ *
+ * This API is only supported by Tuner HAL 2.0 or higher. Use
+ * {@link TunerVersionChecker#getTunerVersion()} to check the version.
+ */
+ public static final int AUDIO_STREAM_TYPE_AAC_HE_LATM =
+ android.hardware.tv.tuner.AudioStreamType.AAC_HE_LATM;
private final boolean mIsPassthrough;
private int mAudioStreamType = AUDIO_STREAM_TYPE_UNDEFINED;
diff --git a/media/java/android/media/tv/tuner/filter/MediaEvent.java b/media/java/android/media/tv/tuner/filter/MediaEvent.java
index 79d4062..d958db1 100644
--- a/media/java/android/media/tv/tuner/filter/MediaEvent.java
+++ b/media/java/android/media/tv/tuner/filter/MediaEvent.java
@@ -49,12 +49,14 @@
private final long mDataId;
private final int mMpuSequenceNumber;
private final boolean mIsPrivateData;
+ private final int mScIndexMask;
private final AudioDescriptor mExtraMetaData;
// This constructor is used by JNI code only
private MediaEvent(int streamId, boolean isPtsPresent, long pts, boolean isDtsPresent, long dts,
long dataLength, long offset, LinearBlock buffer, boolean isSecureMemory, long dataId,
- int mpuSequenceNumber, boolean isPrivateData, AudioDescriptor extraMetaData) {
+ int mpuSequenceNumber, boolean isPrivateData, int scIndexMask,
+ AudioDescriptor extraMetaData) {
mStreamId = streamId;
mIsPtsPresent = isPtsPresent;
mPts = pts;
@@ -67,6 +69,7 @@
mDataId = dataId;
mMpuSequenceNumber = mpuSequenceNumber;
mIsPrivateData = isPrivateData;
+ mScIndexMask = scIndexMask;
mExtraMetaData = extraMetaData;
}
@@ -194,6 +197,17 @@
}
/**
+ * Gets SC (Start Code) index mask.
+ *
+ * <p>This API is only supported by Tuner HAL 2.0 or higher. Unsupported version would return
+ * {@code 0}. Use {@link TunerVersionChecker#getTunerVersion()} to check the version.
+ */
+ @RecordSettings.ScIndexMask
+ public int getScIndexMask() {
+ return mScIndexMask;
+ }
+
+ /**
* Gets audio extra metadata.
*/
@Nullable
diff --git a/media/java/android/media/tv/tuner/frontend/ScanCallback.java b/media/java/android/media/tv/tuner/frontend/ScanCallback.java
index f61bd52..39406f5 100644
--- a/media/java/android/media/tv/tuner/frontend/ScanCallback.java
+++ b/media/java/android/media/tv/tuner/frontend/ScanCallback.java
@@ -31,6 +31,9 @@
/** Scan locked the signal. */
void onLocked();
+ /** Scan unlocked the signal. */
+ default void onUnLocked() {}
+
/** Scan stopped. */
void onScanStopped();
diff --git a/media/jni/android_media_tv_Tuner.cpp b/media/jni/android_media_tv_Tuner.cpp
index e91e238..a8e3288 100644
--- a/media/jni/android_media_tv_Tuner.cpp
+++ b/media/jni/android_media_tv_Tuner.cpp
@@ -604,9 +604,11 @@
const DemuxFilterEvent &event) {
JNIEnv *env = AndroidRuntime::getJNIEnv();
jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/MediaEvent");
- jmethodID eventInit = env->GetMethodID(eventClazz, "<init>",
- "(IZJZJJJLandroid/media/MediaCodec$LinearBlock;"
- "ZJIZLandroid/media/tv/tuner/filter/AudioDescriptor;)V");
+ jmethodID eventInit = env->GetMethodID(
+ eventClazz,
+ "<init>",
+ "(IZJZJJJLandroid/media/MediaCodec$LinearBlock;"
+ "ZJIZILandroid/media/tv/tuner/filter/AudioDescriptor;)V");
jfieldID eventContext = env->GetFieldID(eventClazz, "mNativeContext", "J");
const DemuxFilterMediaEvent &mediaEvent = event.get<DemuxFilterEvent::Tag::media>();
@@ -639,10 +641,20 @@
jlong avDataId = mediaEvent.avDataId;
jint mpuSequenceNumber = mediaEvent.mpuSequenceNumber;
jboolean isPesPrivateData = mediaEvent.isPesPrivateData;
+ jint sc = 0;
+ if (mediaEvent.scIndexMask.getTag() == DemuxFilterScIndexMask::Tag::scIndex) {
+ sc = mediaEvent.scIndexMask.get<DemuxFilterScIndexMask::Tag::scIndex>();
+ } else if (mediaEvent.scIndexMask.getTag() == DemuxFilterScIndexMask::Tag::scHevc) {
+ sc = mediaEvent.scIndexMask.get<DemuxFilterScIndexMask::Tag::scHevc>();
+ } else if (mediaEvent.scIndexMask.getTag() == DemuxFilterScIndexMask::Tag::scAvc) {
+ sc = mediaEvent.scIndexMask.get<DemuxFilterScIndexMask::Tag::scAvc>();
+ // Java uses the values defined by HIDL HAL. Left shift 4 bits.
+ sc = sc << 4;
+ }
jobject obj = env->NewObject(eventClazz, eventInit, streamId, isPtsPresent, pts, isDtsPresent,
dts, dataLength, offset, nullptr, isSecureMemory, avDataId,
- mpuSequenceNumber, isPesPrivateData, audioDescriptor);
+ mpuSequenceNumber, isPesPrivateData, sc, audioDescriptor);
uint64_t avSharedMemSize = mFilterClient->getAvSharedHandleInfo().size;
if (mediaEvent.avMemory.fds.size() > 0 || mediaEvent.avDataId != 0 ||
@@ -1025,6 +1037,10 @@
env->CallVoidMethod(
frontend,
env->GetMethodID(clazz, "onLocked", "()V"));
+ } else {
+ env->CallVoidMethod(
+ frontend,
+ env->GetMethodID(clazz, "onUnLocked", "()V"));
}
break;
}
@@ -1540,6 +1556,15 @@
maxSymbolRate, acquireRange, exclusiveGroupId, statusCaps, jcaps);
}
+Result JTuner::getFrontendHardwareInfo(string &info) {
+ if (mFeClient == nullptr) {
+ ALOGE("frontend is not initialized");
+ return Result::INVALID_STATE;
+ }
+
+ return mFeClient->getHardwareInfo(info);
+}
+
jobject JTuner::openLnbByHandle(int handle) {
if (mTunerClient == nullptr) {
return nullptr;
@@ -1649,11 +1674,10 @@
}
int JTuner::setLna(bool enable) {
- if (mFeClient == nullptr) {
- ALOGE("frontend client is not initialized");
- return (int)Result::INVALID_STATE;
+ if (mTunerClient == nullptr) {
+ return (int)Result::NOT_INITIALIZED;
}
- Result result = mFeClient->setLna(enable);
+ Result result = mTunerClient->setLna(enable);
return (int)result;
}
@@ -4195,6 +4219,16 @@
return filterObj;
}
+static jstring android_media_tv_Tuner_get_frontend_hardware_info(JNIEnv *env, jobject thiz) {
+ sp<JTuner> tuner = getTuner(env, thiz);
+ string info;
+ Result r = tuner->getFrontendHardwareInfo(info);
+ if (r != Result::SUCCESS) {
+ return nullptr;
+ }
+ return env->NewStringUTF(info.data());
+}
+
static jint android_media_tv_Tuner_close_frontend(JNIEnv* env, jobject thiz, jint /* handle */) {
sp<JTuner> tuner = getTuner(env, thiz);
return tuner->closeFrontend();
@@ -4504,6 +4538,8 @@
{ "nativeOpenSharedFilter",
"(Ljava/lang/String;)Landroid/media/tv/tuner/filter/SharedFilter;",
(void *)android_media_tv_Tuner_open_shared_filter},
+ { "nativeGetFrontendHardwareInfo","()Ljava/lang/String;",
+ (void *)android_media_tv_Tuner_get_frontend_hardware_info },
};
static const JNINativeMethod gFilterMethods[] = {
diff --git a/media/jni/android_media_tv_Tuner.h b/media/jni/android_media_tv_Tuner.h
index 06e2492..4cad92b 100644
--- a/media/jni/android_media_tv_Tuner.h
+++ b/media/jni/android_media_tv_Tuner.h
@@ -200,6 +200,7 @@
jint close();
jint closeFrontend();
jint closeDemux();
+ Result getFrontendHardwareInfo(string& info);
jweak getObject();
diff --git a/media/jni/tuner/FrontendClient.cpp b/media/jni/tuner/FrontendClient.cpp
index 70309a0..0fdd8d8 100644
--- a/media/jni/tuner/FrontendClient.cpp
+++ b/media/jni/tuner/FrontendClient.cpp
@@ -102,15 +102,6 @@
return Result::INVALID_STATE;
}
-Result FrontendClient::setLna(bool bEnable) {
- if (mTunerFrontend != nullptr) {
- Status s = mTunerFrontend->setLna(bEnable);
- return ClientHelper::getServiceSpecificErrorCode(s);
- }
-
- return Result::INVALID_STATE;
-}
-
int32_t FrontendClient::linkCiCamToFrontend(int32_t ciCamId) {
int32_t ltsId = static_cast<int32_t>(Constant::INVALID_LTS_ID);
@@ -143,6 +134,15 @@
return Result::INVALID_STATE;
}
+Result FrontendClient::getHardwareInfo(string& info) {
+ if (mTunerFrontend != nullptr) {
+ Status s = mTunerFrontend->getHardwareInfo(&info);
+ return ClientHelper::getServiceSpecificErrorCode(s);
+ }
+
+ return Result::INVALID_STATE;
+}
+
shared_ptr<ITunerFrontend> FrontendClient::getAidlFrontend() {
return mTunerFrontend;
}
diff --git a/media/jni/tuner/FrontendClient.h b/media/jni/tuner/FrontendClient.h
index 08c0b20..77d9098 100644
--- a/media/jni/tuner/FrontendClient.h
+++ b/media/jni/tuner/FrontendClient.h
@@ -99,11 +99,6 @@
Result setLnb(sp<LnbClient> lnbClient);
/**
- * Enable or Disable Low Noise Amplifier (LNA).
- */
- Result setLna(bool bEnable);
-
- /**
* Link Frontend to the cicam with given id.
*
* @return lts id
@@ -120,7 +115,13 @@
*/
Result close();
+ /**
+ * Get Frontend hardware info.
+ */
+ Result getHardwareInfo(string& info);
+
int32_t getId();
+
shared_ptr<ITunerFrontend> getAidlFrontend();
private:
/**
diff --git a/media/jni/tuner/TunerClient.cpp b/media/jni/tuner/TunerClient.cpp
index 861d78d..f917f01 100644
--- a/media/jni/tuner/TunerClient.cpp
+++ b/media/jni/tuner/TunerClient.cpp
@@ -185,4 +185,13 @@
return nullptr;
}
+Result TunerClient::setLna(bool bEnable) {
+ if (mTunerService != nullptr) {
+ Status s = mTunerService->setLna(bEnable);
+ return ClientHelper::getServiceSpecificErrorCode(s);
+ }
+
+ return Result::INVALID_STATE;
+}
+
} // namespace android
diff --git a/media/jni/tuner/TunerClient.h b/media/jni/tuner/TunerClient.h
index 3e59e26..37b8ee1 100644
--- a/media/jni/tuner/TunerClient.h
+++ b/media/jni/tuner/TunerClient.h
@@ -127,6 +127,11 @@
*/
sp<FilterClient> openSharedFilter(const string& filterToken, sp<FilterClientCallback> cb);
+ /**
+ * Enable or Disable Low Noise Amplifier (LNA).
+ */
+ Result setLna(bool bEnable);
+
private:
/**
* An AIDL Tuner Service Singleton assigned at the first time the Tuner Client