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

Commit 0af68d9e authored by Kensuke Miyagi's avatar Kensuke Miyagi Committed by Automerger Merge Worker
Browse files

Merge "Add set/getMaxNumberOfFrontends() support in TunerResourceManager" into...

Merge "Add set/getMaxNumberOfFrontends() support in TunerResourceManager" into tm-dev am: 19b11131 am: cd3236d7

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



Change-Id: I5a48c9bebd63a962871957b80f82e5e9f32c71ec
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents 1a85630c cd3236d7
Loading
Loading
Loading
Loading
+10 −2
Original line number Diff line number Diff line
@@ -1728,7 +1728,9 @@ public class Tuner implements AutoCloseable {
        }
        int res = nativeSetMaxNumberOfFrontends(frontendType, maxNumber);
        if (res == RESULT_SUCCESS) {
            // TODO: b/211778848 Update Tuner Resource Manager.
            if (!mTunerResourceManager.setMaxNumberOfFrontends(frontendType, maxNumber)) {
                res = RESULT_INVALID_ARGUMENT;
            }
        }
        return res;
    }
@@ -1749,7 +1751,13 @@ public class Tuner implements AutoCloseable {
                    TunerVersionChecker.TUNER_VERSION_2_0, "Set maximum Frontends")) {
            return -1;
        }
        return nativeGetMaxNumberOfFrontends(frontendType);
        int maxNumFromHAL = nativeGetMaxNumberOfFrontends(frontendType);
        int maxNumFromTRM = mTunerResourceManager.getMaxNumberOfFrontends(frontendType);
        if (maxNumFromHAL != maxNumFromTRM) {
            Log.w(TAG, "max num of usable frontend is out-of-sync b/w " + maxNumFromHAL
                    + " != " + maxNumFromTRM);
        }
        return maxNumFromHAL;
    }

    /** @hide */
+37 −0
Original line number Diff line number Diff line
@@ -400,6 +400,43 @@ public class TunerResourceManager {
        return result;
    }

    /**
     * Sets the maximum usable frontends number of a given frontend type. It is used to enable or
     * disable frontends when cable connection status is changed by user.
     *
     * @param frontendType the frontendType which the maximum usable number will be set for.
     * @param maxNum the new maximum usable number.
     *
     * @return true if  successful and false otherwise.
     */
    public boolean setMaxNumberOfFrontends(int frontendType, int maxNum) {
        boolean result = false;
        try {
            result = mService.setMaxNumberOfFrontends(frontendType, maxNum);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
        return result;
    }

    /**
     * Get the maximum usable frontends number of a given frontend type.
     *
     * @param frontendType the frontendType which the maximum usable number will be queried for.
     *
     * @return the maximum usable number of the queried frontend type. Returns -1 when the
     *         frontendType is invalid
     */
    public int getMaxNumberOfFrontends(int frontendType) {
        int result = -1;
        try {
            result = mService.getMaxNumberOfFrontends(frontendType);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
        return result;
    }

    /**
     * Requests from the client to share frontend with an existing client.
     *
+21 −0
Original line number Diff line number Diff line
@@ -165,6 +165,27 @@ interface ITunerResourceManager {
     */
    boolean requestFrontend(in TunerFrontendRequest request, out int[] frontendHandle);

    /*
     * Sets the maximum usable frontends number of a given frontend type. It is used to enable or
     * disable frontends when cable connection status is changed by user.
     *
     * @param frontendType the frontendType which the maximum usable number will be set for.
     * @param maxNumber the new maximum usable number.
     *
     * @return true if  successful and false otherwise.
     */
    boolean setMaxNumberOfFrontends(in int frontendType, in int maxNum);

    /*
     * Get the maximum usable frontends number of a given frontend type.
     *
     * @param frontendType the frontendType which the maximum usable number will be queried for.
     *
     * @return the maximum usable number of the queried frontend type. Returns -1 when the
     *         frontendType is invalid
     */
    int getMaxNumberOfFrontends(in int frontendType);

    /*
     * Requests to share frontend with an existing client.
     *
+25 −0
Original line number Diff line number Diff line
@@ -15,6 +15,8 @@
 */
package com.android.server.tv.tunerresourcemanager;

import android.media.tv.tunerresourcemanager.TunerResourceManager;

import java.util.HashSet;
import java.util.Set;

@@ -62,6 +64,11 @@ public final class ClientProfile {
     */
    private int mNiceValue;

    /**
     * The handle of the primary frontend resource
     */
    private int mPrimaryUsingFrontendHandle = TunerResourceManager.INVALID_RESOURCE_HANDLE;

    /**
     * List of the frontend handles that are used by the current client.
     */
@@ -174,6 +181,22 @@ public final class ClientProfile {
        mUsingFrontendHandles.add(frontendHandle);
    }

    /**
     * Set the primary frontend used by the client
     *
     * @param frontendHandle being used.
     */
    public void setPrimaryFrontend(int frontendHandle) {
        mPrimaryUsingFrontendHandle = frontendHandle;
    }

    /**
     * Get the primary frontend used by the client
     */
    public int getPrimaryFrontend() {
        return mPrimaryUsingFrontendHandle;
    }

    /**
     * Update the set of client that share frontend with the current client.
     *
@@ -206,6 +229,7 @@ public final class ClientProfile {
    public void releaseFrontend() {
        mUsingFrontendHandles.clear();
        mShareFeClientIds.clear();
        mPrimaryUsingFrontendHandle = TunerResourceManager.INVALID_RESOURCE_HANDLE;
    }

    /**
@@ -276,6 +300,7 @@ public final class ClientProfile {
    public void reclaimAllResources() {
        mUsingFrontendHandles.clear();
        mShareFeClientIds.clear();
        mPrimaryUsingFrontendHandle = TunerResourceManager.INVALID_RESOURCE_HANDLE;
        mUsingLnbHandles.clear();
        mUsingCasSystemId = INVALID_RESOURCE_ID;
        mUsingCiCamId = INVALID_RESOURCE_ID;
+189 −79
Original line number Diff line number Diff line
@@ -42,6 +42,7 @@ import android.os.SystemClock;
import android.util.IndentingPrintWriter;
import android.util.Log;
import android.util.Slog;
import android.util.SparseIntArray;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
@@ -72,14 +73,28 @@ public class TunerResourceManagerService extends SystemService implements IBinde
    private static final long INVALID_THREAD_ID = -1;
    private static final long TRMS_LOCK_TIMEOUT = 500;

    private static final int INVALID_FE_COUNT = -1;

    // Map of the registered client profiles
    private Map<Integer, ClientProfile> mClientProfiles = new HashMap<>();
    private int mNextUnusedClientId = 0;

    // Map of the current available frontend resources
    private Map<Integer, FrontendResource> mFrontendResources = new HashMap<>();
    // Backup Map of the current available frontend resources
    // SparseIntArray of the max usable number for each frontend resource type
    private SparseIntArray mFrontendMaxUsableNums = new SparseIntArray();
    // SparseIntArray of the currently used number for each frontend resource type
    private SparseIntArray mFrontendUsedNums = new SparseIntArray();
    // SparseIntArray of the existing number for each frontend resource type
    private SparseIntArray mFrontendExistingNums = new SparseIntArray();

    // Backups for the frontend resource maps for enabling testing with custom resource maps
    // such as TunerTest.testHasUnusedFrontend1()
    private Map<Integer, FrontendResource> mFrontendResourcesBackup = new HashMap<>();
    private SparseIntArray mFrontendMaxUsableNumsBackup = new SparseIntArray();
    private SparseIntArray mFrontendUsedNumsBackup = new SparseIntArray();
    private SparseIntArray mFrontendExistingNumsBackup = new SparseIntArray();

    // Map of the current available lnb resources
    private Map<Integer, LnbResource> mLnbResources = new HashMap<>();
    // Map of the current available Cas resources
@@ -267,6 +282,29 @@ public class TunerResourceManagerService extends SystemService implements IBinde
            }
        }

        @Override
        public boolean setMaxNumberOfFrontends(int frontendType, int maxUsableNum) {
            enforceTunerAccessPermission("requestFrontend");
            enforceTrmAccessPermission("requestFrontend");
            if (maxUsableNum < 0) {
                Slog.w(TAG, "setMaxNumberOfFrontends failed with maxUsableNum:" + maxUsableNum
                        + " frontendType:" + frontendType);
                return false;
            }
            synchronized (mLock) {
                return setMaxNumberOfFrontendsInternal(frontendType, maxUsableNum);
            }
        }

        @Override
        public int getMaxNumberOfFrontends(int frontendType) {
            enforceTunerAccessPermission("requestFrontend");
            enforceTrmAccessPermission("requestFrontend");
            synchronized (mLock) {
                return getMaxNumberOfFrontendsInternal(frontendType);
            }
        }

        @Override
        public void shareFrontend(int selfClientId, int targetClientId) throws RemoteException {
            enforceTunerAccessPermission("shareFrontend");
@@ -572,71 +610,19 @@ public class TunerResourceManagerService extends SystemService implements IBinde
            }

            synchronized (mLock) {
                if (mClientProfiles != null) {
                    pw.println("ClientProfiles:");
                    pw.increaseIndent();
                    for (Map.Entry<Integer, ClientProfile> entry : mClientProfiles.entrySet()) {
                        pw.println(entry.getKey() + " : " + entry.getValue());
                    }
                    pw.decreaseIndent();
                }

                if (mFrontendResources != null) {
                    pw.println("FrontendResources:");
                    pw.increaseIndent();
                    for (Map.Entry<Integer, FrontendResource> entry
                            : mFrontendResources.entrySet()) {
                        pw.println(entry.getKey() + " : " + entry.getValue());
                    }
                    pw.decreaseIndent();
                }

                if (mFrontendResourcesBackup != null) {
                    pw.println("FrontendResourcesBackUp:");
                    pw.increaseIndent();
                    for (Map.Entry<Integer, FrontendResource> entry
                            : mFrontendResourcesBackup.entrySet()) {
                        pw.println(entry.getKey() + " : " + entry.getValue());
                    }
                    pw.decreaseIndent();
                }

                if (mLnbResources != null) {
                    pw.println("LnbResources:");
                    pw.increaseIndent();
                    for (Map.Entry<Integer, LnbResource> entry : mLnbResources.entrySet()) {
                        pw.println(entry.getKey() + " : " + entry.getValue());
                    }
                    pw.decreaseIndent();
                }

                if (mCasResources != null) {
                    pw.println("CasResources:");
                    pw.increaseIndent();
                    for (Map.Entry<Integer, CasResource> entry : mCasResources.entrySet()) {
                        pw.println(entry.getKey() + " : " + entry.getValue());
                    }
                    pw.decreaseIndent();
                }

                if (mCiCamResources != null) {
                    pw.println("CiCamResources:");
                    pw.increaseIndent();
                    for (Map.Entry<Integer, CiCamResource> entry : mCiCamResources.entrySet()) {
                        pw.println(entry.getKey() + " : " + entry.getValue());
                    }
                    pw.decreaseIndent();
                }

                if (mListeners != null) {
                    pw.println("Listners:");
                    pw.increaseIndent();
                    for (Map.Entry<Integer, ResourcesReclaimListenerRecord> entry
                            : mListeners.entrySet()) {
                        pw.println(entry.getKey() + " : " + entry.getValue());
                    }
                    pw.decreaseIndent();
                }
                dumpMap(mClientProfiles, "ClientProfiles:", "\n", pw);
                dumpMap(mFrontendResources, "FrontendResources:", "\n", pw);
                dumpSIA(mFrontendExistingNums, "FrontendExistingNums:", ", ", pw);
                dumpSIA(mFrontendUsedNums, "FrontendUsedNums:", ", ", pw);
                dumpSIA(mFrontendMaxUsableNums, "FrontendMaxUsableNums:", ", ", pw);
                dumpMap(mFrontendResourcesBackup, "FrontendResourcesBackUp:", "\n", pw);
                dumpSIA(mFrontendExistingNumsBackup, "FrontendExistingNumsBackup:", ", ", pw);
                dumpSIA(mFrontendUsedNumsBackup, "FrontendUsedNumsBackup:", ", ", pw);
                dumpSIA(mFrontendMaxUsableNumsBackup, "FrontendUsedNumsBackup:", ", ", pw);
                dumpMap(mLnbResources, "LnbResource:", "\n", pw);
                dumpMap(mCasResources, "CasResource:", "\n", pw);
                dumpMap(mCiCamResources, "CiCamResource:", "\n", pw);
                dumpMap(mListeners, "Listners:", "\n", pw);
            }
        }

@@ -786,10 +772,10 @@ public class TunerResourceManagerService extends SystemService implements IBinde
    protected void storeResourceMapInternal(int resourceType) {
        switch (resourceType) {
            case TunerResourceManager.TUNER_RESOURCE_TYPE_FRONTEND:
                if (mFrontendResources != null && mFrontendResources.size() > 0) {
                    mFrontendResourcesBackup.putAll(mFrontendResources);
                    mFrontendResources.clear();
                }
                replaceFeResourceMap(mFrontendResources, mFrontendResourcesBackup);
                replaceFeCounts(mFrontendExistingNums, mFrontendExistingNumsBackup);
                replaceFeCounts(mFrontendUsedNums, mFrontendUsedNumsBackup);
                replaceFeCounts(mFrontendMaxUsableNums, mFrontendMaxUsableNumsBackup);
                break;
                // TODO: implement for other resource type when needed
            default:
@@ -800,9 +786,10 @@ public class TunerResourceManagerService extends SystemService implements IBinde
    protected void clearResourceMapInternal(int resourceType) {
        switch (resourceType) {
            case TunerResourceManager.TUNER_RESOURCE_TYPE_FRONTEND:
                if (mFrontendResources != null) {
                    mFrontendResources.clear();
                }
                replaceFeResourceMap(null, mFrontendResources);
                replaceFeCounts(null, mFrontendExistingNums);
                replaceFeCounts(null, mFrontendUsedNums);
                replaceFeCounts(null, mFrontendMaxUsableNums);
                break;
                // TODO: implement for other resource type when needed
            default:
@@ -813,12 +800,10 @@ public class TunerResourceManagerService extends SystemService implements IBinde
    protected void restoreResourceMapInternal(int resourceType) {
        switch (resourceType) {
            case TunerResourceManager.TUNER_RESOURCE_TYPE_FRONTEND:
                if (mFrontendResourcesBackup != null
                        && mFrontendResourcesBackup.size() > 0) {
                    mFrontendResources.clear();
                    mFrontendResources.putAll(mFrontendResourcesBackup);
                    mFrontendResourcesBackup.clear();
                }
                replaceFeResourceMap(mFrontendResourcesBackup, mFrontendResources);
                replaceFeCounts(mFrontendExistingNumsBackup, mFrontendExistingNums);
                replaceFeCounts(mFrontendUsedNumsBackup, mFrontendUsedNums);
                replaceFeCounts(mFrontendMaxUsableNumsBackup, mFrontendMaxUsableNums);
                break;
                // TODO: implement for other resource type when needed
            default:
@@ -954,6 +939,11 @@ public class TunerResourceManagerService extends SystemService implements IBinde
        for (FrontendResource fr : getFrontendResources().values()) {
            if (fr.getType() == request.frontendType) {
                if (!fr.isInUse()) {
                    // Unused resource cannot be acquired if the max is already reached, but
                    // TRM still has to look for the reclaim candidate
                    if (isFrontendMaxNumUseReached(request.frontendType)) {
                        continue;
                    }
                    // Grant unused frontend with no exclusive group members first.
                    if (fr.getExclusiveGroupMemberFeHandles().isEmpty()) {
                        grantingFrontendHandle = fr.getHandle();
@@ -1021,6 +1011,9 @@ public class TunerResourceManagerService extends SystemService implements IBinde
        for (int inUseHandle : newOwnerProfile.getInUseFrontendHandles()) {
            getFrontendResource(inUseHandle).setOwner(newOwnerId);
        }
        // change the primary frontend
        newOwnerProfile.setPrimaryFrontend(currentOwnerProfile.getPrimaryFrontend());
        currentOwnerProfile.setPrimaryFrontend(TunerResourceManager.INVALID_RESOURCE_HANDLE);
        // double check there is no other resources tied to the previous owner
        for (int inUseHandle : currentOwnerProfile.getInUseFrontendHandles()) {
            int ownerId = getFrontendResource(inUseHandle).getOwnerClientId();
@@ -1657,11 +1650,13 @@ public class TunerResourceManagerService extends SystemService implements IBinde
        FrontendResource grantingFrontend = getFrontendResource(grantingHandle);
        ClientProfile ownerProfile = getClientProfile(ownerClientId);
        grantingFrontend.setOwner(ownerClientId);
        increFrontendNum(mFrontendUsedNums, grantingFrontend.getType());
        ownerProfile.useFrontend(grantingHandle);
        for (int exclusiveGroupMember : grantingFrontend.getExclusiveGroupMemberFeHandles()) {
            getFrontendResource(exclusiveGroupMember).setOwner(ownerClientId);
            ownerProfile.useFrontend(exclusiveGroupMember);
        }
        ownerProfile.setPrimaryFrontend(grantingHandle);
    }

    private void updateLnbClientMappingOnNewGrant(int grantingHandle, int ownerClientId) {
@@ -1755,6 +1750,109 @@ public class TunerResourceManagerService extends SystemService implements IBinde
        return mFrontendResources;
    }

    private boolean setMaxNumberOfFrontendsInternal(int frontendType, int maxUsableNum) {
        int usedNum = mFrontendUsedNums.get(frontendType, INVALID_FE_COUNT);
        if (usedNum == INVALID_FE_COUNT || usedNum <= maxUsableNum) {
            mFrontendMaxUsableNums.put(frontendType, maxUsableNum);
            return true;
        } else {
            Slog.e(TAG, "max number of frontend for frontendType: " + frontendType
                    + " cannot be set to a value lower than the current usage count."
                    + " (requested max num = " + maxUsableNum + ", current usage = " + usedNum);
            return false;
        }
    }

    private int getMaxNumberOfFrontendsInternal(int frontendType) {
        int existingNum = mFrontendExistingNums.get(frontendType, INVALID_FE_COUNT);
        if (existingNum == INVALID_FE_COUNT) {
            Log.e(TAG, "existingNum is -1 for " + frontendType);
            return -1;
        }
        int maxUsableNum = mFrontendMaxUsableNums.get(frontendType, INVALID_FE_COUNT);
        if (maxUsableNum == INVALID_FE_COUNT) {
            return existingNum;
        } else {
            return maxUsableNum;
        }
    }

    private boolean isFrontendMaxNumUseReached(int frontendType) {
        int maxUsableNum = mFrontendMaxUsableNums.get(frontendType, INVALID_FE_COUNT);
        if (maxUsableNum == INVALID_FE_COUNT) {
            return false;
        }
        int useNum = mFrontendUsedNums.get(frontendType, INVALID_FE_COUNT);
        if (useNum == INVALID_FE_COUNT) {
            useNum = 0;
        }
        return useNum >= maxUsableNum;
    }

    private void increFrontendNum(SparseIntArray targetNums, int frontendType) {
        int num = targetNums.get(frontendType, INVALID_FE_COUNT);
        if (num == INVALID_FE_COUNT) {
            targetNums.put(frontendType, 1);
        } else {
            targetNums.put(frontendType, num + 1);
        }
    }

    private void decreFrontendNum(SparseIntArray targetNums, int frontendType) {
        int num = targetNums.get(frontendType, INVALID_FE_COUNT);
        if (num != INVALID_FE_COUNT) {
            targetNums.put(frontendType, num - 1);
        }
    }

    private void replaceFeResourceMap(Map<Integer, FrontendResource> srcMap, Map<Integer,
            FrontendResource> dstMap) {
        if (dstMap != null) {
            dstMap.clear();
            if (srcMap != null && srcMap.size() > 0) {
                dstMap.putAll(srcMap);
            }
        }
    }

    private void replaceFeCounts(SparseIntArray srcCounts, SparseIntArray dstCounts) {
        if (dstCounts != null) {
            dstCounts.clear();
            if (srcCounts != null) {
                for (int i = 0; i < srcCounts.size(); i++) {
                    dstCounts.put(srcCounts.keyAt(i), srcCounts.valueAt(i));
                }
            }
        }
    }
    private void dumpMap(Map<?, ?> targetMap, String headline, String delimiter,
            IndentingPrintWriter pw) {
        if (targetMap != null) {
            pw.println(headline);
            pw.increaseIndent();
            for (Map.Entry<?, ?> entry : targetMap.entrySet()) {
                pw.print(entry.getKey() + " : " + entry.getValue());
                pw.print(delimiter);
            }
            pw.println();
            pw.decreaseIndent();
        }
    }

    private void dumpSIA(SparseIntArray array, String headline, String delimiter,
            IndentingPrintWriter pw) {
        if (array != null) {
            pw.println(headline);
            pw.increaseIndent();
            for (int i = 0; i < array.size(); i++) {
                pw.print(array.keyAt(i) + " : " + array.valueAt(i));
                pw.print(delimiter);
            }
            pw.println();
            pw.decreaseIndent();
        }
    }

    private void addFrontendResource(FrontendResource newFe) {
        // Update the exclusive group member list in all the existing Frontend resource
        for (FrontendResource fe : getFrontendResources().values()) {
@@ -1771,6 +1869,8 @@ public class TunerResourceManagerService extends SystemService implements IBinde
        }
        // Update resource list and available id list
        mFrontendResources.put(newFe.getHandle(), newFe);
        increFrontendNum(mFrontendExistingNums, newFe.getType());

    }

    private void removeFrontendResource(int removingHandle) {
@@ -1789,6 +1889,7 @@ public class TunerResourceManagerService extends SystemService implements IBinde
            getFrontendResource(excGroupmemberFeHandle)
                    .removeExclusiveGroupMemberFeId(fe.getHandle());
        }
        decreFrontendNum(mFrontendExistingNums, fe.getType());
        mFrontendResources.remove(removingHandle);
    }

@@ -1918,6 +2019,15 @@ public class TunerResourceManagerService extends SystemService implements IBinde
            }

        }

        int primaryFeId = profile.getPrimaryFrontend();
        if (primaryFeId != TunerResourceManager.INVALID_RESOURCE_HANDLE) {
            FrontendResource primaryFe = getFrontendResource(primaryFeId);
            if (primaryFe != null) {
                decreFrontendNum(mFrontendUsedNums, primaryFe.getType());
            }
        }

        profile.releaseFrontend();
    }