diff options
8 files changed, 472 insertions, 95 deletions
diff --git a/media/java/android/media/tv/tunerresourcemanager/ITunerResourceManager.aidl b/media/java/android/media/tv/tunerresourcemanager/ITunerResourceManager.aidl index 77cac6ef7e2e..f33ad7de4179 100644 --- a/media/java/android/media/tv/tunerresourcemanager/ITunerResourceManager.aidl +++ b/media/java/android/media/tv/tunerresourcemanager/ITunerResourceManager.aidl @@ -132,11 +132,11 @@ interface ITunerResourceManager { * before this request. * * @param request {@link TunerFrontendRequest} information of the current request. - * @param frontendId a one-element array to return the granted frontendId. + * @param frontendHandle a one-element array to return the granted frontendHandle. * * @return true if there is frontend granted. */ - boolean requestFrontend(in TunerFrontendRequest request, out int[] frontendId); + boolean requestFrontend(in TunerFrontendRequest request, out int[] frontendHandle); /* * Requests to share frontend with an existing client. @@ -240,11 +240,11 @@ interface ITunerResourceManager { * <p><strong>Note:</strong> {@link #setLnbInfos(int[])} must be called before this request. * * @param request {@link TunerLnbRequest} information of the current request. - * @param lnbId a one-element array to return the granted Lnb id. + * @param lnbHandle a one-element array to return the granted Lnb handle. * * @return true if there is Lnb granted. */ - boolean requestLnb(in TunerLnbRequest request, out int[] lnbId); + boolean requestLnb(in TunerLnbRequest request, out int[] lnbHandle); /* * Notifies the TRM that the given frontend has been released. @@ -254,9 +254,9 @@ interface ITunerResourceManager { * <p><strong>Note:</strong> {@link #setFrontendInfoList(TunerFrontendInfo[])} must be called * before this release. * - * @param frontendId the id of the released frontend. + * @param frontendHandle the handle of the released frontend. */ - void releaseFrontend(in int frontendId); + void releaseFrontend(in int frontendHandle); /* * Notifies the TRM that the Demux with the given handle was released. @@ -288,15 +288,15 @@ interface ITunerResourceManager { void releaseCasSession(in int sessionResourceId); /* - * Notifies the TRM that the Lnb with the given id was released. + * Notifies the TRM that the Lnb with the given handle was released. * * <p>Client must call this whenever it releases an Lnb. * * <p><strong>Note:</strong> {@link #setLnbInfos(int[])} must be called before this release. * - * @param lnbId the id of the released Tuner Lnb. + * @param lnbHandle the handle of the released Tuner Lnb. */ - void releaseLnb(in int lnbId); + void releaseLnb(in int lnbHandle); /* * Compare two clients' priority. diff --git a/media/java/android/media/tv/tunerresourcemanager/TunerResourceManager.java b/media/java/android/media/tv/tunerresourcemanager/TunerResourceManager.java index a9f3dcf150cb..a9f89bef06a5 100644 --- a/media/java/android/media/tv/tunerresourcemanager/TunerResourceManager.java +++ b/media/java/android/media/tv/tunerresourcemanager/TunerResourceManager.java @@ -64,6 +64,7 @@ public class TunerResourceManager { private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); public static final int INVALID_RESOURCE_HANDLE = -1; + public static final int INVALID_OWNER_ID = -1; /** * Tuner resource type to help generate resource handle */ @@ -73,6 +74,7 @@ public class TunerResourceManager { TUNER_RESOURCE_TYPE_DESCRAMBLER, TUNER_RESOURCE_TYPE_LNB, TUNER_RESOURCE_TYPE_CAS_SESSION, + TUNER_RESOURCE_TYPE_MAX, }) @Retention(RetentionPolicy.SOURCE) public @interface TunerResourceType {} @@ -82,6 +84,7 @@ public class TunerResourceManager { public static final int TUNER_RESOURCE_TYPE_DESCRAMBLER = 2; public static final int TUNER_RESOURCE_TYPE_LNB = 3; public static final int TUNER_RESOURCE_TYPE_CAS_SESSION = 4; + public static final int TUNER_RESOURCE_TYPE_MAX = 5; private final ITunerResourceManager mService; private final int mUserId; @@ -243,16 +246,16 @@ public class TunerResourceManager { * before this request. * * @param request {@link TunerFrontendRequest} information of the current request. - * @param frontendId a one-element array to return the granted frontendId. If - * no frontend granted, this will return {@link #INVALID_FRONTEND_ID}. + * @param frontendHandle a one-element array to return the granted frontendHandle. If + * no frontend granted, this will return {@link #INVALID_RESOURCE_HANDLE}. * * @return true if there is frontend granted. */ public boolean requestFrontend(@NonNull TunerFrontendRequest request, - @Nullable int[] frontendId) { + @Nullable int[] frontendHandle) { boolean result = false; try { - result = mService.requestFrontend(request, frontendId); + result = mService.requestFrontend(request, frontendHandle); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -393,15 +396,15 @@ public class TunerResourceManager { * <p><strong>Note:</strong> {@link #setLnbInfoList(int[])} must be called before this request. * * @param request {@link TunerLnbRequest} information of the current request. - * @param lnbId a one-element array to return the granted Lnb id. - * If no Lnb granted, this will return {@link #INVALID_LNB_ID}. + * @param lnbHandle a one-element array to return the granted Lnb handle. + * If no Lnb granted, this will return {@link #INVALID_RESOURCE_HANDLE}. * * @return true if there is Lnb granted. */ - public boolean requestLnb(@NonNull TunerLnbRequest request, @NonNull int[] lnbId) { + public boolean requestLnb(@NonNull TunerLnbRequest request, @NonNull int[] lnbHandle) { boolean result = false; try { - result = mService.requestLnb(request, lnbId); + result = mService.requestLnb(request, lnbHandle); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -481,11 +484,11 @@ public class TunerResourceManager { * * <p><strong>Note:</strong> {@link #setLnbInfoList(int[])} must be called before this release. * - * @param lnbId the id of the released Tuner Lnb. + * @param lnbHandle the handle of the released Tuner Lnb. */ - public void releaseLnb(int lnbId) { + public void releaseLnb(int lnbHandle) { try { - mService.releaseLnb(lnbId); + mService.releaseLnb(lnbHandle); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } 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 dfd23df40374..43b48546aada 100644 --- a/services/core/java/com/android/server/tv/tunerresourcemanager/ClientProfile.java +++ b/services/core/java/com/android/server/tv/tunerresourcemanager/ClientProfile.java @@ -68,6 +68,11 @@ public final class ClientProfile { private Set<Integer> mUsingFrontendIds = new HashSet<>(); /** + * List of the Lnb ids that are used by the current client. + */ + private Set<Integer> mUsingLnbIds = new HashSet<>(); + + /** * Optional arbitrary priority value given by the client. * * <p>This value can override the default priorotiy calculated from @@ -146,6 +151,30 @@ public final class ClientProfile { mUsingFrontendIds.remove(frontendId); } + /** + * Set when the client starts to use an Lnb. + * + * @param lnbId being used. + */ + public void useLnb(int lnbId) { + mUsingLnbIds.add(lnbId); + } + + public Set<Integer> getInUseLnbIds() { + return mUsingLnbIds; + } + + /** + * Called when the client released an lnb. + * + * <p>This could happen when client resource reclaimed. + * + * @param lnbId being released. + */ + public void releaseLnb(int lnbId) { + mUsingLnbIds.remove(lnbId); + } + @Override public String toString() { return "ClientProfile[id=" + this.mId + ", tvInputSessionId=" + this.mTvInputSessionId diff --git a/services/core/java/com/android/server/tv/tunerresourcemanager/FrontendResource.java b/services/core/java/com/android/server/tv/tunerresourcemanager/FrontendResource.java index 56f61599c998..7ea62b25c39a 100644 --- a/services/core/java/com/android/server/tv/tunerresourcemanager/FrontendResource.java +++ b/services/core/java/com/android/server/tv/tunerresourcemanager/FrontendResource.java @@ -27,14 +27,7 @@ import java.util.Set; * * @hide */ -public final class FrontendResource { - public static final int INVALID_OWNER_ID = -1; - - /** - * Id of the current frontend. Should not be changed and should be aligned with the driver level - * implementation. - */ - private final int mId; +public final class FrontendResource extends TunerResourceBasic { /** * see {@link android.media.tv.tuner.frontend.FrontendSettings.Type} @@ -51,28 +44,12 @@ public final class FrontendResource { */ private Set<Integer> mExclusiveGroupMemberFeIds = new HashSet<>(); - /** - * If the current resource is in use. Once resources under the same exclusive group id is in use - * all other resources in the same group would be considered in use. - */ - private boolean mIsInUse; - - /** - * The owner client's id if this resource is occupied. Owner of the resource under the same - * exclusive group id would be considered as the whole group's owner. - */ - private int mOwnerClientId = INVALID_OWNER_ID; - private FrontendResource(Builder builder) { - this.mId = builder.mId; + super(builder); this.mType = builder.mType; this.mExclusiveGroupId = builder.mExclusiveGroupId; } - public int getId() { - return mId; - } - public int getType() { return mType; } @@ -112,32 +89,6 @@ public final class FrontendResource { mExclusiveGroupMemberFeIds.remove(id); } - public boolean isInUse() { - return mIsInUse; - } - - public int getOwnerClientId() { - return mOwnerClientId; - } - - /** - * Set an owner client on the resource. - * - * @param ownerClientId the id of the owner client. - */ - public void setOwner(int ownerClientId) { - mIsInUse = true; - mOwnerClientId = ownerClientId; - } - - /** - * Remove an owner client from the resource. - */ - public void removeOwner() { - mIsInUse = false; - mOwnerClientId = INVALID_OWNER_ID; - } - @Override public String toString() { return "FrontendResource[id=" + this.mId + ", type=" + this.mType @@ -149,13 +100,12 @@ public final class FrontendResource { /** * Builder class for {@link FrontendResource}. */ - public static class Builder { - private final int mId; + public static class Builder extends TunerResourceBasic.Builder { @Type private int mType; private int mExclusiveGroupId; Builder(int id) { - this.mId = id; + super(id); } /** @@ -183,6 +133,7 @@ public final class FrontendResource { * * @return {@link FrontendResource}. */ + @Override public FrontendResource build() { FrontendResource frontendResource = new FrontendResource(this); return frontendResource; diff --git a/services/core/java/com/android/server/tv/tunerresourcemanager/LnbResource.java b/services/core/java/com/android/server/tv/tunerresourcemanager/LnbResource.java new file mode 100644 index 000000000000..345b4b261c74 --- /dev/null +++ b/services/core/java/com/android/server/tv/tunerresourcemanager/LnbResource.java @@ -0,0 +1,56 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.server.tv.tunerresourcemanager; + +/** + * An Lnb resource object used by the Tuner Resource Manager to record the tuner Lnb + * information. + * + * @hide + */ +public final class LnbResource extends TunerResourceBasic { + + private LnbResource(Builder builder) { + super(builder); + } + + @Override + public String toString() { + return "LnbResource[id=" + this.mId + + ", isInUse=" + this.mIsInUse + ", ownerClientId=" + this.mOwnerClientId + "]"; + } + + /** + * Builder class for {@link LnbResource}. + */ + public static class Builder extends TunerResourceBasic.Builder { + + Builder(int id) { + super(id); + } + + /** + * Build a {@link LnbResource}. + * + * @return {@link LnbResource}. + */ + @Override + public LnbResource build() { + LnbResource lnb = new LnbResource(this); + return lnb; + } + } +} diff --git a/services/core/java/com/android/server/tv/tunerresourcemanager/TunerResourceBasic.java b/services/core/java/com/android/server/tv/tunerresourcemanager/TunerResourceBasic.java new file mode 100644 index 000000000000..7f133c3ab9f9 --- /dev/null +++ b/services/core/java/com/android/server/tv/tunerresourcemanager/TunerResourceBasic.java @@ -0,0 +1,97 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.server.tv.tunerresourcemanager; + +import static android.media.tv.tunerresourcemanager.TunerResourceManager.INVALID_OWNER_ID; + +/** + * A Tuner resource basic object used by the Tuner Resource Manager to record the resource + * information. + * + * @hide + */ +public class TunerResourceBasic { + /** + * Id of the current resource. Should not be changed and should be aligned with the driver level + * implementation. + */ + final int mId; + + /** + * If the current resource is in use. + */ + boolean mIsInUse; + + /** + * The owner client's id if this resource is occupied. + */ + int mOwnerClientId = INVALID_OWNER_ID; + + TunerResourceBasic(Builder builder) { + this.mId = builder.mId; + } + + public int getId() { + return mId; + } + + public boolean isInUse() { + return mIsInUse; + } + + public int getOwnerClientId() { + return mOwnerClientId; + } + + /** + * Set an owner client on the resource. + * + * @param ownerClientId the id of the owner client. + */ + public void setOwner(int ownerClientId) { + mIsInUse = true; + mOwnerClientId = ownerClientId; + } + + /** + * Remove an owner client from the resource. + */ + public void removeOwner() { + mIsInUse = false; + mOwnerClientId = INVALID_OWNER_ID; + } + + /** + * Builder class for {@link TunerResourceBasic}. + */ + public static class Builder { + private final int mId; + + Builder(int id) { + this.mId = id; + } + + /** + * Build a {@link TunerResourceBasic}. + * + * @return {@link TunerResourceBasic}. + */ + public TunerResourceBasic build() { + TunerResourceBasic resource = new TunerResourceBasic(this); + return resource; + } + } +} 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 fd2445f8366e..acb6f950b6b4 100644 --- a/services/core/java/com/android/server/tv/tunerresourcemanager/TunerResourceManagerService.java +++ b/services/core/java/com/android/server/tv/tunerresourcemanager/TunerResourceManagerService.java @@ -63,6 +63,8 @@ public class TunerResourceManagerService extends SystemService { // Map of the current available frontend resources private Map<Integer, FrontendResource> mFrontendResources = new HashMap<>(); + // Map of the current available lnb resources + private Map<Integer, LnbResource> mLnbResources = new HashMap<>(); @GuardedBy("mLock") private Map<Integer, ResourcesReclaimListenerRecord> mListeners = new HashMap<>(); @@ -164,12 +166,13 @@ public class TunerResourceManagerService extends SystemService { } @Override - public void setLnbInfoList(int[] lnbIds) { + public void setLnbInfoList(int[] lnbIds) throws RemoteException { enforceTrmAccessPermission("setLnbInfoList"); - if (DEBUG) { - for (int i = 0; i < lnbIds.length; i++) { - Slog.d(TAG, "updateLnbInfo(lnbId=" + lnbIds[i] + ")"); - } + if (lnbIds == null) { + throw new RemoteException("Lnb id list can't be null"); + } + synchronized (mLock) { + setLnbInfoListInternal(lnbIds); } } @@ -237,14 +240,20 @@ public class TunerResourceManagerService extends SystemService { } @Override - public boolean requestLnb(@NonNull TunerLnbRequest request, @NonNull int[] lnbHandle) { + public boolean requestLnb(@NonNull TunerLnbRequest request, @NonNull int[] lnbHandle) + throws RemoteException { enforceTunerAccessPermission("requestLnb"); enforceTrmAccessPermission("requestLnb"); - if (DEBUG) { - Slog.d(TAG, "requestLnb(request=" + request + ")"); + if (lnbHandle == null) { + throw new RemoteException("lnbHandle can't be null"); + } + synchronized (mLock) { + try { + return requestLnbInternal(request, lnbHandle); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } } - - return true; } @Override @@ -287,11 +296,14 @@ public class TunerResourceManagerService extends SystemService { } @Override - public void releaseLnb(int lnbId) { + public void releaseLnb(int lnbHandle) throws RemoteException { enforceTunerAccessPermission("releaseLnb"); enforceTrmAccessPermission("releaseLnb"); - if (DEBUG) { - Slog.d(TAG, "releaseLnb(lnbId=" + lnbId + ")"); + if (!validateResourceHandle(TunerResourceManager.TUNER_RESOURCE_TYPE_LNB, lnbHandle)) { + throw new RemoteException("lnbHandle can't be invalid"); + } + synchronized (mLock) { + releaseLnbInternal(getResourceIdFromHandle(lnbHandle)); } } @@ -405,6 +417,38 @@ public class TunerResourceManagerService extends SystemService { } @VisibleForTesting + protected void setLnbInfoListInternal(int[] lnbIds) { + if (DEBUG) { + for (int i = 0; i < lnbIds.length; i++) { + Slog.d(TAG, "updateLnbInfo(lnbId=" + lnbIds[i] + ")"); + } + } + + // A set to record the Lnbs pending on updating. Ids will be removed + // from this set once its updating finished. Any lnb left in this set when all + // the updates are done will be removed from mLnbResources. + Set<Integer> updatingLnbIds = new HashSet<>(getLnbResources().keySet()); + + // Update lnbResources map and other mappings accordingly + for (int i = 0; i < lnbIds.length; i++) { + if (getLnbResource(lnbIds[i]) != null) { + if (DEBUG) { + Slog.d(TAG, "Lnb id=" + lnbIds[i] + "exists."); + } + updatingLnbIds.remove(lnbIds[i]); + } else { + // Add a new lnb resource + LnbResource newLnb = new LnbResource.Builder(lnbIds[i]).build(); + addLnbResource(newLnb); + } + } + + for (int removingId : updatingLnbIds) { + removeLnbResource(removingId); + } + } + + @VisibleForTesting protected boolean requestFrontendInternal(TunerFrontendRequest request, int[] frontendHandle) throws RemoteException { if (DEBUG) { @@ -458,8 +502,8 @@ public class TunerResourceManagerService extends SystemService { if (inUseLowestPriorityFrId > -1 && (requestClient.getPriority() > currentLowestPriority)) { frontendHandle[0] = generateResourceHandle( TunerResourceManager.TUNER_RESOURCE_TYPE_FRONTEND, inUseLowestPriorityFrId); - reclaimFrontendResource(getFrontendResource( - inUseLowestPriorityFrId).getOwnerClientId()); + reclaimResource(getFrontendResource(inUseLowestPriorityFrId).getOwnerClientId(), + TunerResourceManager.TUNER_RESOURCE_TYPE_FRONTEND); updateFrontendClientMappingOnNewGrant(inUseLowestPriorityFrId, request.getClientId()); return true; } @@ -468,6 +512,62 @@ public class TunerResourceManagerService extends SystemService { } @VisibleForTesting + protected boolean requestLnbInternal(TunerLnbRequest request, int[] lnbHandle) + throws RemoteException { + if (DEBUG) { + Slog.d(TAG, "requestLnb(request=" + request + ")"); + } + + lnbHandle[0] = TunerResourceManager.INVALID_RESOURCE_HANDLE; + if (!checkClientExists(request.getClientId())) { + Slog.e(TAG, "Request lnb from unregistered client:" + request.getClientId()); + return false; + } + ClientProfile requestClient = getClientProfile(request.getClientId()); + int grantingLnbId = -1; + int inUseLowestPriorityLnbId = -1; + // Priority max value is 1000 + int currentLowestPriority = MAX_CLIENT_PRIORITY + 1; + for (LnbResource lnb : getLnbResources().values()) { + if (!lnb.isInUse()) { + // Grant the unused lnb with lower id first + grantingLnbId = lnb.getId(); + break; + } else { + // Record the lnb id with the lowest client priority among all the + // in use lnb when no available lnb has been found. + int priority = getOwnerClientPriority(lnb); + if (currentLowestPriority > priority) { + inUseLowestPriorityLnbId = lnb.getId(); + currentLowestPriority = priority; + } + } + } + + // Grant Lnb when there is unused resource. + if (grantingLnbId > -1) { + lnbHandle[0] = generateResourceHandle( + TunerResourceManager.TUNER_RESOURCE_TYPE_LNB, grantingLnbId); + updateLnbClientMappingOnNewGrant(grantingLnbId, request.getClientId()); + return true; + } + + // When all the resources are occupied, grant the lowest priority resource if the + // request client has higher priority. + if (inUseLowestPriorityLnbId > -1 + && (requestClient.getPriority() > currentLowestPriority)) { + lnbHandle[0] = generateResourceHandle( + TunerResourceManager.TUNER_RESOURCE_TYPE_LNB, inUseLowestPriorityLnbId); + reclaimResource(getLnbResource(inUseLowestPriorityLnbId).getOwnerClientId(), + TunerResourceManager.TUNER_RESOURCE_TYPE_LNB); + updateLnbClientMappingOnNewGrant(inUseLowestPriorityLnbId, request.getClientId()); + return true; + } + + return false; + } + + @VisibleForTesting void releaseFrontendInternal(int frontendId) { if (DEBUG) { Slog.d(TAG, "releaseFrontend(id=" + frontendId + ")"); @@ -476,6 +576,14 @@ public class TunerResourceManagerService extends SystemService { } @VisibleForTesting + void releaseLnbInternal(int lnbId) { + if (DEBUG) { + Slog.d(TAG, "releaseLnb(lnbId=" + lnbId + ")"); + } + updateLnbClientMappingOnRelease(lnbId); + } + + @VisibleForTesting boolean requestDemuxInternal(TunerDemuxRequest request, int[] demuxHandle) { if (DEBUG) { Slog.d(TAG, "requestDemux(request=" + request + ")"); @@ -542,12 +650,18 @@ public class TunerResourceManagerService extends SystemService { } @VisibleForTesting - protected void reclaimFrontendResource(int reclaimingId) { + protected void reclaimResource(int reclaimingId, + @TunerResourceManager.TunerResourceType int resourceType) { + if (DEBUG) { + Slog.d(TAG, "Reclaiming resources because higher priority client request resource type " + + resourceType); + } try { mListeners.get(reclaimingId).getListener().onReclaimResources(); } catch (RemoteException e) { Slog.e(TAG, "Failed to reclaim resources on client " + reclaimingId, e); } + // TODO clean all the client and resources mapping/ownership } @VisibleForTesting @@ -591,14 +705,28 @@ public class TunerResourceManagerService extends SystemService { } } + private void updateLnbClientMappingOnNewGrant(int grantingId, int ownerClientId) { + LnbResource grantingLnb = getLnbResource(grantingId); + ClientProfile ownerProfile = getClientProfile(ownerClientId); + grantingLnb.setOwner(ownerClientId); + ownerProfile.useLnb(grantingId); + } + + private void updateLnbClientMappingOnRelease(int lnbId) { + LnbResource releasingLnb = getLnbResource(lnbId); + ClientProfile ownerProfile = getClientProfile(releasingLnb.getOwnerClientId()); + releasingLnb.removeOwner(); + ownerProfile.releaseLnb(lnbId); + } + /** - * Get the owner client's priority from the frontend id. + * Get the owner client's priority from the resource id. * - * @param frontend an in use frontend. - * @return the priority of the owner client of the frontend. + * @param resource a in use tuner resource. + * @return the priority of the owner client of the resource. */ - private int getOwnerClientPriority(FrontendResource frontend) { - return getClientProfile(frontend.getOwnerClientId()).getPriority(); + private int getOwnerClientPriority(TunerResourceBasic resource) { + return getClientProfile(resource.getOwnerClientId()).getPriority(); } @VisibleForTesting @@ -644,6 +772,30 @@ public class TunerResourceManagerService extends SystemService { @VisibleForTesting @Nullable + protected LnbResource getLnbResource(int lnbId) { + return mLnbResources.get(lnbId); + } + + @VisibleForTesting + protected Map<Integer, LnbResource> getLnbResources() { + return mLnbResources; + } + + private void addLnbResource(LnbResource newLnb) { + // Update resource list and available id list + mLnbResources.put(newLnb.getId(), newLnb); + } + + private void removeLnbResource(int removingId) { + LnbResource lnb = getLnbResource(removingId); + if (lnb.isInUse()) { + releaseLnbInternal(removingId); + } + mLnbResources.remove(removingId); + } + + @VisibleForTesting + @Nullable protected ClientProfile getClientProfile(int clientId) { return mClientProfiles.get(clientId); } 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 13248a00c1b0..b9a33df497e4 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 @@ -32,6 +32,7 @@ import android.media.tv.tunerresourcemanager.TunerDemuxRequest; import android.media.tv.tunerresourcemanager.TunerDescramblerRequest; import android.media.tv.tunerresourcemanager.TunerFrontendInfo; import android.media.tv.tunerresourcemanager.TunerFrontendRequest; +import android.media.tv.tunerresourcemanager.TunerLnbRequest; import android.media.tv.tunerresourcemanager.TunerResourceManager; import android.os.RemoteException; import android.platform.test.annotations.Presubmit; @@ -528,6 +529,94 @@ public class TunerResourceManagerServiceTest { } @Test + public void requestLnbTest_NoLnbAvailable_RequestWithHigherPriority() { + // Register clients + ResourceClientProfile[] profiles = new ResourceClientProfile[2]; + profiles[0] = new ResourceClientProfile("0" /*sessionId*/, + TvInputService.PRIORITY_HINT_USE_CASE_TYPE_PLAYBACK); + profiles[1] = new ResourceClientProfile("1" /*sessionId*/, + TvInputService.PRIORITY_HINT_USE_CASE_TYPE_PLAYBACK); + int[] clientPriorities = {100, 500}; + int[] clientId0 = new int[1]; + int[] clientId1 = new int[1]; + TestResourcesReclaimListener listener = new TestResourcesReclaimListener(); + mTunerResourceManagerService.registerClientProfileInternal( + profiles[0], listener, clientId0); + assertThat(clientId0[0]).isNotEqualTo(TunerResourceManagerService.INVALID_CLIENT_ID); + mTunerResourceManagerService.getClientProfile(clientId0[0]) + .setPriority(clientPriorities[0]); + mTunerResourceManagerService.registerClientProfileInternal( + profiles[1], new TestResourcesReclaimListener(), clientId1); + assertThat(clientId1[0]).isNotEqualTo(TunerResourceManagerService.INVALID_CLIENT_ID); + mTunerResourceManagerService.getClientProfile(clientId1[0]) + .setPriority(clientPriorities[1]); + + // Init lnb resources. + int[] lnbIds = {0}; + mTunerResourceManagerService.setLnbInfoListInternal(lnbIds); + + TunerLnbRequest request = new TunerLnbRequest(clientId0[0]); + int[] lnbHandle = new int[1]; + try { + assertThat(mTunerResourceManagerService + .requestLnbInternal(request, lnbHandle)).isTrue(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + assertThat(mTunerResourceManagerService.getResourceIdFromHandle(lnbHandle[0])) + .isEqualTo(lnbIds[0]); + + request = new TunerLnbRequest(clientId1[0]); + try { + assertThat(mTunerResourceManagerService + .requestLnbInternal(request, lnbHandle)).isTrue(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + assertThat(mTunerResourceManagerService.getResourceIdFromHandle(lnbHandle[0])) + .isEqualTo(lnbIds[0]); + assertThat(mTunerResourceManagerService.getLnbResource(lnbIds[0]) + .isInUse()).isTrue(); + assertThat(mTunerResourceManagerService.getLnbResource(lnbIds[0]) + .getOwnerClientId()).isEqualTo(clientId1[0]); + assertThat(listener.isRelaimed()).isTrue(); + } + + @Test + public void releaseLnbTest() { + // Register clients + ResourceClientProfile[] profiles = new ResourceClientProfile[1]; + profiles[0] = new ResourceClientProfile("0" /*sessionId*/, + TvInputService.PRIORITY_HINT_USE_CASE_TYPE_PLAYBACK); + int[] clientId = new int[1]; + TestResourcesReclaimListener listener = new TestResourcesReclaimListener(); + mTunerResourceManagerService.registerClientProfileInternal(profiles[0], listener, clientId); + assertThat(clientId[0]).isNotEqualTo(TunerResourceManagerService.INVALID_CLIENT_ID); + + // Init lnb resources. + int[] lnbIds = {0}; + mTunerResourceManagerService.setLnbInfoListInternal(lnbIds); + + TunerLnbRequest request = new TunerLnbRequest(clientId[0]); + int[] lnbHandle = new int[1]; + try { + assertThat(mTunerResourceManagerService + .requestLnbInternal(request, lnbHandle)).isTrue(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + int lnbId = mTunerResourceManagerService.getResourceIdFromHandle(lnbHandle[0]); + assertThat(lnbId).isEqualTo(lnbIds[0]); + + // Release lnb + mTunerResourceManagerService.releaseLnbInternal(lnbId); + assertThat(mTunerResourceManagerService + .getLnbResource(lnbId).isInUse()).isFalse(); + assertThat(mTunerResourceManagerService + .getClientProfile(clientId[0]).getInUseLnbIds().size()).isEqualTo(0); + } + + @Test public void unregisterClientTest_usingFrontend() { // Register client ResourceClientProfile profile = new ResourceClientProfile("0" /*sessionId*/, |