Tuner FW: handle release frontend

This can unblock tune/scan CTS test cases.
If a frontend resource is acquired in a test case and not released,
it cannot be used by another test case.

Bug: 150952758
Test: atest android.media.tv.tuner.cts.TunerTest
Change-Id: Ib9bab003fc81fe008091a9d1aaefc43e454c3230
This commit is contained in:
shubang
2020-04-10 18:00:56 -07:00
committed by Amy Zhang
parent 2b40d3c462
commit 2f9cab383b
5 changed files with 91 additions and 8 deletions

View File

@@ -263,14 +263,14 @@ public class Tuner implements AutoCloseable {
} }
private void setFrontendInfoList() { private void setFrontendInfoList() {
List<Integer> ids = nativeGetFrontendIds(); List<Integer> ids = getFrontendIds();
if (ids == null) { if (ids == null) {
return; return;
} }
TunerFrontendInfo[] infos = new TunerFrontendInfo[ids.size()]; TunerFrontendInfo[] infos = new TunerFrontendInfo[ids.size()];
for (int i = 0; i < ids.size(); i++) { for (int i = 0; i < ids.size(); i++) {
int id = ids.get(i); int id = ids.get(i);
FrontendInfo frontendInfo = nativeGetFrontendInfo(id); FrontendInfo frontendInfo = getFrontendInfoById(id);
if (frontendInfo == null) { if (frontendInfo == null) {
continue; continue;
} }
@@ -281,6 +281,11 @@ public class Tuner implements AutoCloseable {
mTunerResourceManager.setFrontendInfoList(infos); mTunerResourceManager.setFrontendInfoList(infos);
} }
/** @hide */
public List<Integer> getFrontendIds() {
return nativeGetFrontendIds();
}
private void setLnbIds() { private void setLnbIds() {
int[] ids = nativeGetLnbIds(); int[] ids = nativeGetLnbIds();
if (ids == null) { if (ids == null) {
@@ -345,14 +350,17 @@ public class Tuner implements AutoCloseable {
@Override @Override
public void close() { public void close() {
if (mFrontendHandle != null) { if (mFrontendHandle != null) {
nativeCloseFrontendByHandle(mFrontendHandle);
mTunerResourceManager.releaseFrontend(mFrontendHandle); mTunerResourceManager.releaseFrontend(mFrontendHandle);
mFrontendHandle = null; mFrontendHandle = null;
mFrontend = null;
} }
if (mLnb != null) { if (mLnb != null) {
mTunerResourceManager.releaseLnb(mLnbHandle); mTunerResourceManager.releaseLnb(mLnbHandle);
mLnb = null; mLnb = null;
mLnbHandle = null;
} }
nativeClose(); TunerUtils.throwExceptionForResult(nativeClose(), "failed to close tuner");
} }
/** /**
@@ -374,6 +382,8 @@ public class Tuner implements AutoCloseable {
* Native method to open frontend of the given ID. * Native method to open frontend of the given ID.
*/ */
private native Frontend nativeOpenFrontendByHandle(int handle); private native Frontend nativeOpenFrontendByHandle(int handle);
@Result
private native int nativeCloseFrontendByHandle(int handle);
private native int nativeTune(int type, FrontendSettings settings); private native int nativeTune(int type, FrontendSettings settings);
private native int nativeStopTune(); private native int nativeStopTune();
private native int nativeScan(int settingsType, FrontendSettings settings, int scanType); private native int nativeScan(int settingsType, FrontendSettings settings, int scanType);
@@ -522,6 +532,7 @@ public class Tuner implements AutoCloseable {
public int tune(@NonNull FrontendSettings settings) { public int tune(@NonNull FrontendSettings settings) {
mFrontendType = settings.getType(); mFrontendType = settings.getType();
checkResource(TunerResourceManager.TUNER_RESOURCE_TYPE_FRONTEND); checkResource(TunerResourceManager.TUNER_RESOURCE_TYPE_FRONTEND);
mFrontendInfo = null; mFrontendInfo = null;
return nativeTune(settings.getType(), settings); return nativeTune(settings.getType(), settings);
} }
@@ -706,11 +717,16 @@ public class Tuner implements AutoCloseable {
throw new IllegalStateException("frontend is not initialized"); throw new IllegalStateException("frontend is not initialized");
} }
if (mFrontendInfo == null) { if (mFrontendInfo == null) {
mFrontendInfo = nativeGetFrontendInfo(mFrontend.mId); mFrontendInfo = getFrontendInfoById(mFrontend.mId);
} }
return mFrontendInfo; return mFrontendInfo;
} }
/** @hide */
public FrontendInfo getFrontendInfoById(int id) {
return nativeGetFrontendInfo(id);
}
/** /**
* Gets Demux capabilities. * Gets Demux capabilities.
* *

View File

@@ -416,11 +416,11 @@ public class TunerResourceManager {
* <p><strong>Note:</strong> {@link #setFrontendInfoList(TunerFrontendInfo[])} must be called * <p><strong>Note:</strong> {@link #setFrontendInfoList(TunerFrontendInfo[])} must be called
* before this release. * before this release.
* *
* @param frontendId the id of the released frontend. * @param frontendHandle the handle of the released frontend.
*/ */
public void releaseFrontend(int frontendId) { public void releaseFrontend(int frontendHandle) {
try { try {
mService.releaseFrontend(frontendId); mService.releaseFrontend(frontendHandle);
} catch (RemoteException e) { } catch (RemoteException e) {
throw e.rethrowFromSystemServer(); throw e.rethrowFromSystemServer();
} }

View File

@@ -833,6 +833,12 @@ JTuner::JTuner(JNIEnv *env, jobject thiz)
} }
JTuner::~JTuner() { JTuner::~JTuner() {
if (mFe != NULL) {
mFe->close();
}
if (mDemux != NULL) {
mDemux->close();
}
JNIEnv *env = AndroidRuntime::getJNIEnv(); JNIEnv *env = AndroidRuntime::getJNIEnv();
env->DeleteWeakGlobalRef(mObject); env->DeleteWeakGlobalRef(mObject);
@@ -908,6 +914,14 @@ jobject JTuner::openFrontendById(int id) {
(jint) jId); (jint) jId);
} }
jint JTuner::closeFrontendById(int id) {
if (mFe != NULL && mFeId == id) {
Result r = mFe->close();
return (jint) r;
}
return (jint) Result::SUCCESS;
}
jobject JTuner::getAnalogFrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps) { jobject JTuner::getAnalogFrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps) {
jclass clazz = env->FindClass("android/media/tv/tuner/frontend/AnalogFrontendCapabilities"); jclass clazz = env->FindClass("android/media/tv/tuner/frontend/AnalogFrontendCapabilities");
jmethodID capsInit = env->GetMethodID(clazz, "<init>", "(II)V"); jmethodID capsInit = env->GetMethodID(clazz, "<init>", "(II)V");
@@ -1271,6 +1285,23 @@ Result JTuner::openDemux() {
return res; return res;
} }
jint JTuner::close() {
Result res = Result::SUCCESS;
if (mFe != NULL) {
res = mFe->close();
if (res != Result::SUCCESS) {
return (jint) res;
}
}
if (mDemux != NULL) {
res = mDemux->close();
if (res != Result::SUCCESS) {
return (jint) res;
}
}
return (jint) res;
}
jobject JTuner::getAvSyncHwId(sp<Filter> filter) { jobject JTuner::getAvSyncHwId(sp<Filter> filter) {
if (mDemux == NULL) { if (mDemux == NULL) {
return NULL; return NULL;
@@ -2362,6 +2393,13 @@ static jobject android_media_tv_Tuner_open_frontend_by_handle(
return tuner->openFrontendById(id); return tuner->openFrontendById(id);
} }
static jint android_media_tv_Tuner_close_frontend_by_handle(
JNIEnv *env, jobject thiz, jint handle) {
sp<JTuner> tuner = getTuner(env, thiz);
uint32_t id = getResourceIdFromHandle(handle);
return tuner->closeFrontendById(id);
}
static int android_media_tv_Tuner_tune(JNIEnv *env, jobject thiz, jint type, jobject settings) { static int android_media_tv_Tuner_tune(JNIEnv *env, jobject thiz, jint type, jobject settings) {
sp<JTuner> tuner = getTuner(env, thiz); sp<JTuner> tuner = getTuner(env, thiz);
return tuner->tune(getFrontendSettings(env, type, settings)); return tuner->tune(getFrontendSettings(env, type, settings));
@@ -3135,6 +3173,11 @@ static jint android_media_tv_Tuner_open_demux(JNIEnv* env, jobject thiz, jint /*
return (jint) tuner->openDemux(); return (jint) tuner->openDemux();
} }
static jint android_media_tv_Tuner_close_tuner(JNIEnv* env, jobject thiz) {
sp<JTuner> tuner = getTuner(env, thiz);
return (jint) tuner->close();
}
static jint android_media_tv_Tuner_attach_filter(JNIEnv *env, jobject dvr, jobject filter) { static jint android_media_tv_Tuner_attach_filter(JNIEnv *env, jobject dvr, jobject filter) {
sp<Dvr> dvrSp = getDvr(env, dvr); sp<Dvr> dvrSp = getDvr(env, dvr);
if (dvrSp == NULL) { if (dvrSp == NULL) {
@@ -3424,6 +3467,8 @@ static const JNINativeMethod gTunerMethods[] = {
(void *)android_media_tv_Tuner_get_frontend_ids }, (void *)android_media_tv_Tuner_get_frontend_ids },
{ "nativeOpenFrontendByHandle", "(I)Landroid/media/tv/tuner/Tuner$Frontend;", { "nativeOpenFrontendByHandle", "(I)Landroid/media/tv/tuner/Tuner$Frontend;",
(void *)android_media_tv_Tuner_open_frontend_by_handle }, (void *)android_media_tv_Tuner_open_frontend_by_handle },
{ "nativeCloseFrontendByHandle", "(I)I",
(void *)android_media_tv_Tuner_close_frontend_by_handle },
{ "nativeTune", "(ILandroid/media/tv/tuner/frontend/FrontendSettings;)I", { "nativeTune", "(ILandroid/media/tv/tuner/frontend/FrontendSettings;)I",
(void *)android_media_tv_Tuner_tune }, (void *)android_media_tv_Tuner_tune },
{ "nativeStopTune", "()I", (void *)android_media_tv_Tuner_stop_tune }, { "nativeStopTune", "()I", (void *)android_media_tv_Tuner_stop_tune },
@@ -3460,6 +3505,7 @@ static const JNINativeMethod gTunerMethods[] = {
{ "nativeGetDemuxCapabilities", "()Landroid/media/tv/tuner/DemuxCapabilities;", { "nativeGetDemuxCapabilities", "()Landroid/media/tv/tuner/DemuxCapabilities;",
(void *)android_media_tv_Tuner_get_demux_caps }, (void *)android_media_tv_Tuner_get_demux_caps },
{ "nativeOpenDemuxByhandle", "(I)I", (void *)android_media_tv_Tuner_open_demux }, { "nativeOpenDemuxByhandle", "(I)I", (void *)android_media_tv_Tuner_open_demux },
{"nativeClose", "()I", (void *)android_media_tv_Tuner_close_tuner },
}; };
static const JNINativeMethod gFilterMethods[] = { static const JNINativeMethod gFilterMethods[] = {

View File

@@ -172,6 +172,7 @@ struct JTuner : public RefBase {
int disconnectCiCam(); int disconnectCiCam();
jobject getFrontendIds(); jobject getFrontendIds();
jobject openFrontendById(int id); jobject openFrontendById(int id);
jint closeFrontendById(int id);
jobject getFrontendInfo(int id); jobject getFrontendInfo(int id);
int tune(const FrontendSettings& settings); int tune(const FrontendSettings& settings);
int stopTune(); int stopTune();
@@ -189,6 +190,7 @@ struct JTuner : public RefBase {
jobject getDemuxCaps(); jobject getDemuxCaps();
jobject getFrontendStatus(jintArray types); jobject getFrontendStatus(jintArray types);
Result openDemux(); Result openDemux();
jint close();
protected: protected:
virtual ~JTuner(); virtual ~JTuner();

View File

@@ -247,12 +247,15 @@ public class TunerResourceManagerService extends SystemService {
} }
@Override @Override
public void releaseFrontend(int frontendId) { public void releaseFrontend(int frontendHandle) {
enforceTunerAccessPermission("releaseFrontend"); enforceTunerAccessPermission("releaseFrontend");
enforceTrmAccessPermission("releaseFrontend"); enforceTrmAccessPermission("releaseFrontend");
int frontendId = getResourceId(
TunerResourceManager.TUNER_RESOURCE_TYPE_FRONTEND, frontendHandle);
if (DEBUG) { if (DEBUG) {
Slog.d(TAG, "releaseFrontend(id=" + frontendId + ")"); Slog.d(TAG, "releaseFrontend(id=" + frontendId + ")");
} }
updateFrontendClientMappingOnRelease(frontendId);
} }
@Override @Override
@@ -568,6 +571,17 @@ public class TunerResourceManagerService extends SystemService {
} }
} }
private void updateFrontendClientMappingOnRelease(int frontendId) {
FrontendResource releasingFrontend = getFrontendResource(frontendId);
ClientProfile ownerProfile = getClientProfile(releasingFrontend.getOwnerClientId());
releasingFrontend.removeOwner();
ownerProfile.releaseFrontend(frontendId);
for (int exclusiveGroupMember : releasingFrontend.getExclusiveGroupMemberFeIds()) {
getFrontendResource(exclusiveGroupMember).removeOwner();
ownerProfile.releaseFrontend(frontendId);
}
}
/** /**
* Get the owner client's priority from the frontend id. * Get the owner client's priority from the frontend id.
* *
@@ -651,6 +665,11 @@ public class TunerResourceManagerService extends SystemService {
| (mResourceRequestCount++ & 0xffff); | (mResourceRequestCount++ & 0xffff);
} }
private int getResourceId(
@TunerResourceManager.TunerResourceType int resourceType, int resourceHandle) {
return (resourceHandle & 0x00ff0000) >> 16;
}
private void enforceTrmAccessPermission(String apiName) { private void enforceTrmAccessPermission(String apiName) {
getContext().enforceCallingPermission("android.permission.TUNER_RESOURCE_ACCESS", getContext().enforceCallingPermission("android.permission.TUNER_RESOURCE_ACCESS",
TAG + ": " + apiName); TAG + ": " + apiName);