Merge "Complete shareFrontend API implementation in TunerResourceManagerService" am: 0da9856837

Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1536129

MUST ONLY BE SUBMITTED BY AUTOMERGER

Change-Id: Id13a7dd326537fed1888e49acc23214982cd4f86
This commit is contained in:
Treehugger Robot
2020-12-30 12:16:13 +00:00
committed by Automerger Merge Worker
3 changed files with 410 additions and 41 deletions

View File

@@ -67,6 +67,11 @@ public final class ClientProfile {
*/
private Set<Integer> mUsingFrontendIds = new HashSet<>();
/**
* List of the client ids that share frontend with the current client.
*/
private Set<Integer> 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<Integer> getInUseFrontendIds() {
return mUsingFrontendIds;
}
public Set<Integer> 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;
}

View File

@@ -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<Integer> 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();
}

View File

@@ -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<Integer>(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<Integer>(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<Integer>(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<Integer>(Arrays.asList(
infos[0].getId(),
infos[1].getId())));
assertThat(mTunerResourceManagerService
.getClientProfile(shareClientId0[0])
.getInUseFrontendIds())
.isEqualTo(new HashSet<Integer>(Arrays.asList(
infos[0].getId(),
infos[1].getId())));
assertThat(mTunerResourceManagerService
.getClientProfile(shareClientId1[0])
.getInUseFrontendIds())
.isEqualTo(new HashSet<Integer>(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<Integer>(Arrays.asList(
shareClientId0[0])));
assertThat(mTunerResourceManagerService
.getClientProfile(ownerClientId0[0])
.getInUseFrontendIds())
.isEqualTo(new HashSet<Integer>(Arrays.asList(
infos[0].getId(),
infos[1].getId())));
assertThat(mTunerResourceManagerService
.getClientProfile(shareClientId0[0])
.getInUseFrontendIds())
.isEqualTo(new HashSet<Integer>(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<Integer>(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<Integer>(Arrays.asList(
lnbIds[0])));
}
}