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 2b0fe8a2602b9..2fc17fe657756 100644 --- a/services/core/java/com/android/server/tv/tunerresourcemanager/ClientProfile.java +++ b/services/core/java/com/android/server/tv/tunerresourcemanager/ClientProfile.java @@ -67,6 +67,11 @@ public final class ClientProfile { */ private Set mUsingFrontendIds = new HashSet<>(); + /** + * List of the client ids that share frontend with the current client. + */ + private Set mShareFeClientIds = new HashSet<>(); + /** * List of the Lnb ids that are used by the current client. */ @@ -113,11 +118,7 @@ public final class ClientProfile { } public int getPriority() { - return mPriority; - } - - public int getNiceValue() { - return mNiceValue; + return mPriority - mNiceValue; } public void setGroupId(int groupId) { @@ -141,17 +142,38 @@ public final class ClientProfile { mUsingFrontendIds.add(frontendId); } + /** + * Update the set of client that share frontend with the current client. + * + * @param clientId the client to share the fe with the current client. + */ + public void shareFrontend(int clientId) { + mShareFeClientIds.add(clientId); + } + + /** + * Remove the given client id from the share frontend client id set. + * + * @param clientId the client to stop sharing the fe with the current client. + */ + public void stopSharingFrontend(int clientId) { + mShareFeClientIds.remove(clientId); + } + public Set getInUseFrontendIds() { return mUsingFrontendIds; } + public Set getShareFeClientIds() { + return mShareFeClientIds; + } + /** * Called when the client released a frontend. - * - * @param frontendId being released. */ - public void releaseFrontend(int frontendId) { - mUsingFrontendIds.remove(frontendId); + public void releaseFrontend() { + mUsingFrontendIds.clear(); + mShareFeClientIds.clear(); } /** @@ -201,6 +223,7 @@ public final class ClientProfile { */ public void reclaimAllResources() { mUsingFrontendIds.clear(); + mShareFeClientIds.clear(); mUsingLnbIds.clear(); mUsingCasSystemId = INVALID_RESOURCE_ID; } 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 7cb59dcbfb9bb..fb2347e8e133e 100644 --- a/services/core/java/com/android/server/tv/tunerresourcemanager/TunerResourceManagerService.java +++ b/services/core/java/com/android/server/tv/tunerresourcemanager/TunerResourceManagerService.java @@ -210,19 +210,36 @@ public class TunerResourceManagerService extends SystemService implements IBinde } synchronized (mLock) { if (!checkClientExists(request.getClientId())) { - throw new RemoteException("Request frontend from unregistered client:" + throw new RemoteException("Request frontend from unregistered client: " + request.getClientId()); } + // If the request client is holding or sharing a frontend, throw an exception. + if (!getClientProfile(request.getClientId()).getInUseFrontendIds().isEmpty()) { + throw new RemoteException("Release frontend before requesting another one. " + + "Client id: " + request.getClientId()); + } return requestFrontendInternal(request, frontendHandle); } } @Override - public void shareFrontend(int selfClientId, int targetClientId) { + public void shareFrontend(int selfClientId, int targetClientId) throws RemoteException { enforceTunerAccessPermission("shareFrontend"); enforceTrmAccessPermission("shareFrontend"); - if (DEBUG) { - Slog.d(TAG, "shareFrontend from " + selfClientId + " with " + targetClientId); + synchronized (mLock) { + if (!checkClientExists(selfClientId)) { + throw new RemoteException("Share frontend request from an unregistered client:" + + selfClientId); + } + if (!checkClientExists(targetClientId)) { + throw new RemoteException("Request to share frontend with an unregistered " + + "client:" + targetClientId); + } + if (getClientProfile(targetClientId).getInUseFrontendIds().isEmpty()) { + throw new RemoteException("Request to share frontend with a client that has no " + + "frontend resources. Target client id:" + targetClientId); + } + shareFrontendInternal(selfClientId, targetClientId); } } @@ -315,7 +332,7 @@ public class TunerResourceManagerService extends SystemService implements IBinde throw new RemoteException( "Client is not the current owner of the releasing fe."); } - releaseFrontendInternal(fe); + releaseFrontendInternal(fe, clientId); } } @@ -648,6 +665,17 @@ public class TunerResourceManagerService extends SystemService implements IBinde return false; } + @VisibleForTesting + protected void shareFrontendInternal(int selfClientId, int targetClientId) { + if (DEBUG) { + Slog.d(TAG, "shareFrontend from " + selfClientId + " with " + targetClientId); + } + for (int feId : getClientProfile(targetClientId).getInUseFrontendIds()) { + getClientProfile(selfClientId).useFrontend(feId); + } + getClientProfile(targetClientId).shareFrontend(selfClientId); + } + @VisibleForTesting protected boolean requestLnbInternal(TunerLnbRequest request, int[] lnbHandle) { if (DEBUG) { @@ -777,11 +805,17 @@ public class TunerResourceManagerService extends SystemService implements IBinde } @VisibleForTesting - protected void releaseFrontendInternal(FrontendResource fe) { + protected void releaseFrontendInternal(FrontendResource fe, int clientId) { if (DEBUG) { - Slog.d(TAG, "releaseFrontend(id=" + fe.getId() + ")"); + Slog.d(TAG, "releaseFrontend(id=" + fe.getId() + ", clientId=" + clientId + " )"); } - updateFrontendClientMappingOnRelease(fe); + if (clientId == fe.getOwnerClientId()) { + ClientProfile ownerClient = getClientProfile(fe.getOwnerClientId()); + for (int shareOwnerId : ownerClient.getShareFeClientIds()) { + clearFrontendAndClientMapping(getClientProfile(shareOwnerId)); + } + } + clearFrontendAndClientMapping(getClientProfile(clientId)); } @VisibleForTesting @@ -882,8 +916,21 @@ public class TunerResourceManagerService extends SystemService implements IBinde Slog.e(TAG, "Failed to reclaim resources on client " + reclaimingClientId, e); return false; } + + // Reclaim all the resources of the share owners of the frontend that is used by the current + // resource reclaimed client. ClientProfile profile = getClientProfile(reclaimingClientId); - reclaimingResourcesFromClient(profile); + Set shareFeClientIds = profile.getShareFeClientIds(); + for (int clientId : shareFeClientIds) { + try { + mListeners.get(clientId).getListener().onReclaimResources(); + } catch (RemoteException e) { + Slog.e(TAG, "Failed to reclaim resources on client " + clientId, e); + return false; + } + clearAllResourcesAndClientMapping(getClientProfile(clientId)); + } + clearAllResourcesAndClientMapping(profile); return true; } @@ -929,16 +976,6 @@ public class TunerResourceManagerService extends SystemService implements IBinde } } - private void updateFrontendClientMappingOnRelease(@NonNull FrontendResource releasingFrontend) { - ClientProfile ownerProfile = getClientProfile(releasingFrontend.getOwnerClientId()); - releasingFrontend.removeOwner(); - ownerProfile.releaseFrontend(releasingFrontend.getId()); - for (int exclusiveGroupMember : releasingFrontend.getExclusiveGroupMemberFeIds()) { - getFrontendResource(exclusiveGroupMember).removeOwner(); - ownerProfile.releaseFrontend(exclusiveGroupMember); - } - } - private void updateLnbClientMappingOnNewGrant(int grantingId, int ownerClientId) { LnbResource grantingLnb = getLnbResource(grantingId); ClientProfile ownerProfile = getClientProfile(ownerClientId); @@ -967,10 +1004,10 @@ public class TunerResourceManagerService extends SystemService implements IBinde } /** - * Get the owner client's priority from the resource id. + * Get the owner client's priority. * * @param clientId the owner client id. - * @return the priority of the owner client of the resource. + * @return the priority of the owner client. */ private int getOwnerClientPriority(int clientId) { return getClientProfile(clientId).getPriority(); @@ -1011,7 +1048,11 @@ public class TunerResourceManagerService extends SystemService implements IBinde return; } if (fe.isInUse()) { - releaseFrontendInternal(fe); + ClientProfile ownerClient = getClientProfile(fe.getOwnerClientId()); + for (int shareOwnerId : ownerClient.getShareFeClientIds()) { + clearFrontendAndClientMapping(getClientProfile(shareOwnerId)); + } + clearFrontendAndClientMapping(ownerClient); } for (int excGroupmemberFeId : fe.getExclusiveGroupMemberFeIds()) { getFrontendResource(excGroupmemberFeId) @@ -1093,21 +1134,37 @@ public class TunerResourceManagerService extends SystemService implements IBinde } private void removeClientProfile(int clientId) { - reclaimingResourcesFromClient(getClientProfile(clientId)); + for (int shareOwnerId : getClientProfile(clientId).getShareFeClientIds()) { + clearFrontendAndClientMapping(getClientProfile(shareOwnerId)); + } + clearAllResourcesAndClientMapping(getClientProfile(clientId)); mClientProfiles.remove(clientId); mListeners.remove(clientId); } - private void reclaimingResourcesFromClient(ClientProfile profile) { + private void clearFrontendAndClientMapping(ClientProfile profile) { for (Integer feId : profile.getInUseFrontendIds()) { - getFrontendResource(feId).removeOwner(); + FrontendResource fe = getFrontendResource(feId); + if (fe.getOwnerClientId() == profile.getId()) { + fe.removeOwner(); + continue; + } + getClientProfile(fe.getOwnerClientId()).stopSharingFrontend(profile.getId()); } + profile.releaseFrontend(); + } + + private void clearAllResourcesAndClientMapping(ClientProfile profile) { + // Clear Lnb for (Integer lnbId : profile.getInUseLnbIds()) { getLnbResource(lnbId).removeOwner(); } + // Clear Cas if (profile.getInUseCasSystemId() != ClientProfile.INVALID_RESOURCE_ID) { getCasResource(profile.getInUseCasSystemId()).removeOwner(profile.getId()); } + // Clear Frontend + clearFrontendAndClientMapping(profile); profile.reclaimAllResources(); } 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 2372dd25cb562..1055069c746b5 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 @@ -74,7 +74,7 @@ public class TunerResourceManagerServiceTest { mReclaimed = true; } - public boolean isRelaimed() { + public boolean isReclaimed() { return mReclaimed; } } @@ -379,13 +379,13 @@ public class TunerResourceManagerServiceTest { new TunerFrontendRequest(clientId1[0] /*clientId*/, FrontendSettings.TYPE_DVBT); assertThat(mTunerResourceManagerService .requestFrontendInternal(request, frontendHandle)).isFalse(); - assertThat(listener.isRelaimed()).isFalse(); + assertThat(listener.isReclaimed()).isFalse(); request = new TunerFrontendRequest(clientId1[0] /*clientId*/, FrontendSettings.TYPE_DVBS); assertThat(mTunerResourceManagerService .requestFrontendInternal(request, frontendHandle)).isFalse(); - assertThat(listener.isRelaimed()).isFalse(); + assertThat(listener.isReclaimed()).isFalse(); } @Test @@ -444,7 +444,7 @@ public class TunerResourceManagerServiceTest { .getOwnerClientId()).isEqualTo(clientId1[0]); assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].getId()) .getOwnerClientId()).isEqualTo(clientId1[0]); - assertThat(listener.isRelaimed()).isTrue(); + assertThat(listener.isReclaimed()).isTrue(); } @Test @@ -478,7 +478,7 @@ public class TunerResourceManagerServiceTest { // Release frontend mTunerResourceManagerService.releaseFrontendInternal(mTunerResourceManagerService - .getFrontendResource(frontendId)); + .getFrontendResource(frontendId), clientId[0]); assertThat(mTunerResourceManagerService .getFrontendResource(frontendId).isInUse()).isFalse(); assertThat(mTunerResourceManagerService @@ -540,7 +540,7 @@ public class TunerResourceManagerServiceTest { assertThat(mTunerResourceManagerService.getCasResource(1) .getOwnerClientIds()).isEqualTo(new HashSet(Arrays.asList(clientId1[0]))); assertThat(mTunerResourceManagerService.getCasResource(1).isFullyUsed()).isFalse(); - assertThat(listener.isRelaimed()).isTrue(); + assertThat(listener.isReclaimed()).isTrue(); } @Test @@ -625,7 +625,7 @@ public class TunerResourceManagerServiceTest { .isInUse()).isTrue(); assertThat(mTunerResourceManagerService.getLnbResource(lnbIds[0]) .getOwnerClientId()).isEqualTo(clientId1[0]); - assertThat(listener.isRelaimed()).isTrue(); + assertThat(listener.isReclaimed()).isTrue(); assertThat(mTunerResourceManagerService.getClientProfile(clientId0[0]) .getInUseLnbIds().size()).isEqualTo(0); } @@ -753,4 +753,293 @@ public class TunerResourceManagerServiceTest { backgroundRecordProfile)).isEqualTo( (backgroundPlaybackPriority > backgroundRecordPriority)); } + + @Test + public void shareFrontendTest_FrontendWithExclusiveGroupReadyToShare() { + /**** Register Clients and Set Priority ****/ + + // Int array to save the returned client ids + int[] ownerClientId0 = new int[1]; + int[] ownerClientId1 = new int[1]; + int[] shareClientId0 = new int[1]; + int[] shareClientId1 = new int[1]; + + // Predefined client profiles + ResourceClientProfile[] ownerProfiles = new ResourceClientProfile[2]; + ResourceClientProfile[] shareProfiles = new ResourceClientProfile[2]; + ownerProfiles[0] = new ResourceClientProfile( + "0" /*sessionId*/, + TvInputService.PRIORITY_HINT_USE_CASE_TYPE_LIVE); + ownerProfiles[1] = new ResourceClientProfile( + "1" /*sessionId*/, + TvInputService.PRIORITY_HINT_USE_CASE_TYPE_LIVE); + shareProfiles[0] = new ResourceClientProfile( + "2" /*sessionId*/, + TvInputService.PRIORITY_HINT_USE_CASE_TYPE_RECORD); + shareProfiles[1] = new ResourceClientProfile( + "3" /*sessionId*/, + TvInputService.PRIORITY_HINT_USE_CASE_TYPE_RECORD); + + // Predefined client reclaim listeners + TestResourcesReclaimListener ownerListener0 = new TestResourcesReclaimListener(); + TestResourcesReclaimListener shareListener0 = new TestResourcesReclaimListener(); + TestResourcesReclaimListener ownerListener1 = new TestResourcesReclaimListener(); + TestResourcesReclaimListener shareListener1 = new TestResourcesReclaimListener(); + // Register clients and validate the returned client ids + mTunerResourceManagerService + .registerClientProfileInternal(ownerProfiles[0], ownerListener0, ownerClientId0); + mTunerResourceManagerService + .registerClientProfileInternal(shareProfiles[0], shareListener0, shareClientId0); + mTunerResourceManagerService + .registerClientProfileInternal(ownerProfiles[1], ownerListener1, ownerClientId1); + mTunerResourceManagerService + .registerClientProfileInternal(shareProfiles[1], shareListener1, shareClientId1); + assertThat(ownerClientId0[0]).isNotEqualTo(TunerResourceManagerService.INVALID_CLIENT_ID); + assertThat(shareClientId0[0]).isNotEqualTo(TunerResourceManagerService.INVALID_CLIENT_ID); + assertThat(ownerClientId1[0]).isNotEqualTo(TunerResourceManagerService.INVALID_CLIENT_ID); + assertThat(shareClientId1[0]).isNotEqualTo(TunerResourceManagerService.INVALID_CLIENT_ID); + + mTunerResourceManagerService.updateClientPriorityInternal( + ownerClientId0[0], + 100/*priority*/, + 0/*niceValue*/); + mTunerResourceManagerService.updateClientPriorityInternal( + shareClientId0[0], + 200/*priority*/, + 0/*niceValue*/); + mTunerResourceManagerService.updateClientPriorityInternal( + ownerClientId1[0], + 300/*priority*/, + 0/*niceValue*/); + mTunerResourceManagerService.updateClientPriorityInternal( + shareClientId1[0], + 400/*priority*/, + 0/*niceValue*/); + + /**** Init Frontend Resources ****/ + + // Predefined frontend info + 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*/); + + /**** Init Lnb Resources ****/ + int[] lnbIds = {1}; + mTunerResourceManagerService.setLnbInfoListInternal(lnbIds); + + // Update frontend list in TRM + mTunerResourceManagerService.setFrontendInfoListInternal(infos); + + /**** Request Frontend ****/ + + // Predefined frontend request and array to save returned frontend handle + int[] frontendHandle = new int[1]; + TunerFrontendRequest request = new TunerFrontendRequest( + ownerClientId0[0] /*clientId*/, + FrontendSettings.TYPE_DVBT); + + // Request call and validate granted resource and internal mapping + assertThat(mTunerResourceManagerService + .requestFrontendInternal(request, frontendHandle)) + .isTrue(); + assertThat(mTunerResourceManagerService + .getResourceIdFromHandle(frontendHandle[0])) + .isEqualTo(infos[0].getId()); + assertThat(mTunerResourceManagerService + .getClientProfile(ownerClientId0[0]) + .getInUseFrontendIds()) + .isEqualTo(new HashSet(Arrays.asList( + infos[0].getId(), + infos[1].getId()))); + + /**** Share Frontend ****/ + + // Share frontend call and validate the internal mapping + mTunerResourceManagerService.shareFrontendInternal( + shareClientId0[0]/*selfClientId*/, + ownerClientId0[0]/*targetClientId*/); + mTunerResourceManagerService.shareFrontendInternal( + shareClientId1[0]/*selfClientId*/, + ownerClientId0[0]/*targetClientId*/); + // Verify fe in use status + assertThat(mTunerResourceManagerService.getFrontendResource(infos[0].getId()) + .isInUse()).isTrue(); + assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].getId()) + .isInUse()).isTrue(); + // Verify fe owner status + assertThat(mTunerResourceManagerService.getFrontendResource(infos[0].getId()) + .getOwnerClientId()).isEqualTo(ownerClientId0[0]); + assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].getId()) + .getOwnerClientId()).isEqualTo(ownerClientId0[0]); + // Verify share fe client status in the primary owner client + assertThat(mTunerResourceManagerService.getClientProfile(ownerClientId0[0]) + .getShareFeClientIds()) + .isEqualTo(new HashSet(Arrays.asList( + shareClientId0[0], + shareClientId1[0]))); + // Verify in use frontend list in all the primary owner and share owner clients + assertThat(mTunerResourceManagerService + .getClientProfile(ownerClientId0[0]) + .getInUseFrontendIds()) + .isEqualTo(new HashSet(Arrays.asList( + infos[0].getId(), + infos[1].getId()))); + assertThat(mTunerResourceManagerService + .getClientProfile(shareClientId0[0]) + .getInUseFrontendIds()) + .isEqualTo(new HashSet(Arrays.asList( + infos[0].getId(), + infos[1].getId()))); + assertThat(mTunerResourceManagerService + .getClientProfile(shareClientId1[0]) + .getInUseFrontendIds()) + .isEqualTo(new HashSet(Arrays.asList( + infos[0].getId(), + infos[1].getId()))); + + /**** Remove Frontend Share Owner ****/ + + // Unregister the second share fe client + mTunerResourceManagerService.unregisterClientProfileInternal(shareClientId1[0]); + + // Validate the internal mapping + assertThat(mTunerResourceManagerService.getClientProfile(ownerClientId0[0]) + .getShareFeClientIds()) + .isEqualTo(new HashSet(Arrays.asList( + shareClientId0[0]))); + assertThat(mTunerResourceManagerService + .getClientProfile(ownerClientId0[0]) + .getInUseFrontendIds()) + .isEqualTo(new HashSet(Arrays.asList( + infos[0].getId(), + infos[1].getId()))); + assertThat(mTunerResourceManagerService + .getClientProfile(shareClientId0[0]) + .getInUseFrontendIds()) + .isEqualTo(new HashSet(Arrays.asList( + infos[0].getId(), + infos[1].getId()))); + + /**** Request Shared Frontend with Higher Priority Client ****/ + + // Predefined second frontend request + request = new TunerFrontendRequest( + ownerClientId1[0] /*clientId*/, + FrontendSettings.TYPE_DVBT); + + // Second request call + assertThat(mTunerResourceManagerService + .requestFrontendInternal(request, frontendHandle)) + .isTrue(); + + // Validate granted resource and internal mapping + assertThat(mTunerResourceManagerService + .getResourceIdFromHandle(frontendHandle[0])) + .isEqualTo(infos[0].getId()); + assertThat(mTunerResourceManagerService.getFrontendResource(infos[0].getId()) + .getOwnerClientId()).isEqualTo(ownerClientId1[0]); + assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].getId()) + .getOwnerClientId()).isEqualTo(ownerClientId1[0]); + assertThat(mTunerResourceManagerService + .getClientProfile(ownerClientId1[0]) + .getInUseFrontendIds()) + .isEqualTo(new HashSet(Arrays.asList( + infos[0].getId(), + infos[1].getId()))); + assertThat(mTunerResourceManagerService + .getClientProfile(ownerClientId0[0]) + .getInUseFrontendIds() + .isEmpty()) + .isTrue(); + assertThat(mTunerResourceManagerService + .getClientProfile(shareClientId0[0]) + .getInUseFrontendIds() + .isEmpty()) + .isTrue(); + assertThat(mTunerResourceManagerService + .getClientProfile(ownerClientId0[0]) + .getShareFeClientIds() + .isEmpty()) + .isTrue(); + assertThat(ownerListener0.isReclaimed()).isTrue(); + assertThat(shareListener0.isReclaimed()).isTrue(); + + /**** Release Frontend Resource From Primary Owner ****/ + + // Reshare the frontend + mTunerResourceManagerService.shareFrontendInternal( + shareClientId0[0]/*selfClientId*/, + ownerClientId1[0]/*targetClientId*/); + + // Release the frontend resource from the primary owner + mTunerResourceManagerService.releaseFrontendInternal(mTunerResourceManagerService + .getFrontendResource(infos[0].getId()), ownerClientId1[0]); + + // Validate the internal mapping + assertThat(mTunerResourceManagerService.getFrontendResource(infos[0].getId()) + .isInUse()).isFalse(); + assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].getId()) + .isInUse()).isFalse(); + // Verify client status + assertThat(mTunerResourceManagerService + .getClientProfile(ownerClientId1[0]) + .getInUseFrontendIds() + .isEmpty()) + .isTrue(); + assertThat(mTunerResourceManagerService + .getClientProfile(shareClientId0[0]) + .getInUseFrontendIds() + .isEmpty()) + .isTrue(); + assertThat(mTunerResourceManagerService + .getClientProfile(ownerClientId1[0]) + .getShareFeClientIds() + .isEmpty()) + .isTrue(); + + /**** Unregister Primary Owner when the Share owner owns an Lnb ****/ + + // Predefined Lnb request and handle array + TunerLnbRequest requestLnb = new TunerLnbRequest(shareClientId0[0]); + int[] lnbHandle = new int[1]; + + // Request for an Lnb + assertThat(mTunerResourceManagerService + .requestLnbInternal(requestLnb, lnbHandle)) + .isTrue(); + + // Request and share the frontend resource again + assertThat(mTunerResourceManagerService + .requestFrontendInternal(request, frontendHandle)) + .isTrue(); + mTunerResourceManagerService.shareFrontendInternal( + shareClientId0[0]/*selfClientId*/, + ownerClientId1[0]/*targetClientId*/); + + // Unregister the primary owner of the shared frontend + mTunerResourceManagerService.unregisterClientProfileInternal(ownerClientId1[0]); + + // Validate the internal mapping + assertThat(mTunerResourceManagerService.getFrontendResource(infos[0].getId()) + .isInUse()).isFalse(); + assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].getId()) + .isInUse()).isFalse(); + // Verify client status + assertThat(mTunerResourceManagerService + .getClientProfile(shareClientId0[0]) + .getInUseFrontendIds() + .isEmpty()) + .isTrue(); + assertThat(mTunerResourceManagerService + .getClientProfile(shareClientId0[0]) + .getInUseLnbIds()) + .isEqualTo(new HashSet(Arrays.asList( + lnbIds[0]))); + } }