Add API for requesting a specific frontend.

Test: atest android.media.tv.tuner.cts
Bug: b/239240556
Change-Id: Ia2ade164da52aca1a3e347781851f5a86e8d8c0f
This commit is contained in:
Ray Chin
2022-10-05 16:33:51 +08:00
parent f0a1ec8e54
commit fa22e71e51
5 changed files with 87 additions and 15 deletions

View File

@@ -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);

View File

@@ -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.
*
* <p> 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

View File

@@ -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.
*
* <p>There are three possible scenarios:
* <p>There are two cases:
* <ul>
* <li>If there is frontend available, the API would send the id back.
*
* <li>If no Frontend is available but the current request info can show higher priority than
* other uses of Frontend, the API will send
* <li>If the desiredId is not {@link TunerFrontendRequest#DEFAULT_DESIRED_ID}
* <li><li>If the desired frontend with the given frontendType is available, the API would send
* the id back.
* <li><li>If the desired frontend with the given frontendType is in use but the current request
* info can show higher priority than other uses of Frontend, the API will send
* {@link IResourcesReclaimListener#onReclaimResources()} to the {@link Tuner}. Tuner would
* handle the resource reclaim on the holder of lower priority and notify the holder of its
* resource loss.
* <li><li>If no frontend can be granted, the API would return false.
* <ul>
*
* <li>If no frontend can be granted, the API would return false.
* <li>If the desiredId is {@link TunerFrontendRequest#DEFAULT_DESIRED_ID}
* <li><li>If there is frontend available, the API would send the id back.
* <li><li>If no Frontend is available but the current request info can show higher priority
* than other uses of Frontend, the API will send
* {@link IResourcesReclaimListener#onReclaimResources()} to the {@link Tuner}. Tuner would
* handle the resource reclaim on the holder of lower priority and notify the holder of its
* resource loss.
* <li><li>If no frontend can be granted, the API would return false.
* <ul>
*
* <p><strong>Note:</strong> {@link #setFrontendInfoList(TunerFrontendInfo[])} must be called

View File

@@ -22,7 +22,11 @@ package android.media.tv.tunerresourcemanager;
* @hide
*/
parcelable TunerFrontendRequest {
const int DEFAULT_DESIRED_ID = 0xFFFFFFFF;
int clientId;
int frontendType;
}
int desiredId = DEFAULT_DESIRED_ID;
}

View File

@@ -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