diff --git a/core/api/system-current.txt b/core/api/system-current.txt index beac112ea4ce0..ef01fd560d3ab 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -7094,6 +7094,7 @@ package android.media.tv.tuner { method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_TV_SHARED_FILTER) public static android.media.tv.tuner.filter.SharedFilter openSharedFilter(@NonNull android.content.Context, @NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.media.tv.tuner.filter.SharedFilterCallback); method @Nullable public android.media.tv.tuner.filter.TimeFilter openTimeFilter(); method public int removeOutputPid(@IntRange(from=0) int); + method public int requestFrontendById(int); method public int scan(@NonNull android.media.tv.tuner.frontend.FrontendSettings, int, @NonNull java.util.concurrent.Executor, @NonNull android.media.tv.tuner.frontend.ScanCallback); method public int setLnaEnabled(boolean); method public int setMaxNumberOfFrontends(int, @IntRange(from=0) int); diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java index b1c97300d08a9..51b976bf9f698 100644 --- a/media/java/android/media/tv/tuner/Tuner.java +++ b/media/java/android/media/tv/tuner/Tuner.java @@ -289,6 +289,7 @@ public class Tuner implements AutoCloseable { private Integer mFrontendHandle; private Tuner mFeOwnerTuner = null; private int mFrontendType = FrontendSettings.TYPE_UNDEFINED; + private Integer mDesiredFrontendId = null; private int mUserId; private Lnb mLnb; private Integer mLnbHandle; @@ -1326,10 +1327,18 @@ public class Tuner implements AutoCloseable { private boolean requestFrontend() { int[] feHandle = new int[1]; - TunerFrontendRequest request = new TunerFrontendRequest(); - request.clientId = mClientId; - request.frontendType = mFrontendType; - boolean granted = mTunerResourceManager.requestFrontend(request, feHandle); + boolean granted = false; + try { + TunerFrontendRequest request = new TunerFrontendRequest(); + request.clientId = mClientId; + request.frontendType = mFrontendType; + request.desiredId = mDesiredFrontendId == null + ? TunerFrontendRequest.DEFAULT_DESIRED_ID + : mDesiredFrontendId; + granted = mTunerResourceManager.requestFrontend(request, feHandle); + } finally { + mDesiredFrontendId = null; + } if (granted) { mFrontendHandle = feHandle[0]; mFrontend = nativeOpenFrontendByHandle(mFrontendHandle); @@ -2366,6 +2375,50 @@ public class Tuner implements AutoCloseable { } } + /** + * Request a frontend by frontend id. + * + *
This API is used if the applications want to select a desired frontend before + * {@link tune} to use a specific satellite or sending SatCR DiSEqC command for {@link tune}. + * + * @param desiredId the desired fronted Id. It can be retrieved by + * {@link getAvailableFrontendInfos} + * + * @return result status of open operation. + * @throws SecurityException if the caller does not have appropriate permissions. + */ + @Result + public int requestFrontendById(int desiredId) { + mFrontendLock.lock(); + try { + if (mFeOwnerTuner != null) { + Log.e(TAG, "Operation connot be done by sharee of tuner"); + return RESULT_INVALID_STATE; + } + if (mFrontendHandle != null) { + Log.e(TAG, "A frontend has been opened before"); + return RESULT_INVALID_STATE; + } + FrontendInfo frontendInfo = getFrontendInfoById(desiredId); + if (frontendInfo == null) { + Log.e(TAG, "Failed to get a FrontendInfo by frontend id: " + desiredId); + return RESULT_UNAVAILABLE; + } + int frontendType = frontendInfo.getType(); + if (DEBUG) { + Log.d(TAG, "Opening frontend with type " + frontendType + ", id " + desiredId); + } + mFrontendType = frontendType; + mDesiredFrontendId = desiredId; + if (!checkResource(TunerResourceManager.TUNER_RESOURCE_TYPE_FRONTEND, mFrontendLock)) { + return RESULT_UNAVAILABLE; + } + return RESULT_SUCCESS; + } finally { + mFrontendLock.unlock(); + } + } + /** * Open a shared filter instance. * @@ -2445,7 +2498,7 @@ public class Tuner implements AutoCloseable { return granted; } - private boolean checkResource(int resourceType, ReentrantLock localLock) { + private boolean checkResource(int resourceType, ReentrantLock localLock) { switch (resourceType) { case TunerResourceManager.TUNER_RESOURCE_TYPE_FRONTEND: { if (mFrontendHandle == null && !requestResource(resourceType, localLock)) { @@ -2483,7 +2536,7 @@ public class Tuner implements AutoCloseable { // 3) if no, then first release the held lock and grab the TRMS lock to avoid deadlock // 4) grab the local lock again and release the TRMS lock // If localLock is null, we'll assume the caller does not want the lock related operations - private boolean requestResource(int resourceType, ReentrantLock localLock) { + private boolean requestResource(int resourceType, ReentrantLock localLock) { boolean enableLockOperations = localLock != null; // release the local lock first to avoid deadlock diff --git a/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/ITunerResourceManager.aidl b/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/ITunerResourceManager.aidl index 144b98c36655c..e0af76d27a95f 100644 --- a/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/ITunerResourceManager.aidl +++ b/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/ITunerResourceManager.aidl @@ -140,19 +140,29 @@ interface ITunerResourceManager { void setLnbInfoList(in int[] lnbIds); /* - * This API is used by the Tuner framework to request an available frontend from the TunerHAL. + * This API is used by the Tuner framework to request a frontend from the TunerHAL. * - *
There are three possible scenarios: + *
There are two cases: *
Note: {@link #setFrontendInfoList(TunerFrontendInfo[])} must be called diff --git a/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/TunerFrontendRequest.aidl b/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/TunerFrontendRequest.aidl index 4d98222158421..c4598a49d5dd0 100644 --- a/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/TunerFrontendRequest.aidl +++ b/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/TunerFrontendRequest.aidl @@ -22,7 +22,11 @@ package android.media.tv.tunerresourcemanager; * @hide */ parcelable TunerFrontendRequest { + const int DEFAULT_DESIRED_ID = 0xFFFFFFFF; + int clientId; int frontendType; -} \ No newline at end of file + + int desiredId = DEFAULT_DESIRED_ID; +} 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 edd1ef36deda9..ad1ff72f653cf 100644 --- a/services/core/java/com/android/server/tv/tunerresourcemanager/TunerResourceManagerService.java +++ b/services/core/java/com/android/server/tv/tunerresourcemanager/TunerResourceManagerService.java @@ -946,8 +946,12 @@ public class TunerResourceManagerService extends SystemService implements IBinde int inUseLowestPriorityFrHandle = TunerResourceManager.INVALID_RESOURCE_HANDLE; // Priority max value is 1000 int currentLowestPriority = MAX_CLIENT_PRIORITY + 1; + // If the desired frontend id was specified, we only need to check the frontend. + boolean hasDesiredFrontend = request.desiredId != TunerFrontendRequest.DEFAULT_DESIRED_ID; for (FrontendResource fr : getFrontendResources().values()) { - if (fr.getType() == request.frontendType) { + int frontendId = getResourceIdFromHandle(fr.getHandle()); + if (fr.getType() == request.frontendType + && (!hasDesiredFrontend || frontendId == request.desiredId)) { if (!fr.isInUse()) { // Unused resource cannot be acquired if the max is already reached, but // TRM still has to look for the reclaim candidate