Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b80a3077 authored by Amy Zhang's avatar Amy Zhang
Browse files

Complete shareFrontend API implementation in TunerResourceManagerService

Note that we need to consider share frontend situation in the following
processes:

1. Request Frontend: to compare with the highest priority among all the
share fe clients.

2. Reclaim resources: This only happens on the primary owner of a fe, we
need to reclaim all the resources under the share fe clients also.

3. Remove client: when remove the primary owner, it should be treated
the same way as reclaiming. When remove the share fe clients, we can
just remove it from the share owner list.

4. Release resource: this only happens on the primary owner, we need to
release the fe under the share fe clients also.

Test: atest com.android.server.tv.tunerresourcemanager
Bug: 163395799
Change-Id: I46b209cd9d7b28ac2d93f6ec297669484ff46cf6
parent 3cfbdd8a
Loading
Loading
Loading
Loading
+32 −9
Original line number Diff line number Diff line
@@ -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;
    }
+82 −25
Original line number Diff line number Diff line
@@ -213,16 +213,33 @@ public class TunerResourceManagerService extends SystemService implements IBinde
                    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 + " )");
        }
        if (clientId == fe.getOwnerClientId()) {
            ClientProfile ownerClient = getClientProfile(fe.getOwnerClientId());
            for (int shareOwnerId : ownerClient.getShareFeClientIds()) {
                clearFrontendAndClientMapping(getClientProfile(shareOwnerId));
            }
        updateFrontendClientMappingOnRelease(fe);
        }
        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();
    }

+296 −7

File changed.

Preview size limit exceeded, changes collapsed.