summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--media/java/android/media/tv/tuner/Tuner.java24
-rw-r--r--media/java/android/media/tv/tunerresourcemanager/TunerResourceManager.java6
-rw-r--r--media/jni/android_media_tv_Tuner.cpp46
-rw-r--r--media/jni/android_media_tv_Tuner.h2
-rw-r--r--services/core/java/com/android/server/tv/tunerresourcemanager/ClientProfile.java2
-rw-r--r--services/core/java/com/android/server/tv/tunerresourcemanager/TunerResourceManagerService.java50
-rw-r--r--services/tests/servicestests/src/com/android/server/tv/tunerresourcemanager/TunerResourceManagerServiceTest.java77
7 files changed, 178 insertions, 29 deletions
diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java
index 861eeea3bc34..fdd64f96701c 100644
--- a/media/java/android/media/tv/tuner/Tuner.java
+++ b/media/java/android/media/tv/tuner/Tuner.java
@@ -263,14 +263,14 @@ public class Tuner implements AutoCloseable {
}
private void setFrontendInfoList() {
- List<Integer> ids = nativeGetFrontendIds();
+ List<Integer> ids = getFrontendIds();
if (ids == null) {
return;
}
TunerFrontendInfo[] infos = new TunerFrontendInfo[ids.size()];
for (int i = 0; i < ids.size(); i++) {
int id = ids.get(i);
- FrontendInfo frontendInfo = nativeGetFrontendInfo(id);
+ FrontendInfo frontendInfo = getFrontendInfoById(id);
if (frontendInfo == null) {
continue;
}
@@ -281,6 +281,11 @@ public class Tuner implements AutoCloseable {
mTunerResourceManager.setFrontendInfoList(infos);
}
+ /** @hide */
+ public List<Integer> getFrontendIds() {
+ return nativeGetFrontendIds();
+ }
+
private void setLnbIds() {
int[] ids = nativeGetLnbIds();
if (ids == null) {
@@ -345,14 +350,17 @@ public class Tuner implements AutoCloseable {
@Override
public void close() {
if (mFrontendHandle != null) {
+ nativeCloseFrontendByHandle(mFrontendHandle);
mTunerResourceManager.releaseFrontend(mFrontendHandle);
mFrontendHandle = null;
+ mFrontend = null;
}
if (mLnb != null) {
mTunerResourceManager.releaseLnb(mLnbHandle);
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.
*/
private native Frontend nativeOpenFrontendByHandle(int handle);
+ @Result
+ private native int nativeCloseFrontendByHandle(int handle);
private native int nativeTune(int type, FrontendSettings settings);
private native int nativeStopTune();
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) {
mFrontendType = settings.getType();
checkResource(TunerResourceManager.TUNER_RESOURCE_TYPE_FRONTEND);
+
mFrontendInfo = null;
return nativeTune(settings.getType(), settings);
}
@@ -706,11 +717,16 @@ public class Tuner implements AutoCloseable {
throw new IllegalStateException("frontend is not initialized");
}
if (mFrontendInfo == null) {
- mFrontendInfo = nativeGetFrontendInfo(mFrontend.mId);
+ mFrontendInfo = getFrontendInfoById(mFrontend.mId);
}
return mFrontendInfo;
}
+ /** @hide */
+ public FrontendInfo getFrontendInfoById(int id) {
+ return nativeGetFrontendInfo(id);
+ }
+
/**
* Gets Demux capabilities.
*
diff --git a/media/java/android/media/tv/tunerresourcemanager/TunerResourceManager.java b/media/java/android/media/tv/tunerresourcemanager/TunerResourceManager.java
index 2c8899cfca78..a9f3dcf150cb 100644
--- a/media/java/android/media/tv/tunerresourcemanager/TunerResourceManager.java
+++ b/media/java/android/media/tv/tunerresourcemanager/TunerResourceManager.java
@@ -416,11 +416,11 @@ public class TunerResourceManager {
* <p><strong>Note:</strong> {@link #setFrontendInfoList(TunerFrontendInfo[])} must be called
* 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 {
- mService.releaseFrontend(frontendId);
+ mService.releaseFrontend(frontendHandle);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/media/jni/android_media_tv_Tuner.cpp b/media/jni/android_media_tv_Tuner.cpp
index 7579ca58b37b..909394fbc495 100644
--- a/media/jni/android_media_tv_Tuner.cpp
+++ b/media/jni/android_media_tv_Tuner.cpp
@@ -833,6 +833,12 @@ JTuner::JTuner(JNIEnv *env, jobject thiz)
}
JTuner::~JTuner() {
+ if (mFe != NULL) {
+ mFe->close();
+ }
+ if (mDemux != NULL) {
+ mDemux->close();
+ }
JNIEnv *env = AndroidRuntime::getJNIEnv();
env->DeleteWeakGlobalRef(mObject);
@@ -908,6 +914,14 @@ jobject JTuner::openFrontendById(int id) {
(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) {
jclass clazz = env->FindClass("android/media/tv/tuner/frontend/AnalogFrontendCapabilities");
jmethodID capsInit = env->GetMethodID(clazz, "<init>", "(II)V");
@@ -1271,6 +1285,23 @@ Result JTuner::openDemux() {
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) {
if (mDemux == NULL) {
return NULL;
@@ -2362,6 +2393,13 @@ static jobject android_media_tv_Tuner_open_frontend_by_handle(
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) {
sp<JTuner> tuner = getTuner(env, thiz);
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();
}
+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) {
sp<Dvr> dvrSp = getDvr(env, dvr);
if (dvrSp == NULL) {
@@ -3424,6 +3467,8 @@ static const JNINativeMethod gTunerMethods[] = {
(void *)android_media_tv_Tuner_get_frontend_ids },
{ "nativeOpenFrontendByHandle", "(I)Landroid/media/tv/tuner/Tuner$Frontend;",
(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",
(void *)android_media_tv_Tuner_tune },
{ "nativeStopTune", "()I", (void *)android_media_tv_Tuner_stop_tune },
@@ -3460,6 +3505,7 @@ static const JNINativeMethod gTunerMethods[] = {
{ "nativeGetDemuxCapabilities", "()Landroid/media/tv/tuner/DemuxCapabilities;",
(void *)android_media_tv_Tuner_get_demux_caps },
{ "nativeOpenDemuxByhandle", "(I)I", (void *)android_media_tv_Tuner_open_demux },
+ {"nativeClose", "()I", (void *)android_media_tv_Tuner_close_tuner },
};
static const JNINativeMethod gFilterMethods[] = {
diff --git a/media/jni/android_media_tv_Tuner.h b/media/jni/android_media_tv_Tuner.h
index 6749ba085739..750b146dbd59 100644
--- a/media/jni/android_media_tv_Tuner.h
+++ b/media/jni/android_media_tv_Tuner.h
@@ -172,6 +172,7 @@ struct JTuner : public RefBase {
int disconnectCiCam();
jobject getFrontendIds();
jobject openFrontendById(int id);
+ jint closeFrontendById(int id);
jobject getFrontendInfo(int id);
int tune(const FrontendSettings& settings);
int stopTune();
@@ -189,6 +190,7 @@ struct JTuner : public RefBase {
jobject getDemuxCaps();
jobject getFrontendStatus(jintArray types);
Result openDemux();
+ jint close();
protected:
virtual ~JTuner();
diff --git a/services/core/java/com/android/server/tv/tunerresourcemanager/ClientProfile.java b/services/core/java/com/android/server/tv/tunerresourcemanager/ClientProfile.java
index e100ff816f00..dfd23df40374 100644
--- a/services/core/java/com/android/server/tv/tunerresourcemanager/ClientProfile.java
+++ b/services/core/java/com/android/server/tv/tunerresourcemanager/ClientProfile.java
@@ -131,7 +131,7 @@ public final class ClientProfile {
mUsingFrontendIds.add(frontendId);
}
- public Iterable<Integer> getInUseFrontendIds() {
+ public Set<Integer> getInUseFrontendIds() {
return mUsingFrontendIds;
}
diff --git a/services/core/java/com/android/server/tv/tunerresourcemanager/TunerResourceManagerService.java b/services/core/java/com/android/server/tv/tunerresourcemanager/TunerResourceManagerService.java
index 6dded00321b5..fd2445f8366e 100644
--- a/services/core/java/com/android/server/tv/tunerresourcemanager/TunerResourceManagerService.java
+++ b/services/core/java/com/android/server/tv/tunerresourcemanager/TunerResourceManagerService.java
@@ -243,15 +243,20 @@ public class TunerResourceManagerService extends SystemService {
if (DEBUG) {
Slog.d(TAG, "requestLnb(request=" + request + ")");
}
+
return true;
}
@Override
- public void releaseFrontend(int frontendId) {
+ public void releaseFrontend(int frontendHandle) throws RemoteException {
enforceTunerAccessPermission("releaseFrontend");
enforceTrmAccessPermission("releaseFrontend");
- if (DEBUG) {
- Slog.d(TAG, "releaseFrontend(id=" + frontendId + ")");
+ if (!validateResourceHandle(TunerResourceManager.TUNER_RESOURCE_TYPE_FRONTEND,
+ frontendHandle)) {
+ throw new RemoteException("frontendHandle can't be invalid");
+ }
+ synchronized (mLock) {
+ releaseFrontendInternal(getResourceIdFromHandle(frontendHandle));
}
}
@@ -393,7 +398,6 @@ public class TunerResourceManagerService extends SystemService {
}
}
- // TODO check if the removing resource is in use or not. Handle the conflict.
for (int removingId : updatingFrontendIds) {
// update the exclusive group id member list
removeFrontendResource(removingId);
@@ -464,6 +468,14 @@ public class TunerResourceManagerService extends SystemService {
}
@VisibleForTesting
+ void releaseFrontendInternal(int frontendId) {
+ if (DEBUG) {
+ Slog.d(TAG, "releaseFrontend(id=" + frontendId + ")");
+ }
+ updateFrontendClientMappingOnRelease(frontendId);
+ }
+
+ @VisibleForTesting
boolean requestDemuxInternal(TunerDemuxRequest request, int[] demuxHandle) {
if (DEBUG) {
Slog.d(TAG, "requestDemux(request=" + request + ")");
@@ -568,6 +580,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(exclusiveGroupMember);
+ }
+ }
+
/**
* Get the owner client's priority from the frontend id.
*
@@ -609,6 +632,9 @@ public class TunerResourceManagerService extends SystemService {
private void removeFrontendResource(int removingId) {
FrontendResource fe = getFrontendResource(removingId);
+ if (fe.isInUse()) {
+ releaseFrontendInternal(removingId);
+ }
for (int excGroupmemberFeId : fe.getExclusiveGroupMemberFeIds()) {
getFrontendResource(excGroupmemberFeId)
.removeExclusiveGroupMemberFeId(fe.getId());
@@ -651,6 +677,22 @@ public class TunerResourceManagerService extends SystemService {
| (mResourceRequestCount++ & 0xffff);
}
+ @VisibleForTesting
+ protected int getResourceIdFromHandle(int resourceHandle) {
+ if (resourceHandle == TunerResourceManager.INVALID_RESOURCE_HANDLE) {
+ return resourceHandle;
+ }
+ return (resourceHandle & 0x00ff0000) >> 16;
+ }
+
+ private boolean validateResourceHandle(int resourceType, int resourceHandle) {
+ if (resourceHandle == TunerResourceManager.INVALID_RESOURCE_HANDLE
+ || ((resourceHandle & 0xff000000) >> 24) != resourceType) {
+ return false;
+ }
+ return true;
+ }
+
private void enforceTrmAccessPermission(String apiName) {
getContext().enforceCallingPermission("android.permission.TUNER_RESOURCE_ACCESS",
TAG + ": " + apiName);
diff --git a/services/tests/servicestests/src/com/android/server/tv/tunerresourcemanager/TunerResourceManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/tv/tunerresourcemanager/TunerResourceManagerServiceTest.java
index fcbd5072ae35..13248a00c1b0 100644
--- a/services/tests/servicestests/src/com/android/server/tv/tunerresourcemanager/TunerResourceManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/tv/tunerresourcemanager/TunerResourceManagerServiceTest.java
@@ -96,13 +96,6 @@ public class TunerResourceManagerServiceTest {
}
};
- private static int getResourceIdFromHandle(int resourceHandle) {
- if (resourceHandle == TunerResourceManager.INVALID_RESOURCE_HANDLE) {
- return resourceHandle;
- }
- return (resourceHandle & 0x00ff0000) >> 16;
- }
-
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
@@ -247,7 +240,7 @@ public class TunerResourceManagerServiceTest {
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
- assertThat(getResourceIdFromHandle(frontendHandle[0]))
+ assertThat(mTunerResourceManagerService.getResourceIdFromHandle(frontendHandle[0]))
.isEqualTo(TunerResourceManager.INVALID_RESOURCE_HANDLE);
}
@@ -275,7 +268,7 @@ public class TunerResourceManagerServiceTest {
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
- assertThat(getResourceIdFromHandle(frontendHandle[0]))
+ assertThat(mTunerResourceManagerService.getResourceIdFromHandle(frontendHandle[0]))
.isEqualTo(TunerResourceManager.INVALID_RESOURCE_HANDLE);
}
@@ -307,7 +300,8 @@ public class TunerResourceManagerServiceTest {
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
- assertThat(getResourceIdFromHandle(frontendHandle[0])).isEqualTo(0);
+ assertThat(mTunerResourceManagerService.getResourceIdFromHandle(frontendHandle[0]))
+ .isEqualTo(0);
}
@Test
@@ -344,7 +338,8 @@ public class TunerResourceManagerServiceTest {
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
- assertThat(getResourceIdFromHandle(frontendHandle[0])).isEqualTo(infos[0].getId());
+ assertThat(mTunerResourceManagerService.getResourceIdFromHandle(frontendHandle[0]))
+ .isEqualTo(infos[0].getId());
request =
new TunerFrontendRequest(clientId0[0] /*clientId*/, FrontendSettings.TYPE_DVBT);
@@ -354,7 +349,8 @@ public class TunerResourceManagerServiceTest {
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
- assertThat(getResourceIdFromHandle(frontendHandle[0])).isEqualTo(infos[1].getId());
+ assertThat(mTunerResourceManagerService.getResourceIdFromHandle(frontendHandle[0]))
+ .isEqualTo(infos[1].getId());
assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].getId())
.isInUse()).isTrue();
assertThat(mTunerResourceManagerService.getFrontendResource(infos[2].getId())
@@ -464,7 +460,8 @@ public class TunerResourceManagerServiceTest {
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
- assertThat(getResourceIdFromHandle(frontendHandle[0])).isEqualTo(infos[0].getId());
+ assertThat(mTunerResourceManagerService.getResourceIdFromHandle(frontendHandle[0]))
+ .isEqualTo(infos[0].getId());
request =
new TunerFrontendRequest(clientId1[0] /*clientId*/, FrontendSettings.TYPE_DVBS);
@@ -474,7 +471,8 @@ public class TunerResourceManagerServiceTest {
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
- assertThat(getResourceIdFromHandle(frontendHandle[0])).isEqualTo(infos[1].getId());
+ assertThat(mTunerResourceManagerService.getResourceIdFromHandle(frontendHandle[0]))
+ .isEqualTo(infos[1].getId());
assertThat(mTunerResourceManagerService.getFrontendResource(infos[0].getId())
.isInUse()).isTrue();
assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].getId())
@@ -487,6 +485,49 @@ public class TunerResourceManagerServiceTest {
}
@Test
+ public void releaseFrontendTest_UnderTheSameExclusiveGroup() {
+ // Register clients
+ ResourceClientProfile[] profiles = new ResourceClientProfile[1];
+ profiles[0] = new ResourceClientProfile("0" /*sessionId*/,
+ TvInputService.PRIORITY_HINT_USE_CASE_TYPE_PLAYBACK);
+ int[] clientId = new int[1];
+ TestResourcesReclaimListener listener = new TestResourcesReclaimListener();
+ mTunerResourceManagerService.registerClientProfileInternal(profiles[0], listener, clientId);
+ assertThat(clientId[0]).isNotEqualTo(TunerResourceManagerService.INVALID_CLIENT_ID);
+
+ // Init frontend resources.
+ TunerFrontendInfo[] infos = new TunerFrontendInfo[2];
+ infos[0] =
+ new TunerFrontendInfo(0 /*id*/, FrontendSettings.TYPE_DVBT, 1 /*exclusiveGroupId*/);
+ infos[1] =
+ new TunerFrontendInfo(1 /*id*/, FrontendSettings.TYPE_DVBS, 1 /*exclusiveGroupId*/);
+ mTunerResourceManagerService.setFrontendInfoListInternal(infos);
+
+ TunerFrontendRequest request =
+ new TunerFrontendRequest(clientId[0] /*clientId*/, FrontendSettings.TYPE_DVBT);
+ int[] frontendHandle = new int[1];
+ try {
+ assertThat(mTunerResourceManagerService
+ .requestFrontendInternal(request, frontendHandle)).isTrue();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ int frontendId = mTunerResourceManagerService.getResourceIdFromHandle(frontendHandle[0]);
+ assertThat(frontendId).isEqualTo(infos[0].getId());
+ assertThat(mTunerResourceManagerService
+ .getFrontendResource(infos[1].getId()).isInUse()).isTrue();
+
+ // Release frontend
+ mTunerResourceManagerService.releaseFrontendInternal(frontendId);
+ assertThat(mTunerResourceManagerService
+ .getFrontendResource(frontendId).isInUse()).isFalse();
+ assertThat(mTunerResourceManagerService
+ .getFrontendResource(infos[1].getId()).isInUse()).isFalse();
+ assertThat(mTunerResourceManagerService
+ .getClientProfile(clientId[0]).getInUseFrontendIds().size()).isEqualTo(0);
+ }
+
+ @Test
public void unregisterClientTest_usingFrontend() {
// Register client
ResourceClientProfile profile = new ResourceClientProfile("0" /*sessionId*/,
@@ -513,7 +554,8 @@ public class TunerResourceManagerServiceTest {
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
- assertThat(getResourceIdFromHandle(frontendHandle[0])).isEqualTo(infos[0].getId());
+ assertThat(mTunerResourceManagerService.getResourceIdFromHandle(frontendHandle[0]))
+ .isEqualTo(infos[0].getId());
assertThat(mTunerResourceManagerService.getFrontendResource(infos[0].getId())
.isInUse()).isTrue();
assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].getId())
@@ -543,7 +585,8 @@ public class TunerResourceManagerServiceTest {
TunerDemuxRequest request = new TunerDemuxRequest(clientId[0]);
assertThat(mTunerResourceManagerService.requestDemuxInternal(request, demuxHandle))
.isTrue();
- assertThat(getResourceIdFromHandle(demuxHandle[0])).isEqualTo(0);
+ assertThat(mTunerResourceManagerService.getResourceIdFromHandle(demuxHandle[0]))
+ .isEqualTo(0);
}
@Test
@@ -560,6 +603,6 @@ public class TunerResourceManagerServiceTest {
TunerDescramblerRequest request = new TunerDescramblerRequest(clientId[0]);
assertThat(mTunerResourceManagerService.requestDescramblerInternal(request, desHandle))
.isTrue();
- assertThat(getResourceIdFromHandle(desHandle[0])).isEqualTo(0);
+ assertThat(mTunerResourceManagerService.getResourceIdFromHandle(desHandle[0])).isEqualTo(0);
}
}