Loading services/core/java/com/android/server/tv/tunerresourcemanager/ClientProfile.java +4 −4 Original line number Diff line number Diff line Loading @@ -15,8 +15,8 @@ */ package com.android.server.tv.tunerresourcemanager; import java.util.ArrayList; import java.util.List; import java.util.HashSet; import java.util.Set; /** * A client profile object used by the Tuner Resource Manager to record the registered clients' Loading Loading @@ -65,7 +65,7 @@ public final class ClientProfile { /** * List of the frontend ids that are used by the current client. */ private List<Integer> mUsingFrontendIds = new ArrayList<>(); private Set<Integer> mUsingFrontendIds = new HashSet<>(); /** * Optional arbitrary priority value given by the client. Loading Loading @@ -131,7 +131,7 @@ public final class ClientProfile { mUsingFrontendIds.add(frontendId); } public List<Integer> getInUseFrontendIds() { public Iterable<Integer> getInUseFrontendIds() { return mUsingFrontendIds; } Loading services/core/java/com/android/server/tv/tunerresourcemanager/FrontendResource.java +12 −25 Original line number Diff line number Diff line Loading @@ -15,12 +15,11 @@ */ package com.android.server.tv.tunerresourcemanager; import android.annotation.Nullable; import android.media.tv.tuner.frontend.FrontendSettings.Type; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Collection; import java.util.HashSet; import java.util.Set; /** * A frontend resource object used by the Tuner Resource Manager to record the tuner frontend Loading Loading @@ -50,7 +49,7 @@ public final class FrontendResource { /** * An array to save all the FE ids under the same exclisive group. */ private List<Integer> mExclusiveGroupMemberFeIds = new ArrayList<>(); private Set<Integer> mExclusiveGroupMemberFeIds = new HashSet<>(); /** * If the current resource is in use. Once resources under the same exclusive group id is in use Loading Loading @@ -82,12 +81,12 @@ public final class FrontendResource { return mExclusiveGroupId; } public List<Integer> getExclusiveGroupMemberFeIds() { public Set<Integer> getExclusiveGroupMemberFeIds() { return mExclusiveGroupMemberFeIds; } /** * Add one id into the exclusive group member id list. * Add one id into the exclusive group member id collection. * * @param id the id to be added. */ Loading @@ -96,21 +95,21 @@ public final class FrontendResource { } /** * Add one id list to the exclusive group member id list. * Add one id collection to the exclusive group member id collection. * * @param ids the id list to be added. * @param ids the id collection to be added. */ public void addExclusiveGroupMemberFeId(List<Integer> ids) { public void addExclusiveGroupMemberFeIds(Collection<Integer> ids) { mExclusiveGroupMemberFeIds.addAll(ids); } /** * Remove one id from the exclusive group member id list. * Remove one id from the exclusive group member id collection. * * @param id the id to be removed. */ public void removeExclusiveGroupMemberFeId(int id) { mExclusiveGroupMemberFeIds.remove(new Integer(id)); mExclusiveGroupMemberFeIds.remove(id); } public boolean isInUse() { Loading Loading @@ -143,22 +142,10 @@ public final class FrontendResource { public String toString() { return "FrontendResource[id=" + this.mId + ", type=" + this.mType + ", exclusiveGId=" + this.mExclusiveGroupId + ", exclusiveGMemeberIds=" + Arrays.toString(this.mExclusiveGroupMemberFeIds.toArray()) + this.mExclusiveGroupMemberFeIds + ", isInUse=" + this.mIsInUse + ", ownerClientId=" + this.mOwnerClientId + "]"; } @Override public boolean equals(@Nullable Object o) { if (o instanceof FrontendResource) { FrontendResource fe = (FrontendResource) o; return mId == fe.getId() && mType == fe.getType() && mExclusiveGroupId == fe.getExclusiveGroupId() && mExclusiveGroupMemberFeIds.equals(fe.getExclusiveGroupMemberFeIds()) && mIsInUse == fe.isInUse() && mOwnerClientId == fe.getOwnerClientId(); } return false; } /** * Builder class for {@link FrontendResource}. */ Loading services/core/java/com/android/server/tv/tunerresourcemanager/TunerResourceManagerService.java +78 −73 Original line number Diff line number Diff line Loading @@ -37,8 +37,10 @@ import android.util.SparseArray; import com.android.internal.annotations.VisibleForTesting; import com.android.server.SystemService; import java.util.ArrayList; import java.util.List; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; /** * This class provides a system service that manages the TV tuner resources. Loading @@ -52,16 +54,12 @@ public class TunerResourceManagerService extends SystemService { public static final int INVALID_CLIENT_ID = -1; private static final int MAX_CLIENT_PRIORITY = 1000; // Array of the registered client profiles @VisibleForTesting private SparseArray<ClientProfile> mClientProfiles = new SparseArray<>(); // Map of the registered client profiles private Map<Integer, ClientProfile> mClientProfiles = new HashMap<>(); private int mNextUnusedClientId = 0; private List<Integer> mRegisteredClientIds = new ArrayList<Integer>(); // Array of the current available frontend resources @VisibleForTesting private SparseArray<FrontendResource> mFrontendResources = new SparseArray<>(); // Array of the current available frontend ids private List<Integer> mAvailableFrontendIds = new ArrayList<Integer>(); // Map of the current available frontend resources private Map<Integer, FrontendResource> mFrontendResources = new HashMap<>(); private SparseArray<IResourcesReclaimListener> mListeners = new SparseArray<>(); Loading Loading @@ -261,9 +259,8 @@ public class TunerResourceManagerService extends SystemService { .build(); clientProfile.setPriority(getClientPriority(profile.getUseCase(), pid)); mClientProfiles.append(clientId[0], clientProfile); addClientProfile(clientId[0], clientProfile); mListeners.append(clientId[0], listener); mRegisteredClientIds.add(clientId[0]); } @VisibleForTesting Loading @@ -271,15 +268,8 @@ public class TunerResourceManagerService extends SystemService { if (DEBUG) { Slog.d(TAG, "unregisterClientProfile(clientId=" + clientId + ")"); } for (int id : getClientProfile(clientId).getInUseFrontendIds()) { getFrontendResource(id).removeOwner(); for (int groupMemberId : getFrontendResource(id).getExclusiveGroupMemberFeIds()) { getFrontendResource(groupMemberId).removeOwner(); } } mClientProfiles.remove(clientId); removeClientProfile(clientId); mListeners.remove(clientId); mRegisteredClientIds.remove(clientId); } @VisibleForTesting Loading Loading @@ -313,56 +303,32 @@ public class TunerResourceManagerService extends SystemService { } } // An arrayList to record the frontends pending on updating. Ids will be removed // from this list once its updating finished. Any frontend left in this list when all // the updates are done will be removed from mAvailableFrontendIds and // mFrontendResources. List<Integer> updatingFrontendIds = new ArrayList<>(mAvailableFrontendIds); // A set to record the frontends pending on updating. Ids will be removed // from this set once its updating finished. Any frontend left in this set when all // the updates are done will be removed from mFrontendResources. Set<Integer> updatingFrontendIds = new HashSet<>(getFrontendResources().keySet()); // Update frontendResources sparse array and other mappings accordingly // Update frontendResources map and other mappings accordingly for (int i = 0; i < infos.length; i++) { if (getFrontendResource(infos[i].getId()) != null) { if (DEBUG) { Slog.d(TAG, "Frontend id=" + infos[i].getId() + "exists."); } updatingFrontendIds.remove(new Integer(infos[i].getId())); updatingFrontendIds.remove(infos[i].getId()); } else { // Add a new fe resource FrontendResource newFe = new FrontendResource.Builder(infos[i].getId()) .type(infos[i].getFrontendType()) .exclusiveGroupId(infos[i].getExclusiveGroupId()) .build(); // Update the exclusive group member list in all the existing Frontend resource for (Integer feId : mAvailableFrontendIds) { FrontendResource fe = getFrontendResource(feId.intValue()); if (fe.getExclusiveGroupId() == newFe.getExclusiveGroupId()) { newFe.addExclusiveGroupMemberFeId(fe.getId()); newFe.addExclusiveGroupMemberFeId(fe.getExclusiveGroupMemberFeIds()); for (Integer excGroupmemberFeId : fe.getExclusiveGroupMemberFeIds()) { getFrontendResource(excGroupmemberFeId.intValue()) .addExclusiveGroupMemberFeId(newFe.getId()); } fe.addExclusiveGroupMemberFeId(newFe.getId()); break; } } // Update resource list and available id list mFrontendResources.append(newFe.getId(), newFe); mAvailableFrontendIds.add(newFe.getId()); addFrontendResource(newFe); } } // TODO check if the removing resource is in use or not. Handle the conflict. for (Integer removingId : updatingFrontendIds) { // update the exclusive group id memver list FrontendResource fe = getFrontendResource(removingId.intValue()); fe.removeExclusiveGroupMemberFeId(new Integer(fe.getId())); for (Integer excGroupmemberFeId : fe.getExclusiveGroupMemberFeIds()) { getFrontendResource(excGroupmemberFeId.intValue()) .removeExclusiveGroupMemberFeId(new Integer(fe.getId())); } mFrontendResources.remove(removingId.intValue()); mAvailableFrontendIds.remove(removingId); for (int removingId : updatingFrontendIds) { // update the exclusive group id member list removeFrontendResource(removingId); } } Loading @@ -383,25 +349,24 @@ public class TunerResourceManagerService extends SystemService { int inUseLowestPriorityFrId = -1; // Priority max value is 1000 int currentLowestPriority = MAX_CLIENT_PRIORITY + 1; for (int id : mAvailableFrontendIds) { FrontendResource fr = getFrontendResource(id); for (FrontendResource fr : getFrontendResources().values()) { if (fr.getType() == request.getFrontendType()) { if (!fr.isInUse()) { // Grant unused frontend with no exclusive group members first. if (fr.getExclusiveGroupMemberFeIds().size() == 0) { grantingFrontendId = id; if (fr.getExclusiveGroupMemberFeIds().isEmpty()) { grantingFrontendId = fr.getId(); break; } else if (grantingFrontendId < 0) { // Grant the unused frontend with lower id first if all the unused // frontends have exclusive group members. grantingFrontendId = id; grantingFrontendId = fr.getId(); } } else if (grantingFrontendId < 0) { // Record the frontend id with the lowest client priority among all the // in use frontends when no available frontend has been found. int priority = getOwnerClientPriority(id); int priority = getOwnerClientPriority(fr); if (currentLowestPriority > priority) { inUseLowestPriorityFrId = id; inUseLowestPriorityFrId = fr.getId(); currentLowestPriority = priority; } } Loading Loading @@ -471,33 +436,73 @@ public class TunerResourceManagerService extends SystemService { /** * Get the owner client's priority from the frontend id. * * @param frontendId an in use frontend id. * @param frontend an in use frontend. * @return the priority of the owner client of the frontend. */ private int getOwnerClientPriority(int frontendId) { return getClientProfile(getFrontendResource(frontendId).getOwnerClientId()).getPriority(); } private ClientProfile getClientProfile(int clientId) { return mClientProfiles.get(clientId); private int getOwnerClientPriority(FrontendResource frontend) { return getClientProfile(frontend.getOwnerClientId()).getPriority(); } @VisibleForTesting @Nullable protected FrontendResource getFrontendResource(int frontendId) { return mFrontendResources.get(frontendId); } @VisibleForTesting protected SparseArray<ClientProfile> getClientProfiles() { return mClientProfiles; protected Map<Integer, FrontendResource> getFrontendResources() { return mFrontendResources; } private void addFrontendResource(FrontendResource newFe) { // Update the exclusive group member list in all the existing Frontend resource for (FrontendResource fe : getFrontendResources().values()) { if (fe.getExclusiveGroupId() == newFe.getExclusiveGroupId()) { newFe.addExclusiveGroupMemberFeId(fe.getId()); newFe.addExclusiveGroupMemberFeIds(fe.getExclusiveGroupMemberFeIds()); for (int excGroupmemberFeId : fe.getExclusiveGroupMemberFeIds()) { getFrontendResource(excGroupmemberFeId) .addExclusiveGroupMemberFeId(newFe.getId()); } fe.addExclusiveGroupMemberFeId(newFe.getId()); break; } } // Update resource list and available id list mFrontendResources.put(newFe.getId(), newFe); } private void removeFrontendResource(int removingId) { FrontendResource fe = getFrontendResource(removingId); for (int excGroupmemberFeId : fe.getExclusiveGroupMemberFeIds()) { getFrontendResource(excGroupmemberFeId) .removeExclusiveGroupMemberFeId(fe.getId()); } mFrontendResources.remove(removingId); } @VisibleForTesting protected SparseArray<FrontendResource> getFrontendResources() { return mFrontendResources; @Nullable protected ClientProfile getClientProfile(int clientId) { return mClientProfiles.get(clientId); } private void addClientProfile(int clientId, ClientProfile profile) { mClientProfiles.put(clientId, profile); } private void removeClientProfile(int clientId) { for (int id : getClientProfile(clientId).getInUseFrontendIds()) { getFrontendResource(id).removeOwner(); for (int groupMemberId : getFrontendResource(id).getExclusiveGroupMemberFeIds()) { getFrontendResource(groupMemberId).removeOwner(); } } mClientProfiles.remove(clientId); } private boolean checkClientExists(int clientId) { return mRegisteredClientIds.contains(clientId); return mClientProfiles.keySet().contains(clientId); } private void enforceAccessPermission() { Loading services/core/java/com/android/server/tv/tunerresourcemanager/UseCasePriorityHints.java +3 −3 Original line number Diff line number Diff line Loading @@ -31,8 +31,8 @@ import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.List; import java.util.HashSet; import java.util.Set; /** * This class provides the Tuner Resource Manager use case priority hints config info including a Loading @@ -56,7 +56,7 @@ public class UseCasePriorityHints { */ SparseArray<int[]> mPriorityHints = new SparseArray<>(); List<Integer> mVendorDefinedUseCase = new ArrayList<>(); Set<Integer> mVendorDefinedUseCase = new HashSet<>(); private int mDefaultForeground = 150; private int mDefaultBackground = 50; Loading services/tests/servicestests/src/com/android/server/tv/tunerresourcemanager/TunerResourceManagerServiceTest.java +31 −34 Original line number Diff line number Diff line Loading @@ -48,6 +48,7 @@ import org.mockito.MockitoAnnotations; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; /** * Tests for {@link TunerResourceManagerService} class. Loading Loading @@ -118,7 +119,7 @@ public class TunerResourceManagerServiceTest { new TunerFrontendInfo(1 /*id*/, FrontendSettings.TYPE_DVBT, 1 /*exclusiveGroupId*/); mTunerResourceManagerService.setFrontendInfoListInternal(infos); SparseArray<FrontendResource> resources = Map<Integer, FrontendResource> resources = mTunerResourceManagerService.getFrontendResources(); for (int id = 0; id < infos.length; id++) { assertThat(resources.get(infos[id].getId()) Loading @@ -128,7 +129,7 @@ public class TunerResourceManagerServiceTest { assertThat(resources.get(infos[id].getId()) .getExclusiveGroupMemberFeIds().size()).isEqualTo(0); } assertThat(sparseArrayToList(resources)).comparingElementsUsing(FR_TFI_COMPARE) assertThat(resources.values()).comparingElementsUsing(FR_TFI_COMPARE) .containsExactlyElementsIn(Arrays.asList(infos)); } Loading @@ -146,19 +147,15 @@ public class TunerResourceManagerServiceTest { new TunerFrontendInfo(3 /*id*/, FrontendSettings.TYPE_ATSC, 1 /*exclusiveGroupId*/); mTunerResourceManagerService.setFrontendInfoListInternal(infos); SparseArray<FrontendResource> resources = Map<Integer, FrontendResource> resources = mTunerResourceManagerService.getFrontendResources(); assertThat(sparseArrayToList(resources)).comparingElementsUsing(FR_TFI_COMPARE) assertThat(resources.values()).comparingElementsUsing(FR_TFI_COMPARE) .containsExactlyElementsIn(Arrays.asList(infos)); assertThat(resources.get(0).getExclusiveGroupMemberFeIds()) .isEqualTo(new ArrayList<Integer>()); assertThat(resources.get(1).getExclusiveGroupMemberFeIds()) .isEqualTo(new ArrayList<Integer>(Arrays.asList(2, 3))); assertThat(resources.get(2).getExclusiveGroupMemberFeIds()) .isEqualTo(new ArrayList<Integer>(Arrays.asList(1, 3))); assertThat(resources.get(3).getExclusiveGroupMemberFeIds()) .isEqualTo(new ArrayList<Integer>(Arrays.asList(1, 2))); assertThat(resources.get(0).getExclusiveGroupMemberFeIds()).isEmpty(); assertThat(resources.get(1).getExclusiveGroupMemberFeIds()).containsExactly(2, 3); assertThat(resources.get(2).getExclusiveGroupMemberFeIds()).containsExactly(1, 3); assertThat(resources.get(3).getExclusiveGroupMemberFeIds()).containsExactly(1, 2); } @Test Loading @@ -171,11 +168,11 @@ public class TunerResourceManagerServiceTest { new TunerFrontendInfo(1 /*id*/, FrontendSettings.TYPE_DVBS, 1 /*exclusiveGroupId*/); mTunerResourceManagerService.setFrontendInfoListInternal(infos); SparseArray<FrontendResource> resources0 = Map<Integer, FrontendResource> resources0 = mTunerResourceManagerService.getFrontendResources(); mTunerResourceManagerService.setFrontendInfoListInternal(infos); SparseArray<FrontendResource> resources1 = Map<Integer, FrontendResource> resources1 = mTunerResourceManagerService.getFrontendResources(); assertThat(resources0).isEqualTo(resources1); Loading @@ -198,13 +195,13 @@ public class TunerResourceManagerServiceTest { new TunerFrontendInfo(1 /*id*/, FrontendSettings.TYPE_DVBT, 1 /*exclusiveGroupId*/); mTunerResourceManagerService.setFrontendInfoListInternal(infos1); SparseArray<FrontendResource> resources = Map<Integer, FrontendResource> resources = mTunerResourceManagerService.getFrontendResources(); for (int id = 0; id < infos1.length; id++) { assertThat(resources.get(infos1[id].getId()) .getExclusiveGroupMemberFeIds().size()).isEqualTo(0); } assertThat(sparseArrayToList(resources)).comparingElementsUsing(FR_TFI_COMPARE) assertThat(resources.values()).comparingElementsUsing(FR_TFI_COMPARE) .containsExactlyElementsIn(Arrays.asList(infos1)); } Loading @@ -225,13 +222,13 @@ public class TunerResourceManagerServiceTest { new TunerFrontendInfo(1 /*id*/, FrontendSettings.TYPE_DVBT, 1 /*exclusiveGroupId*/); mTunerResourceManagerService.setFrontendInfoListInternal(infos1); SparseArray<FrontendResource> resources = Map<Integer, FrontendResource> resources = mTunerResourceManagerService.getFrontendResources(); for (int id = 0; id < infos1.length; id++) { assertThat(resources.get(infos1[id].getId()) .getExclusiveGroupMemberFeIds().size()).isEqualTo(0); } assertThat(sparseArrayToList(resources)).comparingElementsUsing(FR_TFI_COMPARE) assertThat(resources.values()).comparingElementsUsing(FR_TFI_COMPARE) .containsExactlyElementsIn(Arrays.asList(infos1)); } Loading Loading @@ -352,9 +349,9 @@ public class TunerResourceManagerServiceTest { throw e.rethrowFromSystemServer(); } assertThat(frontendId[0]).isEqualTo(infos[1].getId()); assertThat(mTunerResourceManagerService.getFrontendResources().get(infos[1].getId()) assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].getId()) .isInUse()).isTrue(); assertThat(mTunerResourceManagerService.getFrontendResources().get(infos[2].getId()) assertThat(mTunerResourceManagerService.getFrontendResource(infos[2].getId()) .isInUse()).isTrue(); } Loading @@ -372,12 +369,12 @@ public class TunerResourceManagerServiceTest { mTunerResourceManagerService.registerClientProfileInternal( profiles[0], null /*listener*/, clientId0); assertThat(clientId0[0]).isNotEqualTo(TunerResourceManagerService.INVALID_CLIENT_ID); mTunerResourceManagerService.getClientProfiles().get(clientId0[0]) mTunerResourceManagerService.getClientProfile(clientId0[0]) .setPriority(clientPriorities[0]); mTunerResourceManagerService.registerClientProfileInternal( profiles[1], null /*listener*/, clientId1); assertThat(clientId1[0]).isNotEqualTo(TunerResourceManagerService.INVALID_CLIENT_ID); mTunerResourceManagerService.getClientProfiles().get(clientId1[0]) mTunerResourceManagerService.getClientProfile(clientId1[0]) .setPriority(clientPriorities[1]); // Init frontend resources. Loading Loading @@ -433,12 +430,12 @@ public class TunerResourceManagerServiceTest { mTunerResourceManagerService.registerClientProfileInternal( profiles[0], null /*listener*/, clientId0); assertThat(clientId0[0]).isNotEqualTo(TunerResourceManagerService.INVALID_CLIENT_ID); mTunerResourceManagerService.getClientProfiles().get(clientId0[0]) mTunerResourceManagerService.getClientProfile(clientId0[0]) .setPriority(clientPriorities[0]); mTunerResourceManagerService.registerClientProfileInternal( profiles[1], null /*listener*/, clientId1); assertThat(clientId1[0]).isNotEqualTo(TunerResourceManagerService.INVALID_CLIENT_ID); mTunerResourceManagerService.getClientProfiles().get(clientId1[0]) mTunerResourceManagerService.getClientProfile(clientId1[0]) .setPriority(clientPriorities[1]); // Init frontend resources. Loading Loading @@ -469,14 +466,14 @@ public class TunerResourceManagerServiceTest { throw e.rethrowFromSystemServer(); } assertThat(frontendId[0]).isEqualTo(infos[1].getId()); assertThat(mTunerResourceManagerService.getFrontendResources().get(infos[0].getId()) assertThat(mTunerResourceManagerService.getFrontendResource(infos[0].getId()) .isInUse()).isTrue(); assertThat(mTunerResourceManagerService.getFrontendResources().get(infos[1].getId()) assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].getId()) .isInUse()).isTrue(); assertThat(mTunerResourceManagerService.getFrontendResources() .get(infos[0].getId()).getOwnerClientId()).isEqualTo(clientId1[0]); assertThat(mTunerResourceManagerService.getFrontendResources() .get(infos[1].getId()).getOwnerClientId()).isEqualTo(clientId1[0]); assertThat(mTunerResourceManagerService.getFrontendResource(infos[0].getId()) .getOwnerClientId()).isEqualTo(clientId1[0]); assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].getId()) .getOwnerClientId()).isEqualTo(clientId1[0]); assertThat(mReclaimingId).isEqualTo(clientId0[0]); } Loading Loading @@ -508,16 +505,16 @@ public class TunerResourceManagerServiceTest { throw e.rethrowFromSystemServer(); } assertThat(frontendId[0]).isEqualTo(infos[0].getId()); assertThat(mTunerResourceManagerService.getFrontendResources().get(infos[0].getId()) assertThat(mTunerResourceManagerService.getFrontendResource(infos[0].getId()) .isInUse()).isTrue(); assertThat(mTunerResourceManagerService.getFrontendResources().get(infos[1].getId()) assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].getId()) .isInUse()).isTrue(); // Unregister client when using frontend mTunerResourceManagerService.unregisterClientProfileInternal(clientId[0]); assertThat(mTunerResourceManagerService.getFrontendResources().get(infos[0].getId()) assertThat(mTunerResourceManagerService.getFrontendResource(infos[0].getId()) .isInUse()).isFalse(); assertThat(mTunerResourceManagerService.getFrontendResources().get(infos[1].getId()) assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].getId()) .isInUse()).isFalse(); } Loading Loading
services/core/java/com/android/server/tv/tunerresourcemanager/ClientProfile.java +4 −4 Original line number Diff line number Diff line Loading @@ -15,8 +15,8 @@ */ package com.android.server.tv.tunerresourcemanager; import java.util.ArrayList; import java.util.List; import java.util.HashSet; import java.util.Set; /** * A client profile object used by the Tuner Resource Manager to record the registered clients' Loading Loading @@ -65,7 +65,7 @@ public final class ClientProfile { /** * List of the frontend ids that are used by the current client. */ private List<Integer> mUsingFrontendIds = new ArrayList<>(); private Set<Integer> mUsingFrontendIds = new HashSet<>(); /** * Optional arbitrary priority value given by the client. Loading Loading @@ -131,7 +131,7 @@ public final class ClientProfile { mUsingFrontendIds.add(frontendId); } public List<Integer> getInUseFrontendIds() { public Iterable<Integer> getInUseFrontendIds() { return mUsingFrontendIds; } Loading
services/core/java/com/android/server/tv/tunerresourcemanager/FrontendResource.java +12 −25 Original line number Diff line number Diff line Loading @@ -15,12 +15,11 @@ */ package com.android.server.tv.tunerresourcemanager; import android.annotation.Nullable; import android.media.tv.tuner.frontend.FrontendSettings.Type; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Collection; import java.util.HashSet; import java.util.Set; /** * A frontend resource object used by the Tuner Resource Manager to record the tuner frontend Loading Loading @@ -50,7 +49,7 @@ public final class FrontendResource { /** * An array to save all the FE ids under the same exclisive group. */ private List<Integer> mExclusiveGroupMemberFeIds = new ArrayList<>(); private Set<Integer> mExclusiveGroupMemberFeIds = new HashSet<>(); /** * If the current resource is in use. Once resources under the same exclusive group id is in use Loading Loading @@ -82,12 +81,12 @@ public final class FrontendResource { return mExclusiveGroupId; } public List<Integer> getExclusiveGroupMemberFeIds() { public Set<Integer> getExclusiveGroupMemberFeIds() { return mExclusiveGroupMemberFeIds; } /** * Add one id into the exclusive group member id list. * Add one id into the exclusive group member id collection. * * @param id the id to be added. */ Loading @@ -96,21 +95,21 @@ public final class FrontendResource { } /** * Add one id list to the exclusive group member id list. * Add one id collection to the exclusive group member id collection. * * @param ids the id list to be added. * @param ids the id collection to be added. */ public void addExclusiveGroupMemberFeId(List<Integer> ids) { public void addExclusiveGroupMemberFeIds(Collection<Integer> ids) { mExclusiveGroupMemberFeIds.addAll(ids); } /** * Remove one id from the exclusive group member id list. * Remove one id from the exclusive group member id collection. * * @param id the id to be removed. */ public void removeExclusiveGroupMemberFeId(int id) { mExclusiveGroupMemberFeIds.remove(new Integer(id)); mExclusiveGroupMemberFeIds.remove(id); } public boolean isInUse() { Loading Loading @@ -143,22 +142,10 @@ public final class FrontendResource { public String toString() { return "FrontendResource[id=" + this.mId + ", type=" + this.mType + ", exclusiveGId=" + this.mExclusiveGroupId + ", exclusiveGMemeberIds=" + Arrays.toString(this.mExclusiveGroupMemberFeIds.toArray()) + this.mExclusiveGroupMemberFeIds + ", isInUse=" + this.mIsInUse + ", ownerClientId=" + this.mOwnerClientId + "]"; } @Override public boolean equals(@Nullable Object o) { if (o instanceof FrontendResource) { FrontendResource fe = (FrontendResource) o; return mId == fe.getId() && mType == fe.getType() && mExclusiveGroupId == fe.getExclusiveGroupId() && mExclusiveGroupMemberFeIds.equals(fe.getExclusiveGroupMemberFeIds()) && mIsInUse == fe.isInUse() && mOwnerClientId == fe.getOwnerClientId(); } return false; } /** * Builder class for {@link FrontendResource}. */ Loading
services/core/java/com/android/server/tv/tunerresourcemanager/TunerResourceManagerService.java +78 −73 Original line number Diff line number Diff line Loading @@ -37,8 +37,10 @@ import android.util.SparseArray; import com.android.internal.annotations.VisibleForTesting; import com.android.server.SystemService; import java.util.ArrayList; import java.util.List; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; /** * This class provides a system service that manages the TV tuner resources. Loading @@ -52,16 +54,12 @@ public class TunerResourceManagerService extends SystemService { public static final int INVALID_CLIENT_ID = -1; private static final int MAX_CLIENT_PRIORITY = 1000; // Array of the registered client profiles @VisibleForTesting private SparseArray<ClientProfile> mClientProfiles = new SparseArray<>(); // Map of the registered client profiles private Map<Integer, ClientProfile> mClientProfiles = new HashMap<>(); private int mNextUnusedClientId = 0; private List<Integer> mRegisteredClientIds = new ArrayList<Integer>(); // Array of the current available frontend resources @VisibleForTesting private SparseArray<FrontendResource> mFrontendResources = new SparseArray<>(); // Array of the current available frontend ids private List<Integer> mAvailableFrontendIds = new ArrayList<Integer>(); // Map of the current available frontend resources private Map<Integer, FrontendResource> mFrontendResources = new HashMap<>(); private SparseArray<IResourcesReclaimListener> mListeners = new SparseArray<>(); Loading Loading @@ -261,9 +259,8 @@ public class TunerResourceManagerService extends SystemService { .build(); clientProfile.setPriority(getClientPriority(profile.getUseCase(), pid)); mClientProfiles.append(clientId[0], clientProfile); addClientProfile(clientId[0], clientProfile); mListeners.append(clientId[0], listener); mRegisteredClientIds.add(clientId[0]); } @VisibleForTesting Loading @@ -271,15 +268,8 @@ public class TunerResourceManagerService extends SystemService { if (DEBUG) { Slog.d(TAG, "unregisterClientProfile(clientId=" + clientId + ")"); } for (int id : getClientProfile(clientId).getInUseFrontendIds()) { getFrontendResource(id).removeOwner(); for (int groupMemberId : getFrontendResource(id).getExclusiveGroupMemberFeIds()) { getFrontendResource(groupMemberId).removeOwner(); } } mClientProfiles.remove(clientId); removeClientProfile(clientId); mListeners.remove(clientId); mRegisteredClientIds.remove(clientId); } @VisibleForTesting Loading Loading @@ -313,56 +303,32 @@ public class TunerResourceManagerService extends SystemService { } } // An arrayList to record the frontends pending on updating. Ids will be removed // from this list once its updating finished. Any frontend left in this list when all // the updates are done will be removed from mAvailableFrontendIds and // mFrontendResources. List<Integer> updatingFrontendIds = new ArrayList<>(mAvailableFrontendIds); // A set to record the frontends pending on updating. Ids will be removed // from this set once its updating finished. Any frontend left in this set when all // the updates are done will be removed from mFrontendResources. Set<Integer> updatingFrontendIds = new HashSet<>(getFrontendResources().keySet()); // Update frontendResources sparse array and other mappings accordingly // Update frontendResources map and other mappings accordingly for (int i = 0; i < infos.length; i++) { if (getFrontendResource(infos[i].getId()) != null) { if (DEBUG) { Slog.d(TAG, "Frontend id=" + infos[i].getId() + "exists."); } updatingFrontendIds.remove(new Integer(infos[i].getId())); updatingFrontendIds.remove(infos[i].getId()); } else { // Add a new fe resource FrontendResource newFe = new FrontendResource.Builder(infos[i].getId()) .type(infos[i].getFrontendType()) .exclusiveGroupId(infos[i].getExclusiveGroupId()) .build(); // Update the exclusive group member list in all the existing Frontend resource for (Integer feId : mAvailableFrontendIds) { FrontendResource fe = getFrontendResource(feId.intValue()); if (fe.getExclusiveGroupId() == newFe.getExclusiveGroupId()) { newFe.addExclusiveGroupMemberFeId(fe.getId()); newFe.addExclusiveGroupMemberFeId(fe.getExclusiveGroupMemberFeIds()); for (Integer excGroupmemberFeId : fe.getExclusiveGroupMemberFeIds()) { getFrontendResource(excGroupmemberFeId.intValue()) .addExclusiveGroupMemberFeId(newFe.getId()); } fe.addExclusiveGroupMemberFeId(newFe.getId()); break; } } // Update resource list and available id list mFrontendResources.append(newFe.getId(), newFe); mAvailableFrontendIds.add(newFe.getId()); addFrontendResource(newFe); } } // TODO check if the removing resource is in use or not. Handle the conflict. for (Integer removingId : updatingFrontendIds) { // update the exclusive group id memver list FrontendResource fe = getFrontendResource(removingId.intValue()); fe.removeExclusiveGroupMemberFeId(new Integer(fe.getId())); for (Integer excGroupmemberFeId : fe.getExclusiveGroupMemberFeIds()) { getFrontendResource(excGroupmemberFeId.intValue()) .removeExclusiveGroupMemberFeId(new Integer(fe.getId())); } mFrontendResources.remove(removingId.intValue()); mAvailableFrontendIds.remove(removingId); for (int removingId : updatingFrontendIds) { // update the exclusive group id member list removeFrontendResource(removingId); } } Loading @@ -383,25 +349,24 @@ public class TunerResourceManagerService extends SystemService { int inUseLowestPriorityFrId = -1; // Priority max value is 1000 int currentLowestPriority = MAX_CLIENT_PRIORITY + 1; for (int id : mAvailableFrontendIds) { FrontendResource fr = getFrontendResource(id); for (FrontendResource fr : getFrontendResources().values()) { if (fr.getType() == request.getFrontendType()) { if (!fr.isInUse()) { // Grant unused frontend with no exclusive group members first. if (fr.getExclusiveGroupMemberFeIds().size() == 0) { grantingFrontendId = id; if (fr.getExclusiveGroupMemberFeIds().isEmpty()) { grantingFrontendId = fr.getId(); break; } else if (grantingFrontendId < 0) { // Grant the unused frontend with lower id first if all the unused // frontends have exclusive group members. grantingFrontendId = id; grantingFrontendId = fr.getId(); } } else if (grantingFrontendId < 0) { // Record the frontend id with the lowest client priority among all the // in use frontends when no available frontend has been found. int priority = getOwnerClientPriority(id); int priority = getOwnerClientPriority(fr); if (currentLowestPriority > priority) { inUseLowestPriorityFrId = id; inUseLowestPriorityFrId = fr.getId(); currentLowestPriority = priority; } } Loading Loading @@ -471,33 +436,73 @@ public class TunerResourceManagerService extends SystemService { /** * Get the owner client's priority from the frontend id. * * @param frontendId an in use frontend id. * @param frontend an in use frontend. * @return the priority of the owner client of the frontend. */ private int getOwnerClientPriority(int frontendId) { return getClientProfile(getFrontendResource(frontendId).getOwnerClientId()).getPriority(); } private ClientProfile getClientProfile(int clientId) { return mClientProfiles.get(clientId); private int getOwnerClientPriority(FrontendResource frontend) { return getClientProfile(frontend.getOwnerClientId()).getPriority(); } @VisibleForTesting @Nullable protected FrontendResource getFrontendResource(int frontendId) { return mFrontendResources.get(frontendId); } @VisibleForTesting protected SparseArray<ClientProfile> getClientProfiles() { return mClientProfiles; protected Map<Integer, FrontendResource> getFrontendResources() { return mFrontendResources; } private void addFrontendResource(FrontendResource newFe) { // Update the exclusive group member list in all the existing Frontend resource for (FrontendResource fe : getFrontendResources().values()) { if (fe.getExclusiveGroupId() == newFe.getExclusiveGroupId()) { newFe.addExclusiveGroupMemberFeId(fe.getId()); newFe.addExclusiveGroupMemberFeIds(fe.getExclusiveGroupMemberFeIds()); for (int excGroupmemberFeId : fe.getExclusiveGroupMemberFeIds()) { getFrontendResource(excGroupmemberFeId) .addExclusiveGroupMemberFeId(newFe.getId()); } fe.addExclusiveGroupMemberFeId(newFe.getId()); break; } } // Update resource list and available id list mFrontendResources.put(newFe.getId(), newFe); } private void removeFrontendResource(int removingId) { FrontendResource fe = getFrontendResource(removingId); for (int excGroupmemberFeId : fe.getExclusiveGroupMemberFeIds()) { getFrontendResource(excGroupmemberFeId) .removeExclusiveGroupMemberFeId(fe.getId()); } mFrontendResources.remove(removingId); } @VisibleForTesting protected SparseArray<FrontendResource> getFrontendResources() { return mFrontendResources; @Nullable protected ClientProfile getClientProfile(int clientId) { return mClientProfiles.get(clientId); } private void addClientProfile(int clientId, ClientProfile profile) { mClientProfiles.put(clientId, profile); } private void removeClientProfile(int clientId) { for (int id : getClientProfile(clientId).getInUseFrontendIds()) { getFrontendResource(id).removeOwner(); for (int groupMemberId : getFrontendResource(id).getExclusiveGroupMemberFeIds()) { getFrontendResource(groupMemberId).removeOwner(); } } mClientProfiles.remove(clientId); } private boolean checkClientExists(int clientId) { return mRegisteredClientIds.contains(clientId); return mClientProfiles.keySet().contains(clientId); } private void enforceAccessPermission() { Loading
services/core/java/com/android/server/tv/tunerresourcemanager/UseCasePriorityHints.java +3 −3 Original line number Diff line number Diff line Loading @@ -31,8 +31,8 @@ import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.List; import java.util.HashSet; import java.util.Set; /** * This class provides the Tuner Resource Manager use case priority hints config info including a Loading @@ -56,7 +56,7 @@ public class UseCasePriorityHints { */ SparseArray<int[]> mPriorityHints = new SparseArray<>(); List<Integer> mVendorDefinedUseCase = new ArrayList<>(); Set<Integer> mVendorDefinedUseCase = new HashSet<>(); private int mDefaultForeground = 150; private int mDefaultBackground = 50; Loading
services/tests/servicestests/src/com/android/server/tv/tunerresourcemanager/TunerResourceManagerServiceTest.java +31 −34 Original line number Diff line number Diff line Loading @@ -48,6 +48,7 @@ import org.mockito.MockitoAnnotations; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; /** * Tests for {@link TunerResourceManagerService} class. Loading Loading @@ -118,7 +119,7 @@ public class TunerResourceManagerServiceTest { new TunerFrontendInfo(1 /*id*/, FrontendSettings.TYPE_DVBT, 1 /*exclusiveGroupId*/); mTunerResourceManagerService.setFrontendInfoListInternal(infos); SparseArray<FrontendResource> resources = Map<Integer, FrontendResource> resources = mTunerResourceManagerService.getFrontendResources(); for (int id = 0; id < infos.length; id++) { assertThat(resources.get(infos[id].getId()) Loading @@ -128,7 +129,7 @@ public class TunerResourceManagerServiceTest { assertThat(resources.get(infos[id].getId()) .getExclusiveGroupMemberFeIds().size()).isEqualTo(0); } assertThat(sparseArrayToList(resources)).comparingElementsUsing(FR_TFI_COMPARE) assertThat(resources.values()).comparingElementsUsing(FR_TFI_COMPARE) .containsExactlyElementsIn(Arrays.asList(infos)); } Loading @@ -146,19 +147,15 @@ public class TunerResourceManagerServiceTest { new TunerFrontendInfo(3 /*id*/, FrontendSettings.TYPE_ATSC, 1 /*exclusiveGroupId*/); mTunerResourceManagerService.setFrontendInfoListInternal(infos); SparseArray<FrontendResource> resources = Map<Integer, FrontendResource> resources = mTunerResourceManagerService.getFrontendResources(); assertThat(sparseArrayToList(resources)).comparingElementsUsing(FR_TFI_COMPARE) assertThat(resources.values()).comparingElementsUsing(FR_TFI_COMPARE) .containsExactlyElementsIn(Arrays.asList(infos)); assertThat(resources.get(0).getExclusiveGroupMemberFeIds()) .isEqualTo(new ArrayList<Integer>()); assertThat(resources.get(1).getExclusiveGroupMemberFeIds()) .isEqualTo(new ArrayList<Integer>(Arrays.asList(2, 3))); assertThat(resources.get(2).getExclusiveGroupMemberFeIds()) .isEqualTo(new ArrayList<Integer>(Arrays.asList(1, 3))); assertThat(resources.get(3).getExclusiveGroupMemberFeIds()) .isEqualTo(new ArrayList<Integer>(Arrays.asList(1, 2))); assertThat(resources.get(0).getExclusiveGroupMemberFeIds()).isEmpty(); assertThat(resources.get(1).getExclusiveGroupMemberFeIds()).containsExactly(2, 3); assertThat(resources.get(2).getExclusiveGroupMemberFeIds()).containsExactly(1, 3); assertThat(resources.get(3).getExclusiveGroupMemberFeIds()).containsExactly(1, 2); } @Test Loading @@ -171,11 +168,11 @@ public class TunerResourceManagerServiceTest { new TunerFrontendInfo(1 /*id*/, FrontendSettings.TYPE_DVBS, 1 /*exclusiveGroupId*/); mTunerResourceManagerService.setFrontendInfoListInternal(infos); SparseArray<FrontendResource> resources0 = Map<Integer, FrontendResource> resources0 = mTunerResourceManagerService.getFrontendResources(); mTunerResourceManagerService.setFrontendInfoListInternal(infos); SparseArray<FrontendResource> resources1 = Map<Integer, FrontendResource> resources1 = mTunerResourceManagerService.getFrontendResources(); assertThat(resources0).isEqualTo(resources1); Loading @@ -198,13 +195,13 @@ public class TunerResourceManagerServiceTest { new TunerFrontendInfo(1 /*id*/, FrontendSettings.TYPE_DVBT, 1 /*exclusiveGroupId*/); mTunerResourceManagerService.setFrontendInfoListInternal(infos1); SparseArray<FrontendResource> resources = Map<Integer, FrontendResource> resources = mTunerResourceManagerService.getFrontendResources(); for (int id = 0; id < infos1.length; id++) { assertThat(resources.get(infos1[id].getId()) .getExclusiveGroupMemberFeIds().size()).isEqualTo(0); } assertThat(sparseArrayToList(resources)).comparingElementsUsing(FR_TFI_COMPARE) assertThat(resources.values()).comparingElementsUsing(FR_TFI_COMPARE) .containsExactlyElementsIn(Arrays.asList(infos1)); } Loading @@ -225,13 +222,13 @@ public class TunerResourceManagerServiceTest { new TunerFrontendInfo(1 /*id*/, FrontendSettings.TYPE_DVBT, 1 /*exclusiveGroupId*/); mTunerResourceManagerService.setFrontendInfoListInternal(infos1); SparseArray<FrontendResource> resources = Map<Integer, FrontendResource> resources = mTunerResourceManagerService.getFrontendResources(); for (int id = 0; id < infos1.length; id++) { assertThat(resources.get(infos1[id].getId()) .getExclusiveGroupMemberFeIds().size()).isEqualTo(0); } assertThat(sparseArrayToList(resources)).comparingElementsUsing(FR_TFI_COMPARE) assertThat(resources.values()).comparingElementsUsing(FR_TFI_COMPARE) .containsExactlyElementsIn(Arrays.asList(infos1)); } Loading Loading @@ -352,9 +349,9 @@ public class TunerResourceManagerServiceTest { throw e.rethrowFromSystemServer(); } assertThat(frontendId[0]).isEqualTo(infos[1].getId()); assertThat(mTunerResourceManagerService.getFrontendResources().get(infos[1].getId()) assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].getId()) .isInUse()).isTrue(); assertThat(mTunerResourceManagerService.getFrontendResources().get(infos[2].getId()) assertThat(mTunerResourceManagerService.getFrontendResource(infos[2].getId()) .isInUse()).isTrue(); } Loading @@ -372,12 +369,12 @@ public class TunerResourceManagerServiceTest { mTunerResourceManagerService.registerClientProfileInternal( profiles[0], null /*listener*/, clientId0); assertThat(clientId0[0]).isNotEqualTo(TunerResourceManagerService.INVALID_CLIENT_ID); mTunerResourceManagerService.getClientProfiles().get(clientId0[0]) mTunerResourceManagerService.getClientProfile(clientId0[0]) .setPriority(clientPriorities[0]); mTunerResourceManagerService.registerClientProfileInternal( profiles[1], null /*listener*/, clientId1); assertThat(clientId1[0]).isNotEqualTo(TunerResourceManagerService.INVALID_CLIENT_ID); mTunerResourceManagerService.getClientProfiles().get(clientId1[0]) mTunerResourceManagerService.getClientProfile(clientId1[0]) .setPriority(clientPriorities[1]); // Init frontend resources. Loading Loading @@ -433,12 +430,12 @@ public class TunerResourceManagerServiceTest { mTunerResourceManagerService.registerClientProfileInternal( profiles[0], null /*listener*/, clientId0); assertThat(clientId0[0]).isNotEqualTo(TunerResourceManagerService.INVALID_CLIENT_ID); mTunerResourceManagerService.getClientProfiles().get(clientId0[0]) mTunerResourceManagerService.getClientProfile(clientId0[0]) .setPriority(clientPriorities[0]); mTunerResourceManagerService.registerClientProfileInternal( profiles[1], null /*listener*/, clientId1); assertThat(clientId1[0]).isNotEqualTo(TunerResourceManagerService.INVALID_CLIENT_ID); mTunerResourceManagerService.getClientProfiles().get(clientId1[0]) mTunerResourceManagerService.getClientProfile(clientId1[0]) .setPriority(clientPriorities[1]); // Init frontend resources. Loading Loading @@ -469,14 +466,14 @@ public class TunerResourceManagerServiceTest { throw e.rethrowFromSystemServer(); } assertThat(frontendId[0]).isEqualTo(infos[1].getId()); assertThat(mTunerResourceManagerService.getFrontendResources().get(infos[0].getId()) assertThat(mTunerResourceManagerService.getFrontendResource(infos[0].getId()) .isInUse()).isTrue(); assertThat(mTunerResourceManagerService.getFrontendResources().get(infos[1].getId()) assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].getId()) .isInUse()).isTrue(); assertThat(mTunerResourceManagerService.getFrontendResources() .get(infos[0].getId()).getOwnerClientId()).isEqualTo(clientId1[0]); assertThat(mTunerResourceManagerService.getFrontendResources() .get(infos[1].getId()).getOwnerClientId()).isEqualTo(clientId1[0]); assertThat(mTunerResourceManagerService.getFrontendResource(infos[0].getId()) .getOwnerClientId()).isEqualTo(clientId1[0]); assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].getId()) .getOwnerClientId()).isEqualTo(clientId1[0]); assertThat(mReclaimingId).isEqualTo(clientId0[0]); } Loading Loading @@ -508,16 +505,16 @@ public class TunerResourceManagerServiceTest { throw e.rethrowFromSystemServer(); } assertThat(frontendId[0]).isEqualTo(infos[0].getId()); assertThat(mTunerResourceManagerService.getFrontendResources().get(infos[0].getId()) assertThat(mTunerResourceManagerService.getFrontendResource(infos[0].getId()) .isInUse()).isTrue(); assertThat(mTunerResourceManagerService.getFrontendResources().get(infos[1].getId()) assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].getId()) .isInUse()).isTrue(); // Unregister client when using frontend mTunerResourceManagerService.unregisterClientProfileInternal(clientId[0]); assertThat(mTunerResourceManagerService.getFrontendResources().get(infos[0].getId()) assertThat(mTunerResourceManagerService.getFrontendResource(infos[0].getId()) .isInUse()).isFalse(); assertThat(mTunerResourceManagerService.getFrontendResources().get(infos[1].getId()) assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].getId()) .isInUse()).isFalse(); } Loading