From 67da3fdf52506abe22229fe8ec2c91481c9d2ab8 Mon Sep 17 00:00:00 2001 From: Amy Zhang Date: Mon, 10 Aug 2020 23:40:47 -0700 Subject: [PATCH] Complete shareFrontend API implementation in TunerResourceManagerService Note that we need to consider share frontend situation in the following processes: 1. Request Frontend: to compare with the highest priority among all the share fe clients. 2. Reclaim resources: This only happens on the primary owner of a fe, we need to reclaim all the resources under the share fe clients also. 3. Remove client: when remove the primary owner, it should be treated the same way as reclaiming. When remove the share fe clients, we can just remove it from the share owner list. 4. Release resource: this only happens on the primary owner, we need to release the fe under the share fe clients also. Test: atest com.android.server.tv.tunerresourcemanager Bug: 163395799 Change-Id: I46b209cd9d7b28ac2d93f6ec297669484ff46cf6 Merged-In: I46b209cd9d7b28ac2d93f6ec297669484ff46cf6 --- .../tunerresourcemanager/ClientProfile.java | 41 ++- .../TunerResourceManagerService.java | 107 +++++-- .../TunerResourceManagerServiceTest.java | 303 +++++++++++++++++- 3 files changed, 410 insertions(+), 41 deletions(-) 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]))); + } }