diff --git a/api/system-current.txt b/api/system-current.txt index 2e53058f96d25..648be0d74bae4 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -5036,6 +5036,7 @@ package android.media.tv.tuner { 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[]); + method public int linkFrontendToCiCam(int); method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_TV_DESCRAMBLER) public android.media.tv.tuner.Descrambler openDescrambler(); method @Nullable public android.media.tv.tuner.dvr.DvrPlayback openDvrPlayback(long, @NonNull java.util.concurrent.Executor, @NonNull android.media.tv.tuner.dvr.OnPlaybackStatusChangedListener); method @Nullable public android.media.tv.tuner.dvr.DvrRecorder openDvrRecorder(long, @NonNull java.util.concurrent.Executor, @NonNull android.media.tv.tuner.dvr.OnRecordStatusChangedListener); @@ -5049,10 +5050,12 @@ package android.media.tv.tuner { method public void setResourceLostListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.tv.tuner.Tuner.OnResourceLostListener); method public void shareFrontendFromTuner(@NonNull android.media.tv.tuner.Tuner); method public int tune(@NonNull android.media.tv.tuner.frontend.FrontendSettings); + method public int unlinkFrontendToCiCam(int); method public void updateResourcePriority(int, int); field public static final int INVALID_AV_SYNC_ID = -1; // 0xffffffff field public static final int INVALID_FILTER_ID = -1; // 0xffffffff field public static final long INVALID_FILTER_ID_64BIT = -1L; // 0xffffffffffffffffL + field public static final int INVALID_LTS_ID = -1; // 0xffffffff field public static final int INVALID_MMTP_RECORD_EVENT_MPT_SEQUENCE_NUM = -1; // 0xffffffff field public static final int INVALID_STREAM_ID = 65535; // 0xffff field public static final long INVALID_TIMESTAMP = -1L; // 0xffffffffffffffffL diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java index 27a49a75c6d00..867eab017a284 100644 --- a/media/java/android/media/tv/tuner/Tuner.java +++ b/media/java/android/media/tv/tuner/Tuner.java @@ -121,6 +121,16 @@ public class Tuner implements AutoCloseable { public static final int INVALID_MMTP_RECORD_EVENT_MPT_SEQUENCE_NUM = android.hardware.tv.tuner.V1_1.Constants.Constant .INVALID_MMTP_RECORD_EVENT_MPT_SEQUENCE_NUM; + /** + * Invalid local transport stream id. + * + *

Returned by {@link #linkFrontendToCiCam(int)} when the requested failed + * or the hal implementation does not support the operation. + * + * @see #linkFrontendToCiCam(int) + */ + public static final int INVALID_LTS_ID = + android.hardware.tv.tuner.V1_1.Constants.Constant.INVALID_LTS_ID; /** * Invalid 64-bit filter ID. */ @@ -475,7 +485,9 @@ public class Tuner implements AutoCloseable { private native Integer nativeGetAvSyncHwId(Filter filter); private native Long nativeGetAvSyncTime(int avSyncId); private native int nativeConnectCiCam(int ciCamId); + private native int nativeLinkCiCam(int ciCamId); private native int nativeDisconnectCiCam(); + private native int nativeUnlinkCiCam(int ciCamId); private native FrontendInfo nativeGetFrontendInfo(int id); private native Filter nativeOpenFilter(int type, int subType, long bufferSize); private native TimeFilter nativeOpenTimeFilter(); @@ -797,6 +809,33 @@ public class Tuner implements AutoCloseable { return RESULT_UNAVAILABLE; } + /** + * Link Conditional Access Modules (CAM) Frontend to support Common Interface (CI) by-pass mode. + * + *

It is used by the client to link CI-CAM to a Frontend. CI by-pass mode requires that + * the CICAM also receives the TS concurrently from the frontend when the Demux is receiving + * the TS directly from the frontend. + * + *

Use {@link #unlinkFrontendToCicam(int)} to disconnect. + * + *

This API is only supported by Tuner HAL 1.1 or higher. Unsupported version would cause + * no-op and return {@link INVALID_LTS_ID}. Use {@link TunerVersionChecker.getTunerVersion()} to + * check the version. + * + * @param ciCamId specify CI-CAM Id to link. + * @return Local transport stream id when connection is successfully established. Failed + * operation returns {@link INVALID_LTS_ID}. + */ + public int linkFrontendToCiCam(int ciCamId) { + if (TunerVersionChecker.checkHigherOrEqualVersionTo(TunerVersionChecker.TUNER_VERSION_1_1, + "linkFrontendToCiCam")) { + if (checkResource(TunerResourceManager.TUNER_RESOURCE_TYPE_FRONTEND)) { + return nativeLinkCiCam(ciCamId); + } + } + return INVALID_LTS_ID; + } + /** * Disconnects Conditional Access Modules (CAM) * @@ -812,6 +851,28 @@ public class Tuner implements AutoCloseable { return RESULT_UNAVAILABLE; } + /** + * Unlink Conditional Access Modules (CAM) Frontend. + * + *

It is used by the client to unlink CI-CAM to a Frontend. + * + *

This API is only supported by Tuner HAL 1.1 or higher. Unsupported version would cause + * no-op. Use {@link TunerVersionChecker.getTunerVersion()} to check the version. + * + * @param ciCamId specify CI-CAM Id to unlink. + * @return result status of the operation. + */ + @Result + public int unlinkFrontendToCiCam(int ciCamId) { + if (TunerVersionChecker.checkHigherOrEqualVersionTo(TunerVersionChecker.TUNER_VERSION_1_1, + "unlinkFrontendToCiCam")) { + if (checkResource(TunerResourceManager.TUNER_RESOURCE_TYPE_FRONTEND)) { + return nativeUnlinkCiCam(ciCamId); + } + } + return RESULT_UNAVAILABLE; + } + /** * Gets the frontend information. * diff --git a/media/jni/android_media_tv_Tuner.cpp b/media/jni/android_media_tv_Tuner.cpp index e0afe29de7e69..05ea512ea970b 100644 --- a/media/jni/android_media_tv_Tuner.cpp +++ b/media/jni/android_media_tv_Tuner.cpp @@ -1034,6 +1034,7 @@ jobject JTuner::openFrontendById(int id) { return NULL; } mFe = fe; + mFe_1_1 = ::android::hardware::tv::tuner::V1_1::IFrontend::castFrom(mFe); mFeId = id; if (mDemux != NULL) { mDemux->setFrontendDataSource(mFeId); @@ -1493,6 +1494,27 @@ int JTuner::connectCiCam(jint id) { return (int) r; } +int JTuner::linkCiCam(int id) { + if (mFe_1_1 == NULL) { + ALOGE("frontend 1.1 is not initialized"); + return (int)Constant::INVALID_LTS_ID; + } + + Result res; + uint32_t ltsId; + mFe_1_1->linkCiCam(static_cast(id), + [&](Result r, uint32_t id) { + res = r; + ltsId = id; + }); + + if (res != Result::SUCCESS) { + return (int)Constant::INVALID_LTS_ID; + } + + return (int) ltsId; +} + int JTuner::disconnectCiCam() { if (mDemux == NULL) { Result r = openDemux(); @@ -1504,6 +1526,18 @@ int JTuner::disconnectCiCam() { return (int) r; } + +int JTuner::unlinkCiCam(int id) { + if (mFe_1_1 == NULL) { + ALOGE("frontend 1.1 is not initialized"); + return (int)Result::INVALID_STATE; + } + + Result r = mFe_1_1->unlinkCiCam(static_cast(id)); + + return (int) r; +} + jobject JTuner::openDescrambler() { ALOGD("JTuner::openDescrambler"); if (mTuner == nullptr || mDemux == nullptr) { @@ -1947,6 +1981,10 @@ jint JTuner::closeFrontend() { if (mFe != NULL) { r = mFe->close(); } + if (r == Result::SUCCESS) { + mFe = NULL; + mFe_1_1 = NULL; + } return (jint) r; } @@ -1955,6 +1993,9 @@ jint JTuner::closeDemux() { if (mDemux != NULL) { r = mDemux->close(); } + if (r == Result::SUCCESS) { + mDemux = NULL; + } return (jint) r; } @@ -2629,11 +2670,21 @@ static int android_media_tv_Tuner_connect_cicam(JNIEnv *env, jobject thiz, jint return tuner->connectCiCam(id); } +static int android_media_tv_Tuner_link_cicam(JNIEnv *env, jobject thiz, jint id) { + sp tuner = getTuner(env, thiz); + return tuner->linkCiCam(id); +} + static int android_media_tv_Tuner_disconnect_cicam(JNIEnv *env, jobject thiz) { sp tuner = getTuner(env, thiz); return tuner->disconnectCiCam(); } +static int android_media_tv_Tuner_unlink_cicam(JNIEnv *env, jobject thiz, jint id) { + sp tuner = getTuner(env, thiz); + return tuner->unlinkCiCam(id); +} + static jobject android_media_tv_Tuner_get_frontend_info(JNIEnv *env, jobject thiz, jint id) { sp tuner = getTuner(env, thiz); return tuner->getFrontendInfo(id); @@ -3786,6 +3837,10 @@ static const JNINativeMethod gTunerMethods[] = { { "nativeGetAvSyncTime", "(I)Ljava/lang/Long;", (void *)android_media_tv_Tuner_get_av_sync_time }, { "nativeConnectCiCam", "(I)I", (void *)android_media_tv_Tuner_connect_cicam }, + { "nativeLinkCiCam", "(I)I", + (void *)android_media_tv_Tuner_link_cicam }, + { "nativeUnlinkCiCam", "(I)I", + (void *)android_media_tv_Tuner_unlink_cicam }, { "nativeDisconnectCiCam", "()I", (void *)android_media_tv_Tuner_disconnect_cicam }, { "nativeGetFrontendInfo", "(I)Landroid/media/tv/tuner/frontend/FrontendInfo;", (void *)android_media_tv_Tuner_get_frontend_info }, diff --git a/media/jni/android_media_tv_Tuner.h b/media/jni/android_media_tv_Tuner.h index d7dc600a166b1..3cd1564b70898 100644 --- a/media/jni/android_media_tv_Tuner.h +++ b/media/jni/android_media_tv_Tuner.h @@ -19,6 +19,7 @@ #include #include +#include #include #include @@ -207,7 +208,9 @@ struct JTuner : public RefBase { jobject getAvSyncHwId(sp filter); jobject getAvSyncTime(jint id); int connectCiCam(jint id); + int linkCiCam(jint id); int disconnectCiCam(); + int unlinkCiCam(jint id); jobject getFrontendIds(); jobject openFrontendById(int id); jint closeFrontendById(int id); @@ -245,6 +248,7 @@ private: static int mTunerVersion; hidl_vec mFeIds; sp mFe; + sp<::android::hardware::tv::tuner::V1_1::IFrontend> mFe_1_1; int mFeId; hidl_vec mLnbIds; sp mLnb; diff --git a/non-updatable-api/system-current.txt b/non-updatable-api/system-current.txt index 75e038be1a2b9..900f68b02be92 100644 --- a/non-updatable-api/system-current.txt +++ b/non-updatable-api/system-current.txt @@ -4976,6 +4976,7 @@ package android.media.tv.tuner { 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[]); + method public int linkFrontendToCiCam(int); method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_TV_DESCRAMBLER) public android.media.tv.tuner.Descrambler openDescrambler(); method @Nullable public android.media.tv.tuner.dvr.DvrPlayback openDvrPlayback(long, @NonNull java.util.concurrent.Executor, @NonNull android.media.tv.tuner.dvr.OnPlaybackStatusChangedListener); method @Nullable public android.media.tv.tuner.dvr.DvrRecorder openDvrRecorder(long, @NonNull java.util.concurrent.Executor, @NonNull android.media.tv.tuner.dvr.OnRecordStatusChangedListener); @@ -4989,10 +4990,12 @@ package android.media.tv.tuner { method public void setResourceLostListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.tv.tuner.Tuner.OnResourceLostListener); method public void shareFrontendFromTuner(@NonNull android.media.tv.tuner.Tuner); method public int tune(@NonNull android.media.tv.tuner.frontend.FrontendSettings); + method public int unlinkFrontendToCiCam(int); method public void updateResourcePriority(int, int); field public static final int INVALID_AV_SYNC_ID = -1; // 0xffffffff field public static final int INVALID_FILTER_ID = -1; // 0xffffffff field public static final long INVALID_FILTER_ID_64BIT = -1L; // 0xffffffffffffffffL + field public static final int INVALID_LTS_ID = -1; // 0xffffffff field public static final int INVALID_MMTP_RECORD_EVENT_MPT_SEQUENCE_NUM = -1; // 0xffffffff field public static final int INVALID_STREAM_ID = 65535; // 0xffff field public static final long INVALID_TIMESTAMP = -1L; // 0xffffffffffffffffL