diff --git a/Android.bp b/Android.bp index ff6210626eccf..35f97ac572816 100644 --- a/Android.bp +++ b/Android.bp @@ -223,6 +223,9 @@ filegroup { "media/java/**/*.java", "media/java/**/*.aidl", ], + exclude_srcs: [ + ":framework-media-tv-tunerresourcemanager-sources-aidl", + ], path: "media/java", } @@ -630,6 +633,7 @@ java_defaults { // in favor of an API stubs dependency in java_library "framework" below. "mimemap", "av-types-aidl-java", + "tv_tuner_resource_manager_aidl_interface-java", "soundtrigger_middleware-aidl-java", "modules-utils-os", ], diff --git a/media/java/android/media/MediaCas.java b/media/java/android/media/MediaCas.java index 9957975f16926..582a28ee278e2 100644 --- a/media/java/android/media/MediaCas.java +++ b/media/java/android/media/MediaCas.java @@ -716,8 +716,9 @@ public final class MediaCas implements AutoCloseable { context.getSystemService(Context.TV_TUNER_RESOURCE_MGR_SERVICE); if (mTunerResourceManager != null) { int[] clientId = new int[1]; - ResourceClientProfile profile = - new ResourceClientProfile(tvInputServiceSessionId, priorityHint); + ResourceClientProfile profile = new ResourceClientProfile(); + profile.tvInputSessionId = tvInputServiceSessionId; + profile.useCase = priorityHint; mTunerResourceManager.registerClientProfile( profile, context.getMainExecutor(), mResourceListener, clientId); mClientId = clientId[0]; @@ -921,7 +922,9 @@ public final class MediaCas implements AutoCloseable { int[] sessionResourceHandle = new int[1]; sessionResourceHandle[0] = -1; if (mTunerResourceManager != null) { - CasSessionRequest casSessionRequest = new CasSessionRequest(mClientId, mCasSystemId); + CasSessionRequest casSessionRequest = new CasSessionRequest(); + casSessionRequest.clientId = mClientId; + casSessionRequest.casSystemId = mCasSystemId; if (!mTunerResourceManager .requestCasSession(casSessionRequest, sessionResourceHandle)) { throw new MediaCasException.InsufficientResourceException( diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java index 9abd8fc141be4..46b29f5bc90a4 100644 --- a/media/java/android/media/tv/tuner/Tuner.java +++ b/media/java/android/media/tv/tuner/Tuner.java @@ -44,9 +44,9 @@ import android.media.tv.tuner.frontend.FrontendStatus.FrontendStatusType; import android.media.tv.tuner.frontend.OnTuneEventListener; import android.media.tv.tuner.frontend.ScanCallback; import android.media.tv.tunerresourcemanager.ResourceClientProfile; +import android.media.tv.tunerresourcemanager.TunerCiCamRequest; 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; @@ -298,6 +298,8 @@ public class Tuner implements AutoCloseable { private Executor mOnResourceLostListenerExecutor; private Integer mDemuxHandle; + private Integer mFrontendCiCamHandle; + private Integer mFrontendCiCamId; private Map> mDescramblers = new HashMap<>(); private List> mFilters = new ArrayList>(); @@ -343,33 +345,14 @@ public class Tuner implements AutoCloseable { mHandler = createEventHandler(); int[] clientId = new int[1]; - ResourceClientProfile profile = new ResourceClientProfile(tvInputSessionId, useCase); + ResourceClientProfile profile = new ResourceClientProfile(); + profile.tvInputSessionId = tvInputSessionId; + profile.useCase = useCase; mTunerResourceManager.registerClientProfile( profile, new HandlerExecutor(mHandler), mResourceListener, clientId); mClientId = clientId[0]; mUserId = ActivityManager.getCurrentUser(); - - setFrontendInfoList(); - } - - private void setFrontendInfoList() { - List ids = getFrontendIds(); - if (ids == null) { - return; - } - TunerFrontendInfo[] infos = new TunerFrontendInfo[ids.size()]; - for (int i = 0; i < ids.size(); i++) { - int id = ids.get(i); - FrontendInfo frontendInfo = getFrontendInfoById(id); - if (frontendInfo == null) { - continue; - } - TunerFrontendInfo tunerFrontendInfo = new TunerFrontendInfo( - id, frontendInfo.getType(), frontendInfo.getExclusiveGroupId()); - infos[i] = tunerFrontendInfo; - } - mTunerResourceManager.setFrontendInfoList(infos); } /** @@ -489,6 +472,14 @@ public class Tuner implements AutoCloseable { if (mLnb != null) { mLnb.close(); } + if (mFrontendCiCamHandle != null) { + int result = nativeUnlinkCiCam(mFrontendCiCamId); + if (result == RESULT_SUCCESS) { + mTunerResourceManager.releaseCiCam(mFrontendCiCamHandle, mClientId); + mFrontendCiCamId = null; + mFrontendCiCamHandle = null; + } + } synchronized (mDescramblers) { if (!mDescramblers.isEmpty()) { for (Map.Entry> d : mDescramblers.entrySet()) { @@ -804,7 +795,9 @@ public class Tuner implements AutoCloseable { private boolean requestFrontend() { int[] feHandle = new int[1]; - TunerFrontendRequest request = new TunerFrontendRequest(mClientId, mFrontendType); + TunerFrontendRequest request = new TunerFrontendRequest(); + request.clientId = mClientId; + request.frontendType = mFrontendType; boolean granted = mTunerResourceManager.requestFrontend(request, feHandle); if (granted) { mFrontendHandle = feHandle[0]; @@ -935,7 +928,8 @@ public class Tuner implements AutoCloseable { public int connectFrontendToCiCam(int ciCamId) { if (TunerVersionChecker.checkHigherOrEqualVersionTo(TunerVersionChecker.TUNER_VERSION_1_1, "linkFrontendToCiCam")) { - if (checkResource(TunerResourceManager.TUNER_RESOURCE_TYPE_FRONTEND)) { + if (checkResource(TunerResourceManager.TUNER_RESOURCE_TYPE_FRONTEND) + && checkCiCamResource(ciCamId)) { return nativeLinkCiCam(ciCamId); } } @@ -954,7 +948,7 @@ public class Tuner implements AutoCloseable { */ @Result public int disconnectCiCam() { - if (checkResource(TunerResourceManager.TUNER_RESOURCE_TYPE_DEMUX)) { + if (mDemuxHandle != null) { return nativeDisconnectCiCam(); } return RESULT_UNAVAILABLE; @@ -980,8 +974,14 @@ public class Tuner implements AutoCloseable { public int disconnectFrontendToCiCam(int ciCamId) { if (TunerVersionChecker.checkHigherOrEqualVersionTo(TunerVersionChecker.TUNER_VERSION_1_1, "unlinkFrontendToCiCam")) { - if (checkResource(TunerResourceManager.TUNER_RESOURCE_TYPE_FRONTEND)) { - return nativeUnlinkCiCam(ciCamId); + if (mFrontendCiCamHandle != null && mFrontendCiCamId == ciCamId) { + int result = nativeUnlinkCiCam(ciCamId); + if (result == RESULT_SUCCESS) { + mTunerResourceManager.releaseCiCam(mFrontendCiCamHandle, mClientId); + mFrontendCiCamId = null; + mFrontendCiCamHandle = null; + } + return result; } } return RESULT_UNAVAILABLE; @@ -1258,7 +1258,8 @@ public class Tuner implements AutoCloseable { private boolean requestLnb() { int[] lnbHandle = new int[1]; - TunerLnbRequest request = new TunerLnbRequest(mClientId); + TunerLnbRequest request = new TunerLnbRequest(); + request.clientId = mClientId; boolean granted = mTunerResourceManager.requestLnb(request, lnbHandle); if (granted) { mLnbHandle = lnbHandle[0]; @@ -1346,7 +1347,8 @@ public class Tuner implements AutoCloseable { private boolean requestDemux() { int[] demuxHandle = new int[1]; - TunerDemuxRequest request = new TunerDemuxRequest(mClientId); + TunerDemuxRequest request = new TunerDemuxRequest(); + request.clientId = mClientId; boolean granted = mTunerResourceManager.requestDemux(request, demuxHandle); if (granted) { mDemuxHandle = demuxHandle[0]; @@ -1357,7 +1359,8 @@ public class Tuner implements AutoCloseable { private Descrambler requestDescrambler() { int[] descramblerHandle = new int[1]; - TunerDescramblerRequest request = new TunerDescramblerRequest(mClientId); + TunerDescramblerRequest request = new TunerDescramblerRequest(); + request.clientId = mClientId; boolean granted = mTunerResourceManager.requestDescrambler(request, descramblerHandle); if (!granted) { return null; @@ -1375,6 +1378,18 @@ public class Tuner implements AutoCloseable { return descrambler; } + private boolean requestFrontendCiCam(int ciCamId) { + int[] ciCamHandle = new int[1]; + TunerCiCamRequest request = new TunerCiCamRequest(); + request.clientId = mClientId; + request.ciCamId = ciCamId; + boolean granted = mTunerResourceManager.requestCiCam(request, ciCamHandle); + if (granted) { + mFrontendCiCamHandle = ciCamHandle[0]; + } + return granted; + } + private boolean checkResource(int resourceType) { switch (resourceType) { case TunerResourceManager.TUNER_RESOURCE_TYPE_FRONTEND: { @@ -1401,6 +1416,13 @@ public class Tuner implements AutoCloseable { return true; } + private boolean checkCiCamResource(int ciCamId) { + if (mFrontendCiCamHandle == null && !requestFrontendCiCam(ciCamId)) { + return false; + } + return true; + } + /* package */ void releaseLnb() { if (mLnbHandle != null) { // LNB handle can be null if it's opened by name. diff --git a/media/java/android/media/tv/tunerresourcemanager/Android.bp b/media/java/android/media/tv/tunerresourcemanager/Android.bp index c65d25a03813f..02390bb7c31b3 100644 --- a/media/java/android/media/tv/tunerresourcemanager/Android.bp +++ b/media/java/android/media/tv/tunerresourcemanager/Android.bp @@ -1,17 +1,36 @@ filegroup { - name: "framework-media-tv-tunerresourcemanager-sources", + name: "framework-media-tv-tunerresourcemanager-sources-aidl", srcs: [ - "*.java", - "*.aidl", + "aidl/android/media/tv/tunerresourcemanager/CasSessionRequest.aidl", + "aidl/android/media/tv/tunerresourcemanager/IResourcesReclaimListener.aidl", + "aidl/android/media/tv/tunerresourcemanager/ResourceClientProfile.aidl", + "aidl/android/media/tv/tunerresourcemanager/TunerCiCamRequest.aidl", + "aidl/android/media/tv/tunerresourcemanager/TunerDemuxRequest.aidl", + "aidl/android/media/tv/tunerresourcemanager/TunerDescramblerRequest.aidl", + "aidl/android/media/tv/tunerresourcemanager/TunerFrontendInfo.aidl", + "aidl/android/media/tv/tunerresourcemanager/TunerFrontendRequest.aidl", + "aidl/android/media/tv/tunerresourcemanager/TunerLnbRequest.aidl", + "aidl/android/media/tv/tunerresourcemanager/ITunerResourceManager.aidl", ], - path: ".", + path: "aidl", } -java_library { - name: "framework-media-tv-trm-sources", - srcs: [":framework-media-tv-tunerresourcemanager-sources"], - installable: true, - visibility: [ - "//frameworks/base", +aidl_interface { + name: "tv_tuner_resource_manager_aidl_interface", + unstable: true, + local_include_dir: "aidl", + backend: { + java: { + sdk_version: "current", + }, + cpp: { + enabled: true, + }, + ndk: { + enabled: true, + }, + }, + srcs: [ + ":framework-media-tv-tunerresourcemanager-sources-aidl", ], -} \ No newline at end of file +} diff --git a/media/java/android/media/tv/tunerresourcemanager/CasSessionRequest.java b/media/java/android/media/tv/tunerresourcemanager/CasSessionRequest.java deleted file mode 100644 index 59802ff8c3f8e..0000000000000 --- a/media/java/android/media/tv/tunerresourcemanager/CasSessionRequest.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * 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 android.media.tv.tunerresourcemanager; - -import android.annotation.NonNull; -import android.os.Parcel; -import android.os.Parcelable; -import android.util.Log; - -/** - * Information required to request a Cas Session. - * - * @hide - */ -public final class CasSessionRequest implements Parcelable { - static final String TAG = "CasSessionRequest"; - - public static final - @NonNull - Parcelable.Creator CREATOR = - new Parcelable.Creator() { - @Override - public CasSessionRequest createFromParcel(Parcel source) { - try { - return new CasSessionRequest(source); - } catch (Exception e) { - Log.e(TAG, "Exception creating CasSessionRequest from parcel", e); - return null; - } - } - - @Override - public CasSessionRequest[] newArray(int size) { - return new CasSessionRequest[size]; - } - }; - - /** - * Client id of the client that sends the request. - */ - private final int mClientId; - - /** - * System id of the requested cas. - */ - private final int mCasSystemId; - - private CasSessionRequest(@NonNull Parcel source) { - mClientId = source.readInt(); - mCasSystemId = source.readInt(); - } - - /** - * Constructs a new {@link CasSessionRequest} with the given parameters. - * - * @param clientId id of the client. - * @param casSystemId the cas system id that the client is requesting. - */ - public CasSessionRequest(int clientId, - int casSystemId) { - mClientId = clientId; - mCasSystemId = casSystemId; - } - - /** - * Returns the id of the client. - */ - public int getClientId() { - return mClientId; - } - - /** - * Returns the cas system id requested. - */ - public int getCasSystemId() { - return mCasSystemId; - } - - // Parcelable - @Override - public int describeContents() { - return 0; - } - - @NonNull - @Override - public String toString() { - StringBuilder b = new StringBuilder(128); - b.append("CasSessionRequest {clientId=").append(mClientId); - b.append(", casSystemId=").append(mCasSystemId); - b.append("}"); - return b.toString(); - } - - @Override - public void writeToParcel(@NonNull Parcel dest, int flags) { - dest.writeInt(mClientId); - dest.writeInt(mCasSystemId); - } -} diff --git a/media/java/android/media/tv/tunerresourcemanager/ResourceClientProfile.java b/media/java/android/media/tv/tunerresourcemanager/ResourceClientProfile.java deleted file mode 100644 index 28f1ac916690b..0000000000000 --- a/media/java/android/media/tv/tunerresourcemanager/ResourceClientProfile.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * 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 android.media.tv.tunerresourcemanager; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.os.Parcel; -import android.os.Parcelable; -import android.util.Log; - -/** - * A profile of a resource client. This profile is used to register the client info - * with the Tuner Resource Manager(TRM). - * - * @hide - */ -public final class ResourceClientProfile implements Parcelable { - static final String TAG = "ResourceClientProfile"; - - public static final - @NonNull - Parcelable.Creator CREATOR = - new Parcelable.Creator() { - @Override - public ResourceClientProfile createFromParcel(Parcel source) { - try { - return new ResourceClientProfile(source); - } catch (Exception e) { - Log.e(TAG, "Exception creating ResourceClientProfile from parcel", e); - return null; - } - } - - @Override - public ResourceClientProfile[] newArray(int size) { - return new ResourceClientProfile[size]; - } - }; - - /** - * This is used by TRM to get TV App’s processId from TIF. - * The processId will be used to identify foreground applications. - * - *

MediaCas, Tuner and TvInputHardwareManager get tvInputSessionId from TIS. - * If mTvInputSessionId is UNKNOWN, the client is always background. - */ - private final String mTvInputSessionId; - - /** - * Usage of the client. - */ - private final int mUseCase; - - private ResourceClientProfile(@NonNull Parcel source) { - mTvInputSessionId = source.readString(); - mUseCase = source.readInt(); - } - - /** - * Constructs a new {@link ResourceClientProfile} with the given parameters. - * - * @param tvInputSessionId the unique id of the session owned by the client. - * @param useCase the usage of the client. Suggested priority hints are - * {@link android.media.tv.TvInputService.PRIORITY_HINT_USE_CASE_TYPE_PLAYBACK} - * {@link android.media.tv.TvInputService.PRIORITY_HINT_USE_CASE_TYPE_LIVE} - * {@link android.media.tv.TvInputService.PRIORITY_HINT_USE_CASE_TYPE_RECORD}. - * New [use case : priority value] pair can be defined in the manifest by the - * OEM. The id of the useCaseVendor should be passed through this parameter. Any - * undefined use case would cause IllegalArgumentException. - */ - public ResourceClientProfile(@Nullable String tvInputSessionId, - int useCase) { - mTvInputSessionId = tvInputSessionId; - mUseCase = useCase; - } - - /** - * Returns the tv input session id of the client. - * - * @return the value of the tv input session id. - */ - @Nullable - public String getTvInputSessionId() { - return mTvInputSessionId; - } - - /** - * Returns the user usage of the client. - * - * @return the value of use case. - */ - public int getUseCase() { - return mUseCase; - } - - // Parcelable - @Override - public int describeContents() { - return 0; - } - - @NonNull - @Override - public String toString() { - StringBuilder b = new StringBuilder(128); - b.append("ResourceClientProfile {tvInputSessionId=").append(mTvInputSessionId); - b.append(", useCase=").append(mUseCase); - b.append("}"); - return b.toString(); - } - - @Override - public void writeToParcel(@NonNull Parcel dest, int flags) { - dest.writeString(mTvInputSessionId); - dest.writeInt(mUseCase); - } -} diff --git a/media/java/android/media/tv/tunerresourcemanager/TunerDemuxRequest.java b/media/java/android/media/tv/tunerresourcemanager/TunerDemuxRequest.java deleted file mode 100644 index 34a77616f62e2..0000000000000 --- a/media/java/android/media/tv/tunerresourcemanager/TunerDemuxRequest.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * 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 android.media.tv.tunerresourcemanager; - -import android.annotation.NonNull; -import android.os.Parcel; -import android.os.Parcelable; -import android.util.Log; - -/** - * Information required to request a Tuner Demux. - * - * @hide - */ -public final class TunerDemuxRequest implements Parcelable { - static final String TAG = "TunerDemuxRequest"; - - public static final - @NonNull - Parcelable.Creator CREATOR = - new Parcelable.Creator() { - @Override - public TunerDemuxRequest createFromParcel(Parcel source) { - try { - return new TunerDemuxRequest(source); - } catch (Exception e) { - Log.e(TAG, "Exception creating TunerDemuxRequest from parcel", e); - return null; - } - } - - @Override - public TunerDemuxRequest[] newArray(int size) { - return new TunerDemuxRequest[size]; - } - }; - - /** - * Client id of the client that sends the request. - */ - private final int mClientId; - - private TunerDemuxRequest(@NonNull Parcel source) { - mClientId = source.readInt(); - } - - /** - * Constructs a new {@link TunerDemuxRequest} with the given parameters. - * - * @param clientId id of the client. - */ - public TunerDemuxRequest(int clientId) { - mClientId = clientId; - } - - /** - * Returns the id of the client. - */ - public int getClientId() { - return mClientId; - } - - // Parcelable - @Override - public int describeContents() { - return 0; - } - - @NonNull - @Override - public String toString() { - StringBuilder b = new StringBuilder(128); - b.append("TunerDemuxRequest {clientId=").append(mClientId); - b.append("}"); - return b.toString(); - } - - @Override - public void writeToParcel(@NonNull Parcel dest, int flags) { - dest.writeInt(mClientId); - } -} diff --git a/media/java/android/media/tv/tunerresourcemanager/TunerDescramblerRequest.java b/media/java/android/media/tv/tunerresourcemanager/TunerDescramblerRequest.java deleted file mode 100644 index 58162879f8cfe..0000000000000 --- a/media/java/android/media/tv/tunerresourcemanager/TunerDescramblerRequest.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * 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 android.media.tv.tunerresourcemanager; - -import android.annotation.NonNull; -import android.os.Parcel; -import android.os.Parcelable; -import android.util.Log; - -/** - * Information required to request a Tuner Descrambler. - * - * @hide - */ -public final class TunerDescramblerRequest implements Parcelable { - static final String TAG = "TunerDescramblerRequest"; - - public static final - @NonNull - Parcelable.Creator CREATOR = - new Parcelable.Creator() { - @Override - public TunerDescramblerRequest createFromParcel(Parcel source) { - try { - return new TunerDescramblerRequest(source); - } catch (Exception e) { - Log.e(TAG, "Exception creating TunerDescramblerRequest from parcel", e); - return null; - } - } - - @Override - public TunerDescramblerRequest[] newArray(int size) { - return new TunerDescramblerRequest[size]; - } - }; - - /** - * Client id of the client that sends the request. - */ - private final int mClientId; - - private TunerDescramblerRequest(@NonNull Parcel source) { - mClientId = source.readInt(); - } - - /** - * Constructs a new {@link TunerDescramblerRequest} with the given parameters. - * - * @param clientId id of the client. - */ - public TunerDescramblerRequest(int clientId) { - mClientId = clientId; - } - - /** - * Returns the id of the client. - */ - public int getClientId() { - return mClientId; - } - - // Parcelable - @Override - public int describeContents() { - return 0; - } - - @NonNull - @Override - public String toString() { - StringBuilder b = new StringBuilder(128); - b.append("TunerDescramblerRequest {clientId=").append(mClientId); - b.append("}"); - return b.toString(); - } - - @Override - public void writeToParcel(@NonNull Parcel dest, int flags) { - dest.writeInt(mClientId); - } -} diff --git a/media/java/android/media/tv/tunerresourcemanager/TunerFrontendInfo.java b/media/java/android/media/tv/tunerresourcemanager/TunerFrontendInfo.java deleted file mode 100644 index ef50aacf43b5d..0000000000000 --- a/media/java/android/media/tv/tunerresourcemanager/TunerFrontendInfo.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * 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 android.media.tv.tunerresourcemanager; - -import android.annotation.NonNull; -import android.media.tv.tuner.frontend.FrontendSettings.Type; -import android.os.Parcel; -import android.os.Parcelable; -import android.util.Log; - -/** - * Simple container of the FrontendInfo struct defined in the TunerHAL 1.0 interface. - * - *

Note that this object is defined to pass necessary frontend info between the - * Tuner Resource Manager and the client. It includes partial information in - * {@link FrontendInfo}. - * - * @hide - */ -public final class TunerFrontendInfo implements Parcelable { - static final String TAG = "TunerFrontendInfo"; - - public static final - @NonNull - Parcelable.Creator CREATOR = - new Parcelable.Creator() { - @Override - public TunerFrontendInfo createFromParcel(Parcel source) { - try { - return new TunerFrontendInfo(source); - } catch (Exception e) { - Log.e(TAG, "Exception creating TunerFrontendInfo from parcel", e); - return null; - } - } - - @Override - public TunerFrontendInfo[] newArray(int size) { - return new TunerFrontendInfo[size]; - } - }; - - private final int mHandle; - - @Type - private final int mFrontendType; - - /** - * Frontends are assigned with the same exclusiveGroupId if they can't - * function at same time. For instance, they share same hardware module. - */ - private final int mExclusiveGroupId; - - private TunerFrontendInfo(@NonNull Parcel source) { - mHandle = source.readInt(); - mFrontendType = source.readInt(); - mExclusiveGroupId = source.readInt(); - } - - /** - * Constructs a new {@link TunerFrontendInfo} with the given parameters. - * - * @param handle frontend handle - * @param frontendType the type of the frontend. - * @param exclusiveGroupId the group id of the frontend. FE with the same - group id can't function at the same time. - */ - public TunerFrontendInfo(int handle, - @Type int frontendType, - int exclusiveGroupId) { - mHandle = handle; - mFrontendType = frontendType; - mExclusiveGroupId = exclusiveGroupId; - } - - /** - * Returns the frontend handle. - * - * @return the value of the frontend handle. - */ - public int getHandle() { - return mHandle; - } - - /** - * Returns the application id that requests the tuner frontend resource. - * - * @return the value of the frontend type. - */ - @Type - public int getFrontendType() { - return mFrontendType; - } - - /** - * Returns the exclusiveGroupId. Frontends with the same exclusiveGroupId - * can't function at same time. - * - * @return the value of the exclusive group id. - */ - public int getExclusiveGroupId() { - return mExclusiveGroupId; - } - - // Parcelable - @Override - public int describeContents() { - return 0; - } - - @NonNull - @Override - public String toString() { - StringBuilder b = new StringBuilder(128); - b.append("TunerFrontendInfo {handle=").append(mHandle); - b.append(", frontendType=").append(mFrontendType); - b.append(", exclusiveGroupId=").append(mExclusiveGroupId); - b.append("}"); - return b.toString(); - } - - @Override - public void writeToParcel(@NonNull Parcel dest, int flags) { - dest.writeInt(mHandle); - dest.writeInt(mFrontendType); - dest.writeInt(mExclusiveGroupId); - } -} diff --git a/media/java/android/media/tv/tunerresourcemanager/TunerFrontendRequest.java b/media/java/android/media/tv/tunerresourcemanager/TunerFrontendRequest.java deleted file mode 100644 index 12f8032ab99bd..0000000000000 --- a/media/java/android/media/tv/tunerresourcemanager/TunerFrontendRequest.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * 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 android.media.tv.tunerresourcemanager; - -import android.annotation.NonNull; -import android.media.tv.tuner.frontend.FrontendSettings.Type; -import android.os.Parcel; -import android.os.Parcelable; -import android.util.Log; - -/** - * Information required to request a Tuner Frontend. - * - * @hide - */ -public final class TunerFrontendRequest implements Parcelable { - static final String TAG = "TunerFrontendRequest"; - - public static final - @NonNull - Parcelable.Creator CREATOR = - new Parcelable.Creator() { - @Override - public TunerFrontendRequest createFromParcel(Parcel source) { - try { - return new TunerFrontendRequest(source); - } catch (Exception e) { - Log.e(TAG, "Exception creating TunerFrontendRequest from parcel", e); - return null; - } - } - - @Override - public TunerFrontendRequest[] newArray(int size) { - return new TunerFrontendRequest[size]; - } - }; - - private final int mClientId; - @Type - private final int mFrontendType; - - private TunerFrontendRequest(@NonNull Parcel source) { - mClientId = source.readInt(); - mFrontendType = source.readInt(); - } - - /** - * Constructs a new {@link TunerFrontendRequest} with the given parameters. - * - * @param clientId the unique id of the client returned when registering profile. - * @param frontendType the type of the requested frontend. - */ - public TunerFrontendRequest(int clientId, - @Type int frontendType) { - mClientId = clientId; - mFrontendType = frontendType; - } - - /** - * Returns the client id that requests the tuner frontend resource. - * - * @return the value of the client id. - */ - public int getClientId() { - return mClientId; - } - - /** - * Returns the frontend type that the client requests for. - * - * @return the value of the requested frontend type. - */ - @Type - public int getFrontendType() { - return mFrontendType; - } - - // Parcelable - @Override - public int describeContents() { - return 0; - } - - @NonNull - @Override - public String toString() { - StringBuilder b = new StringBuilder(128); - b.append("TunerFrontendRequest {clientId=").append(mClientId); - b.append(", frontendType=").append(mFrontendType); - b.append("}"); - return b.toString(); - } - - @Override - public void writeToParcel(@NonNull Parcel dest, int flags) { - dest.writeInt(mClientId); - dest.writeInt(mFrontendType); - } -} diff --git a/media/java/android/media/tv/tunerresourcemanager/TunerLnbRequest.java b/media/java/android/media/tv/tunerresourcemanager/TunerLnbRequest.java deleted file mode 100644 index 5ed7f3f546f4a..0000000000000 --- a/media/java/android/media/tv/tunerresourcemanager/TunerLnbRequest.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * 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 android.media.tv.tunerresourcemanager; - -import android.annotation.NonNull; -import android.os.Parcel; -import android.os.Parcelable; -import android.util.Log; - -/** - * Information required to request a Tuner Lnb. - * - * @hide - */ -public final class TunerLnbRequest implements Parcelable { - static final String TAG = "TunerLnbRequest"; - - public static final - @NonNull - Parcelable.Creator CREATOR = - new Parcelable.Creator() { - @Override - public TunerLnbRequest createFromParcel(Parcel source) { - try { - return new TunerLnbRequest(source); - } catch (Exception e) { - Log.e(TAG, "Exception creating TunerLnbRequest from parcel", e); - return null; - } - } - - @Override - public TunerLnbRequest[] newArray(int size) { - return new TunerLnbRequest[size]; - } - }; - - /** - * Client id of the client that sends the request. - */ - private final int mClientId; - - private TunerLnbRequest(@NonNull Parcel source) { - mClientId = source.readInt(); - } - - /** - * Constructs a new {@link TunerLnbRequest} with the given parameters. - * - * @param clientId the id of the client. - */ - public TunerLnbRequest(int clientId) { - mClientId = clientId; - } - - /** - * Returns the id of the client - */ - public int getClientId() { - return mClientId; - } - - // Parcelable - @Override - public int describeContents() { - return 0; - } - - @NonNull - @Override - public String toString() { - StringBuilder b = new StringBuilder(128); - b.append("TunerLnbRequest {clientId=").append(mClientId); - b.append("}"); - return b.toString(); - } - - @Override - public void writeToParcel(@NonNull Parcel dest, int flags) { - dest.writeInt(mClientId); - } -} diff --git a/media/java/android/media/tv/tunerresourcemanager/TunerResourceManager.java b/media/java/android/media/tv/tunerresourcemanager/TunerResourceManager.java index be102d8acc10b..6f7adbc653182 100644 --- a/media/java/android/media/tv/tunerresourcemanager/TunerResourceManager.java +++ b/media/java/android/media/tv/tunerresourcemanager/TunerResourceManager.java @@ -74,6 +74,7 @@ public class TunerResourceManager { TUNER_RESOURCE_TYPE_DESCRAMBLER, TUNER_RESOURCE_TYPE_LNB, TUNER_RESOURCE_TYPE_CAS_SESSION, + TUNER_RESOURCE_TYPE_FRONTEND_CICAM, TUNER_RESOURCE_TYPE_MAX, }) @Retention(RetentionPolicy.SOURCE) @@ -84,7 +85,8 @@ 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; + public static final int TUNER_RESOURCE_TYPE_FRONTEND_CICAM = 5; + public static final int TUNER_RESOURCE_TYPE_MAX = 6; private final ITunerResourceManager mService; private final int mUserId; @@ -378,6 +380,38 @@ public class TunerResourceManager { return result; } + /** + * Requests a CiCam resource. + * + *

There are three possible scenarios: + *

    + *
  • If there is CiCam available, the API would send the id back. + * + *
  • If no CiCam is available but the current request info can show higher priority than + * other uses of the CiCam, 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. + * + *

    Note: {@link #updateCasInfo(int, int)} must be called before this + * request. + * + * @param request {@link TunerCiCamRequest} information of the current request. + * @param ciCamHandle a one-element array to return the granted ciCam handle. + * If no ciCam granted, this will return {@link #INVALID_RESOURCE_HANDLE}. + * + * @return true if there is ciCam granted. + */ + public boolean requestCiCam(TunerCiCamRequest request, int[] ciCamHandle) { + boolean result = false; + try { + result = mService.requestCiCam(request, ciCamHandle); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + return result; + } + /** * Requests a Tuner Lnb resource. * @@ -481,6 +515,25 @@ public class TunerResourceManager { } } + /** + * Notifies the TRM that the given CiCam has been released. + * + *

    Client must call this whenever it releases a CiCam. + * + *

    Note: {@link #updateCasInfo(int, int)} must be called before this + * release. + * + * @param ciCamHandle the handle of the releasing CiCam. + * @param clientId the id of the client that is releasing the CiCam. + */ + public void releaseCiCam(int ciCamHandle, int clientId) { + try { + mService.releaseCiCam(ciCamHandle, clientId); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + /** * Notifies the TRM that the Lnb with the given id has been released. * diff --git a/media/java/android/media/tv/tunerresourcemanager/CasSessionRequest.aidl b/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/CasSessionRequest.aidl similarity index 91% rename from media/java/android/media/tv/tunerresourcemanager/CasSessionRequest.aidl rename to media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/CasSessionRequest.aidl index c918d88b479ae..88f591551e8af 100644 --- a/media/java/android/media/tv/tunerresourcemanager/CasSessionRequest.aidl +++ b/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/CasSessionRequest.aidl @@ -21,4 +21,8 @@ package android.media.tv.tunerresourcemanager; * * @hide */ -parcelable CasSessionRequest; \ No newline at end of file +parcelable CasSessionRequest { + int clientId; + + int casSystemId; +} \ No newline at end of file diff --git a/media/java/android/media/tv/tunerresourcemanager/IResourcesReclaimListener.aidl b/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/IResourcesReclaimListener.aidl similarity index 100% rename from media/java/android/media/tv/tunerresourcemanager/IResourcesReclaimListener.aidl rename to media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/IResourcesReclaimListener.aidl diff --git a/media/java/android/media/tv/tunerresourcemanager/ITunerResourceManager.aidl b/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/ITunerResourceManager.aidl similarity index 89% rename from media/java/android/media/tv/tunerresourcemanager/ITunerResourceManager.aidl rename to media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/ITunerResourceManager.aidl index 487b444eb627b..a1f6687a1b81d 100644 --- a/media/java/android/media/tv/tunerresourcemanager/ITunerResourceManager.aidl +++ b/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/ITunerResourceManager.aidl @@ -19,6 +19,7 @@ package android.media.tv.tunerresourcemanager; import android.media.tv.tunerresourcemanager.CasSessionRequest; import android.media.tv.tunerresourcemanager.IResourcesReclaimListener; import android.media.tv.tunerresourcemanager.ResourceClientProfile; +import android.media.tv.tunerresourcemanager.TunerCiCamRequest; import android.media.tv.tunerresourcemanager.TunerDemuxRequest; import android.media.tv.tunerresourcemanager.TunerDescramblerRequest; import android.media.tv.tunerresourcemanager.TunerFrontendInfo; @@ -224,6 +225,31 @@ interface ITunerResourceManager { */ boolean requestCasSession(in CasSessionRequest request, out int[] casSessionHandle); + /* + * This API is used by the Tuner framework to request an available CuCam. + * + *

    There are three possible scenarios: + *

      + *
    • If there is CiCam available, the API would send the handle back. + * + *
    • If no CiCma is available but the current request info can show higher priority than + * other uses of the ciCam, the API will send + * {@link ITunerResourceManagerCallback#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. + * + *
    • If no CiCam can be granted, the API would return false. + *
        + * + *

        Note: {@link #updateCasInfo(int, int)} must be called before this request. + * + * @param request {@link TunerCiCamRequest} information of the current request. + * @param ciCamHandle a one-element array to return the granted ciCam handle. + * + * @return true if there is CiCam granted. + */ + boolean requestCiCam(in TunerCiCamRequest request, out int[] ciCamHandle); + /* * This API is used by the Tuner framework to request an available Lnb from the TunerHAL. * @@ -293,6 +319,19 @@ interface ITunerResourceManager { */ void releaseCasSession(in int casSessionHandle, int clientId); + /** + * Notifies the TRM that the given CiCam has been released. + * + *

        Client must call this whenever it releases a CiCam. + * + *

        Note: {@link #updateCasInfo(int, int)} must be called before this + * release. + * + * @param ciCamHandle the handle of the releasing CiCam. + * @param clientId the id of the client that is releasing the CiCam. + */ + void releaseCiCam(in int ciCamHandle, int clientId); + /* * Notifies the TRM that the Lnb with the given handle was released. * diff --git a/media/java/android/media/tv/tunerresourcemanager/ResourceClientProfile.aidl b/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/ResourceClientProfile.aidl similarity index 90% rename from media/java/android/media/tv/tunerresourcemanager/ResourceClientProfile.aidl rename to media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/ResourceClientProfile.aidl index ed90c1dc39969..08c2bb85c0c43 100644 --- a/media/java/android/media/tv/tunerresourcemanager/ResourceClientProfile.aidl +++ b/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/ResourceClientProfile.aidl @@ -22,4 +22,8 @@ package android.media.tv.tunerresourcemanager; * * @hide */ -parcelable ResourceClientProfile; \ No newline at end of file +parcelable ResourceClientProfile { + String tvInputSessionId; + + int useCase; +} \ No newline at end of file diff --git a/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/TunerCiCamRequest.aidl b/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/TunerCiCamRequest.aidl new file mode 100644 index 0000000000000..76f9f83ead82b --- /dev/null +++ b/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/TunerCiCamRequest.aidl @@ -0,0 +1,28 @@ +/* + * 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 android.media.tv.tunerresourcemanager; + +/** + * A wrapper of a ciCam requests that contains all the request info of the client. + * + * @hide + */ +parcelable TunerCiCamRequest { + int clientId; + + int ciCamId; +} \ No newline at end of file diff --git a/media/java/android/media/tv/tunerresourcemanager/TunerDemuxRequest.aidl b/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/TunerDemuxRequest.aidl similarity index 93% rename from media/java/android/media/tv/tunerresourcemanager/TunerDemuxRequest.aidl rename to media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/TunerDemuxRequest.aidl index 919a215a9ce59..457f90ce866d3 100644 --- a/media/java/android/media/tv/tunerresourcemanager/TunerDemuxRequest.aidl +++ b/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/TunerDemuxRequest.aidl @@ -21,4 +21,6 @@ package android.media.tv.tunerresourcemanager; * * @hide */ -parcelable TunerDemuxRequest; \ No newline at end of file +parcelable TunerDemuxRequest { + int clientId; +} \ No newline at end of file diff --git a/media/java/android/media/tv/tunerresourcemanager/TunerDescramblerRequest.aidl b/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/TunerDescramblerRequest.aidl similarity index 92% rename from media/java/android/media/tv/tunerresourcemanager/TunerDescramblerRequest.aidl rename to media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/TunerDescramblerRequest.aidl index fbafb3bc010e5..98ab7301bac95 100644 --- a/media/java/android/media/tv/tunerresourcemanager/TunerDescramblerRequest.aidl +++ b/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/TunerDescramblerRequest.aidl @@ -21,4 +21,6 @@ package android.media.tv.tunerresourcemanager; * * @hide */ -parcelable TunerDescramblerRequest; \ No newline at end of file +parcelable TunerDescramblerRequest { + int clientId; +} \ No newline at end of file diff --git a/media/java/android/media/tv/tunerresourcemanager/TunerFrontendInfo.aidl b/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/TunerFrontendInfo.aidl similarity index 88% rename from media/java/android/media/tv/tunerresourcemanager/TunerFrontendInfo.aidl rename to media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/TunerFrontendInfo.aidl index e649c2aa3fd6b..edf96ddd4e5a2 100644 --- a/media/java/android/media/tv/tunerresourcemanager/TunerFrontendInfo.aidl +++ b/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/TunerFrontendInfo.aidl @@ -21,4 +21,10 @@ package android.media.tv.tunerresourcemanager; * * @hide */ -parcelable TunerFrontendInfo; \ No newline at end of file +parcelable TunerFrontendInfo { + int handle; + + int frontendType; + + int exclusiveGroupId; +} diff --git a/media/java/android/media/tv/tunerresourcemanager/TunerFrontendRequest.aidl b/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/TunerFrontendRequest.aidl similarity index 90% rename from media/java/android/media/tv/tunerresourcemanager/TunerFrontendRequest.aidl rename to media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/TunerFrontendRequest.aidl index 5e48adc075b86..4d98222158421 100644 --- a/media/java/android/media/tv/tunerresourcemanager/TunerFrontendRequest.aidl +++ b/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/TunerFrontendRequest.aidl @@ -21,4 +21,8 @@ package android.media.tv.tunerresourcemanager; * * @hide */ -parcelable TunerFrontendRequest; \ No newline at end of file +parcelable TunerFrontendRequest { + int clientId; + + int frontendType; +} \ No newline at end of file diff --git a/media/java/android/media/tv/tunerresourcemanager/TunerLnbRequest.aidl b/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/TunerLnbRequest.aidl similarity index 93% rename from media/java/android/media/tv/tunerresourcemanager/TunerLnbRequest.aidl rename to media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/TunerLnbRequest.aidl index 0e6fcde516423..1a059ea632f27 100644 --- a/media/java/android/media/tv/tunerresourcemanager/TunerLnbRequest.aidl +++ b/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/TunerLnbRequest.aidl @@ -21,4 +21,6 @@ package android.media.tv.tunerresourcemanager; * * @hide */ -parcelable TunerLnbRequest; \ No newline at end of file +parcelable TunerLnbRequest { + int clientId; +} \ No newline at end of file diff --git a/media/jni/Android.bp b/media/jni/Android.bp index f80f41219e344..decf68f26c0e2 100644 --- a/media/jni/Android.bp +++ b/media/jni/Android.bp @@ -137,6 +137,7 @@ cc_library_shared { cc_library_shared { name: "libmedia_tv_tuner", + srcs: [ "android_media_tv_Tuner.cpp", "tuner/DemuxClient.cpp", @@ -163,6 +164,7 @@ cc_library_shared { "libnativehelper", "libutils", "tv_tuner_aidl_interface-ndk_platform", + "tv_tuner_resource_manager_aidl_interface-ndk_platform" ], defaults: [ "libcodec2-impl-defaults", diff --git a/media/jni/tuner/TunerClient.cpp b/media/jni/tuner/TunerClient.cpp index b14e902d549c1..39e6ba27e56f2 100644 --- a/media/jni/tuner/TunerClient.cpp +++ b/media/jni/tuner/TunerClient.cpp @@ -25,6 +25,8 @@ using ::android::hardware::tv::tuner::V1_0::FrontendId; using ::android::hardware::tv::tuner::V1_0::FrontendType; +using ::aidl::android::media::tv::tunerresourcemanager::TunerFrontendInfo; + namespace android { sp TunerClient::mTuner; @@ -37,6 +39,7 @@ int TunerClient::mTunerVersion; TunerClient::TunerClient() { // Get HIDL Tuner in migration stage. getHidlTuner(); + updateTunerResources(); // Connect with Tuner Service. ::ndk::SpAIBinder binder(AServiceManager_getService("media.tuner")); mTunerService = ITunerService::fromBinder(binder); @@ -259,6 +262,49 @@ sp TunerClient::openLnbByName(string lnbName) { /////////////// TunerClient Helper Methods /////////////////////// +void TunerClient::updateTunerResources() { + if (mTuner == NULL) { + return; + } + + // Connect with Tuner Resource Manager. + ::ndk::SpAIBinder binder(AServiceManager_getService("tv_tuner_resource_mgr")); + mTunerResourceManager = ITunerResourceManager::fromBinder(binder); + + updateFrontendResources(); + updateLnbResources(); + // TODO: update Demux, Descrambler. +} + +void TunerClient::updateFrontendResources() { + vector ids = getFrontendIds(); + if (ids.size() == 0) { + return; + } + vector infos; + for (int i = 0; i < ids.size(); i++) { + shared_ptr frontendInfo = getFrontendInfo((int)ids[i]); + if (frontendInfo == NULL) { + continue; + } + TunerFrontendInfo tunerFrontendInfo{ + .handle = getResourceHandleFromId((int)ids[i], FRONTEND), + .frontendType = static_cast(frontendInfo->type), + .exclusiveGroupId = static_cast(frontendInfo->exclusiveGroupId), + }; + infos.push_back(tunerFrontendInfo); + } + mTunerResourceManager->setFrontendInfoList(infos); +} + +void TunerClient::updateLnbResources() { + vector handles = getLnbHandles(); + if (handles.size() == 0) { + return; + } + mTunerResourceManager->setLnbInfoList(handles); +} + sp TunerClient::getHidlTuner() { if (mTuner == NULL) { mTunerVersion = 0; @@ -366,6 +412,32 @@ sp TunerClient::openHidlDescrambler() { return descrambler; } +vector TunerClient::getLnbHandles() { + vector lnbHandles; + + if (mTunerService != NULL) { + // TODO: pending hidl interface + } + + if (mTuner != NULL) { + Result res; + vector lnbIds; + mTuner->getLnbIds([&](Result r, const hardware::hidl_vec& ids) { + lnbIds = ids; + res = r; + }); + if (res != Result::SUCCESS || lnbIds.size() == 0) { + ALOGW("Lnb isn't available"); + } else { + for (int i = 0; i < lnbIds.size(); i++) { + lnbHandles.push_back(getResourceHandleFromId((int)lnbIds[i], LNB)); + } + } + } + + return lnbHandles; +} + FrontendInfo TunerClient::FrontendInfoAidlToHidl(TunerServiceFrontendInfo aidlFrontendInfo) { FrontendInfo hidlFrontendInfo { .type = static_cast(aidlFrontendInfo.type), diff --git a/media/jni/tuner/TunerClient.h b/media/jni/tuner/TunerClient.h index 94fdf274ef166..a3d2d02c7ef6d 100644 --- a/media/jni/tuner/TunerClient.h +++ b/media/jni/tuner/TunerClient.h @@ -17,6 +17,8 @@ #ifndef _ANDROID_MEDIA_TV_TUNER_CLIENT_H_ #define _ANDROID_MEDIA_TV_TUNER_CLIENT_H_ +#include +#include #include #include #include @@ -28,10 +30,12 @@ using ::aidl::android::media::tv::tuner::ITunerService; using ::aidl::android::media::tv::tuner::TunerServiceFrontendInfo; +using ::aidl::android::media::tv::tunerresourcemanager::ITunerResourceManager; using ::android::hardware::tv::tuner::V1_0::DemuxCapabilities; using ::android::hardware::tv::tuner::V1_0::FrontendId; using ::android::hardware::tv::tuner::V1_0::ITuner; +using ::android::hardware::tv::tuner::V1_0::LnbId; using ::android::hardware::tv::tuner::V1_0::Result; using ::android::hardware::tv::tuner::V1_1::FrontendDtmbCapabilities; @@ -136,13 +140,16 @@ private: sp openHidlLnbById(int id); sp openHidlLnbByName(string name, LnbId& lnbId); sp openHidlDescrambler(); + vector getLnbHandles(); FrontendInfo FrontendInfoAidlToHidl(TunerServiceFrontendInfo aidlFrontendInfo); + void updateTunerResources(); + void updateFrontendResources(); + void updateLnbResources(); int getResourceIdFromHandle(int handle, int resourceType); int getResourceHandleFromId(int id, int resourceType); -private: /** * An AIDL Tuner Service Singleton assigned at the first time the Tuner Client * connects with the Tuner Service. Default null when the service does not exist. @@ -167,6 +174,8 @@ private: // while the low 16 bits are the minor version. Default value is unknown version 0. static int mTunerVersion; + shared_ptr mTunerResourceManager; + int mResourceRequestCount = 0; }; } // namespace android diff --git a/services/core/java/com/android/server/tv/TvInputHardwareManager.java b/services/core/java/com/android/server/tv/TvInputHardwareManager.java index 2314afc787c37..a036bd196b23e 100755 --- a/services/core/java/com/android/server/tv/TvInputHardwareManager.java +++ b/services/core/java/com/android/server/tv/TvInputHardwareManager.java @@ -380,8 +380,9 @@ class TvInputHardwareManager implements TvInputHal.Callback { return null; } - ResourceClientProfile profile = - new ResourceClientProfile(tvInputSessionId, priorityHint); + ResourceClientProfile profile = new ResourceClientProfile(); + profile.tvInputSessionId = tvInputSessionId; + profile.useCase = priorityHint; ResourceClientProfile holderProfile = connection.getResourceClientProfileLocked(); if (holderProfile != null && trm != null && !trm.isHigherPriority(profile, holderProfile)) { diff --git a/services/core/java/com/android/server/tv/tunerresourcemanager/CasResource.java b/services/core/java/com/android/server/tv/tunerresourcemanager/CasResource.java index 54ad1d268e560..4a81c95f0b8fa 100644 --- a/services/core/java/com/android/server/tv/tunerresourcemanager/CasResource.java +++ b/services/core/java/com/android/server/tv/tunerresourcemanager/CasResource.java @@ -25,7 +25,7 @@ import java.util.Set; * * @hide */ -public final class CasResource { +public class CasResource { private final int mSystemId; @@ -38,7 +38,7 @@ public final class CasResource { */ private Map mOwnerClientIdsToSessionNum = new HashMap<>(); - private CasResource(Builder builder) { + CasResource(Builder builder) { this.mSystemId = builder.mSystemId; this.mMaxSessionNum = builder.mMaxSessionNum; this.mAvailableSessionNum = builder.mMaxSessionNum; @@ -111,7 +111,7 @@ public final class CasResource { public static class Builder { private int mSystemId; - private int mMaxSessionNum; + protected int mMaxSessionNum; Builder(int systemId) { this.mSystemId = systemId; @@ -138,7 +138,7 @@ public final class CasResource { } } - private String ownersMapToString() { + protected String ownersMapToString() { StringBuilder string = new StringBuilder("{"); for (int clienId : mOwnerClientIdsToSessionNum.keySet()) { string.append(" clientId=") diff --git a/services/core/java/com/android/server/tv/tunerresourcemanager/CiCamResource.java b/services/core/java/com/android/server/tv/tunerresourcemanager/CiCamResource.java new file mode 100644 index 0000000000000..31149f3590b8a --- /dev/null +++ b/services/core/java/com/android/server/tv/tunerresourcemanager/CiCamResource.java @@ -0,0 +1,70 @@ +/* + * 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; + +/** + * A CiCam resource object used by the Tuner Resource Manager to record the CiCam + * information. + * + * @hide + */ +public final class CiCamResource extends CasResource { + private CiCamResource(Builder builder) { + super(builder); + } + + @Override + public String toString() { + return "CiCamResource[systemId=" + this.getSystemId() + + ", isFullyUsed=" + (this.isFullyUsed()) + + ", maxSessionNum=" + this.getMaxSessionNum() + + ", ownerClients=" + ownersMapToString() + "]"; + } + + public int getCiCamId() { + return this.getSystemId(); + } + + /** + * Builder class for {@link CiCamResource}. + */ + public static class Builder extends CasResource.Builder { + Builder(int systemId) { + super(systemId); + } + + /** + * Builder for {@link CasResource}. + * + * @param maxSessionNum the max session num the current Cas has. + */ + public Builder maxSessionNum(int maxSessionNum) { + super.mMaxSessionNum = maxSessionNum; + return this; + } + + /** + * Build a {@link CiCamResource}. + * + * @return {@link CiCamResource}. + */ + @Override + public CiCamResource build() { + CiCamResource ciCam = new CiCamResource(this); + return ciCam; + } + } +} 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 edf007d428c1a..5723e1dcceb59 100644 --- a/services/core/java/com/android/server/tv/tunerresourcemanager/ClientProfile.java +++ b/services/core/java/com/android/server/tv/tunerresourcemanager/ClientProfile.java @@ -50,6 +50,8 @@ public final class ClientProfile { */ private final int mProcessId; + private boolean mIsForeground; + /** * All the clients that share the same resource would be under the same group id. * @@ -82,6 +84,11 @@ public final class ClientProfile { */ private int mUsingCasSystemId = INVALID_RESOURCE_ID; + /** + * CiCam id that is used by the client. + */ + private int mUsingCiCamId = INVALID_RESOURCE_ID; + /** * Optional arbitrary priority value given by the client. * @@ -113,6 +120,20 @@ public final class ClientProfile { return mProcessId; } + /** + * Set the current isForeground status. + */ + public void setForeground(boolean isForeground) { + mIsForeground = isForeground; + } + + /** + * Get the previous recorded isForeground status. + */ + public boolean isForeground() { + return mIsForeground; + } + public int getGroupId() { return mGroupId; } @@ -221,6 +242,26 @@ public final class ClientProfile { mUsingCasSystemId = INVALID_RESOURCE_ID; } + /** + * Set when the client starts to connect to a CiCam. + * + * @param ciCamId ciCam being used. + */ + public void useCiCam(int ciCamId) { + mUsingCiCamId = ciCamId; + } + + public int getInUseCiCamId() { + return mUsingCiCamId; + } + + /** + * Called when the client disconnect to a CiCam. + */ + public void releaseCiCam() { + mUsingCiCamId = INVALID_RESOURCE_ID; + } + /** * Called to reclaim all the resources being used by the current client. */ @@ -229,6 +270,7 @@ public final class ClientProfile { mShareFeClientIds.clear(); mUsingLnbHandles.clear(); mUsingCasSystemId = INVALID_RESOURCE_ID; + mUsingCiCamId = INVALID_RESOURCE_ID; } @Override 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 8c6e690afe5bd..072bdd2d15069 100644 --- a/services/core/java/com/android/server/tv/tunerresourcemanager/TunerResourceManagerService.java +++ b/services/core/java/com/android/server/tv/tunerresourcemanager/TunerResourceManagerService.java @@ -27,6 +27,7 @@ import android.media.tv.tunerresourcemanager.CasSessionRequest; import android.media.tv.tunerresourcemanager.IResourcesReclaimListener; import android.media.tv.tunerresourcemanager.ITunerResourceManager; import android.media.tv.tunerresourcemanager.ResourceClientProfile; +import android.media.tv.tunerresourcemanager.TunerCiCamRequest; import android.media.tv.tunerresourcemanager.TunerDemuxRequest; import android.media.tv.tunerresourcemanager.TunerDescramblerRequest; import android.media.tv.tunerresourcemanager.TunerFrontendInfo; @@ -71,6 +72,8 @@ public class TunerResourceManagerService extends SystemService implements IBinde private Map mLnbResources = new HashMap<>(); // Map of the current available Cas resources private Map mCasResources = new HashMap<>(); + // Map of the current available CiCam resources + private Map mCiCamResources = new HashMap<>(); @GuardedBy("mLock") private Map mListeners = new HashMap<>(); @@ -141,8 +144,8 @@ public class TunerResourceManagerService extends SystemService implements IBinde throw new RemoteException("IResourcesReclaimListener can't be null!"); } - if (!mPriorityCongfig.isDefinedUseCase(profile.getUseCase())) { - throw new RemoteException("Use undefined client use case:" + profile.getUseCase()); + if (!mPriorityCongfig.isDefinedUseCase(profile.useCase)) { + throw new RemoteException("Use undefined client use case:" + profile.useCase); } synchronized (mLock) { @@ -209,14 +212,14 @@ public class TunerResourceManagerService extends SystemService implements IBinde throw new RemoteException("frontendHandle can't be null"); } synchronized (mLock) { - if (!checkClientExists(request.getClientId())) { + if (!checkClientExists(request.clientId)) { throw new RemoteException("Request frontend from unregistered client: " - + request.getClientId()); + + request.clientId); } // If the request client is holding or sharing a frontend, throw an exception. - if (!getClientProfile(request.getClientId()).getInUseFrontendHandles().isEmpty()) { + if (!getClientProfile(request.clientId).getInUseFrontendHandles().isEmpty()) { throw new RemoteException("Release frontend before requesting another one. " - + "Client id: " + request.getClientId()); + + "Client id: " + request.clientId); } return requestFrontendInternal(request, frontendHandle); } @@ -252,9 +255,9 @@ public class TunerResourceManagerService extends SystemService implements IBinde throw new RemoteException("demuxHandle can't be null"); } synchronized (mLock) { - if (!checkClientExists(request.getClientId())) { + if (!checkClientExists(request.clientId)) { throw new RemoteException("Request demux from unregistered client:" - + request.getClientId()); + + request.clientId); } return requestDemuxInternal(request, demuxHandle); } @@ -269,9 +272,9 @@ public class TunerResourceManagerService extends SystemService implements IBinde throw new RemoteException("descramblerHandle can't be null"); } synchronized (mLock) { - if (!checkClientExists(request.getClientId())) { + if (!checkClientExists(request.clientId)) { throw new RemoteException("Request descrambler from unregistered client:" - + request.getClientId()); + + request.clientId); } return requestDescramblerInternal(request, descramblerHandle); } @@ -285,14 +288,30 @@ public class TunerResourceManagerService extends SystemService implements IBinde throw new RemoteException("casSessionHandle can't be null"); } synchronized (mLock) { - if (!checkClientExists(request.getClientId())) { + if (!checkClientExists(request.clientId)) { throw new RemoteException("Request cas from unregistered client:" - + request.getClientId()); + + request.clientId); } return requestCasSessionInternal(request, casSessionHandle); } } + @Override + public boolean requestCiCam(@NonNull TunerCiCamRequest request, + @NonNull int[] ciCamHandle) throws RemoteException { + enforceTrmAccessPermission("requestCiCam"); + if (ciCamHandle == null) { + throw new RemoteException("ciCamHandle can't be null"); + } + synchronized (mLock) { + if (!checkClientExists(request.clientId)) { + throw new RemoteException("Request ciCam from unregistered client:" + + request.clientId); + } + return requestCiCamInternal(request, ciCamHandle); + } + } + @Override public boolean requestLnb(@NonNull TunerLnbRequest request, @NonNull int[] lnbHandle) throws RemoteException { @@ -302,9 +321,9 @@ public class TunerResourceManagerService extends SystemService implements IBinde throw new RemoteException("lnbHandle can't be null"); } synchronized (mLock) { - if (!checkClientExists(request.getClientId())) { + if (!checkClientExists(request.clientId)) { throw new RemoteException("Request lnb from unregistered client:" - + request.getClientId()); + + request.clientId); } return requestLnbInternal(request, lnbHandle); } @@ -377,6 +396,34 @@ public class TunerResourceManagerService extends SystemService implements IBinde } } + @Override + public void releaseCiCam(int ciCamHandle, int clientId) throws RemoteException { + enforceTrmAccessPermission("releaseCiCam"); + if (!validateResourceHandle( + TunerResourceManager.TUNER_RESOURCE_TYPE_FRONTEND_CICAM, ciCamHandle)) { + throw new RemoteException("ciCamHandle can't be invalid"); + } + synchronized (mLock) { + if (!checkClientExists(clientId)) { + throw new RemoteException("Release ciCam from unregistered client:" + clientId); + } + int ciCamId = getClientProfile(clientId).getInUseCiCamId(); + if (ciCamId != getResourceIdFromHandle(ciCamHandle)) { + throw new RemoteException("The client " + clientId + " is not the owner of " + + "the releasing ciCam."); + } + CiCamResource ciCam = getCiCamResource(ciCamId); + if (ciCam == null) { + throw new RemoteException("Releasing ciCam does not exist."); + } + if (!ciCam.getOwnerClientIds().contains(clientId)) { + throw new RemoteException( + "Client is not the current owner of the releasing ciCam."); + } + releaseCiCamInternal(ciCam, clientId); + } + } + @Override public void releaseLnb(int lnbHandle, int clientId) throws RemoteException { enforceTunerAccessPermission("releaseLnb"); @@ -441,12 +488,12 @@ public class TunerResourceManagerService extends SystemService implements IBinde // TODO tell if the client already exists clientId[0] = mNextUnusedClientId++; - int pid = profile.getTvInputSessionId() == null + int pid = profile.tvInputSessionId == null ? Binder.getCallingPid() /*callingPid*/ - : mTvInputManager.getClientPid(profile.getTvInputSessionId()); /*tvAppId*/ + : mTvInputManager.getClientPid(profile.tvInputSessionId); /*tvAppId*/ // Update Media Resource Manager with the tvAppId - if (profile.getTvInputSessionId() != null && mMediaResourceManager != null) { + if (profile.tvInputSessionId != null && mMediaResourceManager != null) { try { mMediaResourceManager.overridePid(Binder.getCallingPid(), pid); } catch (RemoteException e) { @@ -456,11 +503,13 @@ public class TunerResourceManagerService extends SystemService implements IBinde } ClientProfile clientProfile = new ClientProfile.Builder(clientId[0]) - .tvInputSessionId(profile.getTvInputSessionId()) - .useCase(profile.getUseCase()) + .tvInputSessionId(profile.tvInputSessionId) + .useCase(profile.useCase) .processId(pid) .build(); - clientProfile.setPriority(getClientPriority(profile.getUseCase(), pid)); + clientProfile.setForeground(checkIsForeground(pid)); + clientProfile.setPriority( + getClientPriority(profile.useCase, clientProfile.isForeground())); addClientProfile(clientId[0], clientProfile, listener); } @@ -498,6 +547,7 @@ public class TunerResourceManagerService extends SystemService implements IBinde return false; } + profile.setForeground(checkIsForeground(profile.getProcessId())); profile.setPriority(priority); profile.setNiceValue(niceValue); @@ -520,16 +570,16 @@ public class TunerResourceManagerService extends SystemService implements IBinde // Update frontendResources map and other mappings accordingly for (int i = 0; i < infos.length; i++) { - if (getFrontendResource(infos[i].getHandle()) != null) { + if (getFrontendResource(infos[i].handle) != null) { if (DEBUG) { - Slog.d(TAG, "Frontend handle=" + infos[i].getHandle() + "exists."); + Slog.d(TAG, "Frontend handle=" + infos[i].handle + "exists."); } - updatingFrontendHandles.remove(infos[i].getHandle()); + updatingFrontendHandles.remove(infos[i].handle); } else { // Add a new fe resource - FrontendResource newFe = new FrontendResource.Builder(infos[i].getHandle()) - .type(infos[i].getFrontendType()) - .exclusiveGroupId(infos[i].getExclusiveGroupId()) + FrontendResource newFe = new FrontendResource.Builder(infos[i].handle) + .type(infos[i].frontendType) + .exclusiveGroupId(infos[i].exclusiveGroupId) .build(); addFrontendResource(newFe); } @@ -583,24 +633,33 @@ public class TunerResourceManagerService extends SystemService implements IBinde // If maxSessionNum is 0, removing the Cas Resource. if (maxSessionNum == 0) { removeCasResource(casSystemId); + removeCiCamResource(casSystemId); return; } // If the Cas exists, updates the Cas Resource accordingly. CasResource cas = getCasResource(casSystemId); + CiCamResource ciCam = getCiCamResource(casSystemId); if (cas != null) { if (cas.getUsedSessionNum() > maxSessionNum) { // Sort and release the short number of Cas resources. int releasingCasResourceNum = cas.getUsedSessionNum() - maxSessionNum; - releaseLowerPriorityClientCasResources(releasingCasResourceNum); + // TODO: handle CiCam session update. } cas.updateMaxSessionNum(maxSessionNum); + if (ciCam != null) { + ciCam.updateMaxSessionNum(maxSessionNum); + } return; } // Add the new Cas Resource. cas = new CasResource.Builder(casSystemId) .maxSessionNum(maxSessionNum) .build(); + ciCam = new CiCamResource.Builder(casSystemId) + .maxSessionNum(maxSessionNum) + .build(); addCasResource(cas); + addCiCamResource(ciCam); } @VisibleForTesting @@ -610,13 +669,17 @@ public class TunerResourceManagerService extends SystemService implements IBinde } frontendHandle[0] = TunerResourceManager.INVALID_RESOURCE_HANDLE; - ClientProfile requestClient = getClientProfile(request.getClientId()); + ClientProfile requestClient = getClientProfile(request.clientId); + if (requestClient == null) { + return false; + } + clientPriorityUpdateOnRequest(requestClient); int grantingFrontendHandle = TunerResourceManager.INVALID_RESOURCE_HANDLE; int inUseLowestPriorityFrHandle = TunerResourceManager.INVALID_RESOURCE_HANDLE; // Priority max value is 1000 int currentLowestPriority = MAX_CLIENT_PRIORITY + 1; for (FrontendResource fr : getFrontendResources().values()) { - if (fr.getType() == request.getFrontendType()) { + if (fr.getType() == request.frontendType) { if (!fr.isInUse()) { // Grant unused frontend with no exclusive group members first. if (fr.getExclusiveGroupMemberFeHandles().isEmpty()) { @@ -643,7 +706,7 @@ public class TunerResourceManagerService extends SystemService implements IBinde // Grant frontend when there is unused resource. if (grantingFrontendHandle != TunerResourceManager.INVALID_RESOURCE_HANDLE) { frontendHandle[0] = grantingFrontendHandle; - updateFrontendClientMappingOnNewGrant(grantingFrontendHandle, request.getClientId()); + updateFrontendClientMappingOnNewGrant(grantingFrontendHandle, request.clientId); return true; } @@ -658,7 +721,7 @@ public class TunerResourceManagerService extends SystemService implements IBinde } frontendHandle[0] = inUseLowestPriorityFrHandle; updateFrontendClientMappingOnNewGrant( - inUseLowestPriorityFrHandle, request.getClientId()); + inUseLowestPriorityFrHandle, request.clientId); return true; } @@ -683,7 +746,8 @@ public class TunerResourceManagerService extends SystemService implements IBinde } lnbHandle[0] = TunerResourceManager.INVALID_RESOURCE_HANDLE; - ClientProfile requestClient = getClientProfile(request.getClientId()); + ClientProfile requestClient = getClientProfile(request.clientId); + clientPriorityUpdateOnRequest(requestClient); int grantingLnbHandle = TunerResourceManager.INVALID_RESOURCE_HANDLE; int inUseLowestPriorityLnbHandle = TunerResourceManager.INVALID_RESOURCE_HANDLE; // Priority max value is 1000 @@ -707,7 +771,7 @@ public class TunerResourceManagerService extends SystemService implements IBinde // Grant Lnb when there is unused resource. if (grantingLnbHandle > -1) { lnbHandle[0] = grantingLnbHandle; - updateLnbClientMappingOnNewGrant(grantingLnbHandle, request.getClientId()); + updateLnbClientMappingOnNewGrant(grantingLnbHandle, request.clientId); return true; } @@ -720,7 +784,7 @@ public class TunerResourceManagerService extends SystemService implements IBinde return false; } lnbHandle[0] = inUseLowestPriorityLnbHandle; - updateLnbClientMappingOnNewGrant(inUseLowestPriorityLnbHandle, request.getClientId()); + updateLnbClientMappingOnNewGrant(inUseLowestPriorityLnbHandle, request.clientId); return true; } @@ -732,23 +796,24 @@ public class TunerResourceManagerService extends SystemService implements IBinde if (DEBUG) { Slog.d(TAG, "requestCasSession(request=" + request + ")"); } - CasResource cas = getCasResource(request.getCasSystemId()); + CasResource cas = getCasResource(request.casSystemId); // Unregistered Cas System is treated as having unlimited sessions. if (cas == null) { - cas = new CasResource.Builder(request.getCasSystemId()) + cas = new CasResource.Builder(request.casSystemId) .maxSessionNum(Integer.MAX_VALUE) .build(); addCasResource(cas); } casSessionHandle[0] = TunerResourceManager.INVALID_RESOURCE_HANDLE; - ClientProfile requestClient = getClientProfile(request.getClientId()); + ClientProfile requestClient = getClientProfile(request.clientId); + clientPriorityUpdateOnRequest(requestClient); int lowestPriorityOwnerId = -1; // Priority max value is 1000 int currentLowestPriority = MAX_CLIENT_PRIORITY + 1; if (!cas.isFullyUsed()) { casSessionHandle[0] = generateResourceHandle( TunerResourceManager.TUNER_RESOURCE_TYPE_CAS_SESSION, cas.getSystemId()); - updateCasClientMappingOnNewGrant(request.getCasSystemId(), request.getClientId()); + updateCasClientMappingOnNewGrant(request.casSystemId, request.clientId); return true; } for (int ownerId : cas.getOwnerClientIds()) { @@ -769,7 +834,56 @@ public class TunerResourceManagerService extends SystemService implements IBinde } casSessionHandle[0] = generateResourceHandle( TunerResourceManager.TUNER_RESOURCE_TYPE_CAS_SESSION, cas.getSystemId()); - updateCasClientMappingOnNewGrant(request.getCasSystemId(), request.getClientId()); + updateCasClientMappingOnNewGrant(request.casSystemId, request.clientId); + return true; + } + return false; + } + + @VisibleForTesting + protected boolean requestCiCamInternal(TunerCiCamRequest request, int[] ciCamHandle) { + if (DEBUG) { + Slog.d(TAG, "requestCiCamInternal(TunerCiCamRequest=" + request + ")"); + } + CiCamResource ciCam = getCiCamResource(request.ciCamId); + // Unregistered Cas System is treated as having unlimited sessions. + if (ciCam == null) { + ciCam = new CiCamResource.Builder(request.ciCamId) + .maxSessionNum(Integer.MAX_VALUE) + .build(); + addCiCamResource(ciCam); + } + ciCamHandle[0] = TunerResourceManager.INVALID_RESOURCE_HANDLE; + ClientProfile requestClient = getClientProfile(request.clientId); + clientPriorityUpdateOnRequest(requestClient); + int lowestPriorityOwnerId = -1; + // Priority max value is 1000 + int currentLowestPriority = MAX_CLIENT_PRIORITY + 1; + if (!ciCam.isFullyUsed()) { + ciCamHandle[0] = generateResourceHandle( + TunerResourceManager.TUNER_RESOURCE_TYPE_FRONTEND_CICAM, ciCam.getCiCamId()); + updateCiCamClientMappingOnNewGrant(request.ciCamId, request.clientId); + return true; + } + for (int ownerId : ciCam.getOwnerClientIds()) { + // Record the client id with lowest priority that is using the current Cas system. + int priority = getOwnerClientPriority(ownerId); + if (currentLowestPriority > priority) { + lowestPriorityOwnerId = ownerId; + currentLowestPriority = priority; + } + } + + // When all the CiCam sessions are occupied, reclaim the lowest priority client if the + // request client has higher priority. + if (lowestPriorityOwnerId > -1 && (requestClient.getPriority() > currentLowestPriority)) { + if (!reclaimResource(lowestPriorityOwnerId, + TunerResourceManager.TUNER_RESOURCE_TYPE_FRONTEND_CICAM)) { + return false; + } + ciCamHandle[0] = generateResourceHandle( + TunerResourceManager.TUNER_RESOURCE_TYPE_FRONTEND_CICAM, ciCam.getCiCamId()); + updateCiCamClientMappingOnNewGrant(request.ciCamId, request.clientId); return true; } return false; @@ -790,15 +904,16 @@ public class TunerResourceManagerService extends SystemService implements IBinde return true; } - int challengerPid = challengerProfile.getTvInputSessionId() == null + int challengerPid = challengerProfile.tvInputSessionId == null ? Binder.getCallingPid() /*callingPid*/ - : mTvInputManager.getClientPid(challengerProfile.getTvInputSessionId()); /*tvAppId*/ - int holderPid = holderProfile.getTvInputSessionId() == null + : mTvInputManager.getClientPid(challengerProfile.tvInputSessionId); /*tvAppId*/ + int holderPid = holderProfile.tvInputSessionId == null ? Binder.getCallingPid() /*callingPid*/ - : mTvInputManager.getClientPid(holderProfile.getTvInputSessionId()); /*tvAppId*/ + : mTvInputManager.getClientPid(holderProfile.tvInputSessionId); /*tvAppId*/ - int challengerPriority = getClientPriority(challengerProfile.getUseCase(), challengerPid); - int holderPriority = getClientPriority(holderProfile.getUseCase(), holderPid); + int challengerPriority = getClientPriority( + challengerProfile.useCase, checkIsForeground(challengerPid)); + int holderPriority = getClientPriority(holderProfile.useCase, checkIsForeground(holderPid)); return challengerPriority > holderPriority; } @@ -832,6 +947,14 @@ public class TunerResourceManagerService extends SystemService implements IBinde updateCasClientMappingOnRelease(cas, ownerClientId); } + @VisibleForTesting + protected void releaseCiCamInternal(CiCamResource ciCam, int ownerClientId) { + if (DEBUG) { + Slog.d(TAG, "releaseCiCamInternal(ciCamId=" + ciCam.getCiCamId() + ")"); + } + updateCiCamClientMappingOnRelease(ciCam, ownerClientId); + } + @VisibleForTesting protected boolean requestDemuxInternal(TunerDemuxRequest request, int[] demuxHandle) { if (DEBUG) { @@ -842,6 +965,21 @@ public class TunerResourceManagerService extends SystemService implements IBinde return true; } + @VisibleForTesting + // This mothod is to sync up the request client's foreground/background status and update + // the client priority accordingly whenever new resource request comes in. + protected void clientPriorityUpdateOnRequest(ClientProfile requestProfile) { + int pid = requestProfile.getProcessId(); + boolean currentIsForeground = checkIsForeground(pid); + if (requestProfile.isForeground() == currentIsForeground) { + // To avoid overriding the priority set through updateClientPriority API. + return; + } + requestProfile.setForeground(currentIsForeground); + requestProfile.setPriority( + getClientPriority(requestProfile.getUseCase(), currentIsForeground)); + } + @VisibleForTesting protected boolean requestDescramblerInternal( TunerDescramblerRequest request, int[] descramblerHandle) { @@ -933,20 +1071,20 @@ public class TunerResourceManagerService extends SystemService implements IBinde } @VisibleForTesting - protected int getClientPriority(int useCase, int pid) { + protected int getClientPriority(int useCase, boolean isForeground) { if (DEBUG) { Slog.d(TAG, "getClientPriority useCase=" + useCase - + ", pid=" + pid + ")"); + + ", isForeground=" + isForeground + ")"); } - if (isForeground(pid)) { + if (isForeground) { return mPriorityCongfig.getForegroundPriority(useCase); } return mPriorityCongfig.getBackgroundPriority(useCase); } @VisibleForTesting - protected boolean isForeground(int pid) { + protected boolean checkIsForeground(int pid) { if (mActivityManager == null) { return false; } @@ -994,6 +1132,13 @@ public class TunerResourceManagerService extends SystemService implements IBinde ownerProfile.useCas(grantingId); } + private void updateCiCamClientMappingOnNewGrant(int grantingId, int ownerClientId) { + CiCamResource grantingCiCam = getCiCamResource(grantingId); + ClientProfile ownerProfile = getClientProfile(ownerClientId); + grantingCiCam.setOwner(ownerClientId); + ownerProfile.useCiCam(grantingId); + } + private void updateCasClientMappingOnRelease( @NonNull CasResource releasingCas, int ownerClientId) { ClientProfile ownerProfile = getClientProfile(ownerClientId); @@ -1001,6 +1146,13 @@ public class TunerResourceManagerService extends SystemService implements IBinde ownerProfile.releaseCas(); } + private void updateCiCamClientMappingOnRelease( + @NonNull CiCamResource releasingCiCam, int ownerClientId) { + ClientProfile ownerProfile = getClientProfile(ownerClientId); + releasingCiCam.removeOwner(ownerClientId); + ownerProfile.releaseCiCam(); + } + /** * Get the owner client's priority. * @@ -1092,16 +1244,32 @@ public class TunerResourceManagerService extends SystemService implements IBinde return mCasResources.get(systemId); } + @VisibleForTesting + @Nullable + protected CiCamResource getCiCamResource(int ciCamId) { + return mCiCamResources.get(ciCamId); + } + @VisibleForTesting protected Map getCasResources() { return mCasResources; } + @VisibleForTesting + protected Map getCiCamResources() { + return mCiCamResources; + } + private void addCasResource(CasResource newCas) { // Update resource list and available id list mCasResources.put(newCas.getSystemId(), newCas); } + private void addCiCamResource(CiCamResource newCiCam) { + // Update resource list and available id list + mCiCamResources.put(newCiCam.getCiCamId(), newCiCam); + } + private void removeCasResource(int removingId) { CasResource cas = getCasResource(removingId); if (cas == null) { @@ -1113,6 +1281,17 @@ public class TunerResourceManagerService extends SystemService implements IBinde mCasResources.remove(removingId); } + private void removeCiCamResource(int removingId) { + CiCamResource ciCam = getCiCamResource(removingId); + if (ciCam == null) { + return; + } + for (int ownerId : ciCam.getOwnerClientIds()) { + getClientProfile(ownerId).releaseCiCam(); + } + mCiCamResources.remove(removingId); + } + private void releaseLowerPriorityClientCasResources(int releasingCasResourceNum) { // TODO: Sort with a treemap @@ -1161,6 +1340,10 @@ public class TunerResourceManagerService extends SystemService implements IBinde if (profile.getInUseCasSystemId() != ClientProfile.INVALID_RESOURCE_ID) { getCasResource(profile.getInUseCasSystemId()).removeOwner(profile.getId()); } + // Clear CiCam + if (profile.getInUseCiCamId() != ClientProfile.INVALID_RESOURCE_ID) { + getCiCamResource(profile.getInUseCiCamId()).removeOwner(profile.getId()); + } // Clear Frontend clearFrontendAndClientMapping(profile); profile.reclaimAllResources(); 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 62be98c15a2ed..385837009b2f6 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 @@ -29,6 +29,7 @@ import android.media.tv.tuner.frontend.FrontendSettings; import android.media.tv.tunerresourcemanager.CasSessionRequest; import android.media.tv.tunerresourcemanager.IResourcesReclaimListener; import android.media.tv.tunerresourcemanager.ResourceClientProfile; +import android.media.tv.tunerresourcemanager.TunerCiCamRequest; import android.media.tv.tunerresourcemanager.TunerDemuxRequest; import android.media.tv.tunerresourcemanager.TunerDescramblerRequest; import android.media.tv.tunerresourcemanager.TunerFrontendInfo; @@ -86,9 +87,9 @@ public class TunerResourceManagerServiceTest { return (actual == null) && (expected == null); } - return actual.getHandle() == expected.getHandle() - && actual.getType() == expected.getFrontendType() - && actual.getExclusiveGroupId() == expected.getExclusiveGroupId(); + return actual.getHandle() == expected.handle + && actual.getType() == expected.frontendType + && actual.getExclusiveGroupId() == expected.exclusiveGroupId; }, "is correctly configured from "); @Before @@ -99,7 +100,7 @@ public class TunerResourceManagerServiceTest { when(mContextSpy.getSystemService(Context.TV_INPUT_SERVICE)).thenReturn(tvInputManager); mTunerResourceManagerService = new TunerResourceManagerService(mContextSpy) { @Override - protected boolean isForeground(int pid) { + protected boolean checkIsForeground(int pid) { return mIsForeground; } }; @@ -111,19 +112,19 @@ public class TunerResourceManagerServiceTest { // Init frontend resources. TunerFrontendInfo[] infos = new TunerFrontendInfo[2]; infos[0] = - new TunerFrontendInfo(0 /*id*/, FrontendSettings.TYPE_DVBT, 0 /*exclusiveGroupId*/); + tunerFrontendInfo(0 /*handle*/, FrontendSettings.TYPE_DVBT, 0 /*exclusiveGroupId*/); infos[1] = - new TunerFrontendInfo(1 /*id*/, FrontendSettings.TYPE_DVBT, 1 /*exclusiveGroupId*/); + tunerFrontendInfo(1 /*handle*/, FrontendSettings.TYPE_DVBT, 1 /*exclusiveGroupId*/); mTunerResourceManagerService.setFrontendInfoListInternal(infos); Map resources = mTunerResourceManagerService.getFrontendResources(); for (int id = 0; id < infos.length; id++) { - assertThat(resources.get(infos[id].getHandle()) + assertThat(resources.get(infos[id].handle) .getExclusiveGroupMemberFeHandles().size()).isEqualTo(0); } for (int id = 0; id < infos.length; id++) { - assertThat(resources.get(infos[id].getHandle()) + assertThat(resources.get(infos[id].handle) .getExclusiveGroupMemberFeHandles().size()).isEqualTo(0); } assertThat(resources.values()).comparingElementsUsing(FR_TFI_COMPARE) @@ -135,13 +136,13 @@ public class TunerResourceManagerServiceTest { // Init frontend resources. TunerFrontendInfo[] infos = new TunerFrontendInfo[4]; infos[0] = - new TunerFrontendInfo(0 /*id*/, FrontendSettings.TYPE_DVBT, 0 /*exclusiveGroupId*/); + tunerFrontendInfo(0 /*handle*/, FrontendSettings.TYPE_DVBT, 0 /*exclusiveGroupId*/); infos[1] = - new TunerFrontendInfo(1 /*id*/, FrontendSettings.TYPE_DVBT, 1 /*exclusiveGroupId*/); + tunerFrontendInfo(1 /*handle*/, FrontendSettings.TYPE_DVBT, 1 /*exclusiveGroupId*/); infos[2] = - new TunerFrontendInfo(2 /*id*/, FrontendSettings.TYPE_DVBS, 1 /*exclusiveGroupId*/); + tunerFrontendInfo(2 /*handle*/, FrontendSettings.TYPE_DVBS, 1 /*exclusiveGroupId*/); infos[3] = - new TunerFrontendInfo(3 /*id*/, FrontendSettings.TYPE_ATSC, 1 /*exclusiveGroupId*/); + tunerFrontendInfo(3 /*handle*/, FrontendSettings.TYPE_ATSC, 1 /*exclusiveGroupId*/); mTunerResourceManagerService.setFrontendInfoListInternal(infos); Map resources = @@ -160,9 +161,9 @@ public class TunerResourceManagerServiceTest { // Init frontend resources. TunerFrontendInfo[] infos = new TunerFrontendInfo[2]; infos[0] = - new TunerFrontendInfo(0 /*id*/, FrontendSettings.TYPE_DVBT, 1 /*exclusiveGroupId*/); + tunerFrontendInfo(0 /*handle*/, FrontendSettings.TYPE_DVBT, 1 /*exclusiveGroupId*/); infos[1] = - new TunerFrontendInfo(1 /*id*/, FrontendSettings.TYPE_DVBS, 1 /*exclusiveGroupId*/); + tunerFrontendInfo(1 /*handle*/, FrontendSettings.TYPE_DVBS, 1 /*exclusiveGroupId*/); mTunerResourceManagerService.setFrontendInfoListInternal(infos); Map resources0 = @@ -180,22 +181,22 @@ public class TunerResourceManagerServiceTest { // Init frontend resources. TunerFrontendInfo[] infos0 = new TunerFrontendInfo[3]; infos0[0] = - new TunerFrontendInfo(0 /*id*/, FrontendSettings.TYPE_DVBT, 0 /*exclusiveGroupId*/); + tunerFrontendInfo(0 /*handle*/, FrontendSettings.TYPE_DVBT, 0 /*exclusiveGroupId*/); infos0[1] = - new TunerFrontendInfo(1 /*id*/, FrontendSettings.TYPE_DVBT, 1 /*exclusiveGroupId*/); + tunerFrontendInfo(1 /*handle*/, FrontendSettings.TYPE_DVBT, 1 /*exclusiveGroupId*/); infos0[2] = - new TunerFrontendInfo(2 /*id*/, FrontendSettings.TYPE_DVBS, 2 /*exclusiveGroupId*/); + tunerFrontendInfo(2 /*handle*/, FrontendSettings.TYPE_DVBS, 2 /*exclusiveGroupId*/); mTunerResourceManagerService.setFrontendInfoListInternal(infos0); TunerFrontendInfo[] infos1 = new TunerFrontendInfo[1]; infos1[0] = - new TunerFrontendInfo(1 /*id*/, FrontendSettings.TYPE_DVBT, 1 /*exclusiveGroupId*/); + tunerFrontendInfo(1 /*handle*/, FrontendSettings.TYPE_DVBT, 1 /*exclusiveGroupId*/); mTunerResourceManagerService.setFrontendInfoListInternal(infos1); Map resources = mTunerResourceManagerService.getFrontendResources(); for (int id = 0; id < infos1.length; id++) { - assertThat(resources.get(infos1[id].getHandle()) + assertThat(resources.get(infos1[id].handle) .getExclusiveGroupMemberFeHandles().size()).isEqualTo(0); } assertThat(resources.values()).comparingElementsUsing(FR_TFI_COMPARE) @@ -207,22 +208,22 @@ public class TunerResourceManagerServiceTest { // Init frontend resources. TunerFrontendInfo[] infos0 = new TunerFrontendInfo[3]; infos0[0] = - new TunerFrontendInfo(0 /*id*/, FrontendSettings.TYPE_DVBT, 0 /*exclusiveGroupId*/); + tunerFrontendInfo(0 /*handle*/, FrontendSettings.TYPE_DVBT, 0 /*exclusiveGroupId*/); infos0[1] = - new TunerFrontendInfo(1 /*id*/, FrontendSettings.TYPE_DVBT, 1 /*exclusiveGroupId*/); + tunerFrontendInfo(1 /*handle*/, FrontendSettings.TYPE_DVBT, 1 /*exclusiveGroupId*/); infos0[2] = - new TunerFrontendInfo(2 /*id*/, FrontendSettings.TYPE_DVBS, 1 /*exclusiveGroupId*/); + tunerFrontendInfo(2 /*handle*/, FrontendSettings.TYPE_DVBS, 1 /*exclusiveGroupId*/); mTunerResourceManagerService.setFrontendInfoListInternal(infos0); TunerFrontendInfo[] infos1 = new TunerFrontendInfo[1]; infos1[0] = - new TunerFrontendInfo(1 /*id*/, FrontendSettings.TYPE_DVBT, 1 /*exclusiveGroupId*/); + tunerFrontendInfo(1 /*handle*/, FrontendSettings.TYPE_DVBT, 1 /*exclusiveGroupId*/); mTunerResourceManagerService.setFrontendInfoListInternal(infos1); Map resources = mTunerResourceManagerService.getFrontendResources(); for (int id = 0; id < infos1.length; id++) { - assertThat(resources.get(infos1[id].getHandle()) + assertThat(resources.get(infos1[id].handle) .getExclusiveGroupMemberFeHandles().size()).isEqualTo(0); } assertThat(resources.values()).comparingElementsUsing(FR_TFI_COMPARE) @@ -231,8 +232,12 @@ public class TunerResourceManagerServiceTest { @Test public void requestFrontendTest_ClientNotRegistered() { + TunerFrontendInfo[] infos0 = new TunerFrontendInfo[1]; + infos0[0] = + tunerFrontendInfo(0 /*id*/, FrontendSettings.TYPE_DVBT, 0 /*exclusiveGroupId*/); + mTunerResourceManagerService.setFrontendInfoListInternal(infos0); TunerFrontendRequest request = - new TunerFrontendRequest(0 /*clientId*/, FrontendSettings.TYPE_DVBT); + tunerFrontendRequest(0 /*clientId*/, FrontendSettings.TYPE_DVBT); int[] frontendHandle = new int[1]; assertThat(mTunerResourceManagerService .requestFrontendInternal(request, frontendHandle)).isFalse(); @@ -241,7 +246,7 @@ public class TunerResourceManagerServiceTest { @Test public void requestFrontendTest_NoFrontendWithGiveTypeAvailable() { - ResourceClientProfile profile = new ResourceClientProfile("0" /*sessionId*/, + ResourceClientProfile profile = resourceClientProfile("0" /*sessionId*/, TvInputService.PRIORITY_HINT_USE_CASE_TYPE_PLAYBACK); int[] clientId = new int[1]; mTunerResourceManagerService.registerClientProfileInternal( @@ -251,11 +256,11 @@ public class TunerResourceManagerServiceTest { // Init frontend resources. TunerFrontendInfo[] infos = new TunerFrontendInfo[1]; infos[0] = - new TunerFrontendInfo(0 /*id*/, FrontendSettings.TYPE_DVBS, 0 /*exclusiveGroupId*/); + tunerFrontendInfo(0 /*handle*/, FrontendSettings.TYPE_DVBS, 0 /*exclusiveGroupId*/); mTunerResourceManagerService.setFrontendInfoListInternal(infos); TunerFrontendRequest request = - new TunerFrontendRequest(clientId[0] /*clientId*/, FrontendSettings.TYPE_DVBT); + tunerFrontendRequest(clientId[0] /*clientId*/, FrontendSettings.TYPE_DVBT); int[] frontendHandle = new int[1]; assertThat(mTunerResourceManagerService .requestFrontendInternal(request, frontendHandle)).isFalse(); @@ -264,7 +269,7 @@ public class TunerResourceManagerServiceTest { @Test public void requestFrontendTest_FrontendWithNoExclusiveGroupAvailable() { - ResourceClientProfile profile = new ResourceClientProfile("0" /*sessionId*/, + ResourceClientProfile profile = resourceClientProfile("0" /*sessionId*/, TvInputService.PRIORITY_HINT_USE_CASE_TYPE_PLAYBACK); int[] clientId = new int[1]; mTunerResourceManagerService.registerClientProfileInternal( @@ -273,22 +278,22 @@ public class TunerResourceManagerServiceTest { // Init frontend resources. TunerFrontendInfo[] infos = new TunerFrontendInfo[3]; - infos[0] = new TunerFrontendInfo( + infos[0] = tunerFrontendInfo( 0 /*handle*/, FrontendSettings.TYPE_DVBT, 0 /*exclusiveGroupId*/); - infos[1] = new TunerFrontendInfo( + infos[1] = tunerFrontendInfo( 1 /*handle*/, FrontendSettings.TYPE_DVBT, 1 /*exclusiveGroupId*/); - infos[2] = new TunerFrontendInfo( + infos[2] = tunerFrontendInfo( 2 /*handle*/, FrontendSettings.TYPE_DVBS, 1 /*exclusiveGroupId*/); mTunerResourceManagerService.setFrontendInfoListInternal(infos); TunerFrontendRequest request = - new TunerFrontendRequest(clientId[0] /*clientId*/, FrontendSettings.TYPE_DVBT); + tunerFrontendRequest(clientId[0] /*clientId*/, FrontendSettings.TYPE_DVBT); int[] frontendHandle = new int[1]; assertThat(mTunerResourceManagerService .requestFrontendInternal(request, frontendHandle)).isTrue(); @@ -297,9 +302,9 @@ public class TunerResourceManagerServiceTest { @Test public void requestFrontendTest_FrontendWithExclusiveGroupAvailable() { - ResourceClientProfile profile0 = new ResourceClientProfile("0" /*sessionId*/, + ResourceClientProfile profile0 = resourceClientProfile("0" /*sessionId*/, TvInputService.PRIORITY_HINT_USE_CASE_TYPE_PLAYBACK); - ResourceClientProfile profile1 = new ResourceClientProfile("1" /*sessionId*/, + ResourceClientProfile profile1 = resourceClientProfile("1" /*sessionId*/, TvInputService.PRIORITY_HINT_USE_CASE_TYPE_PLAYBACK); int[] clientId0 = new int[1]; int[] clientId1 = new int[1]; @@ -312,15 +317,15 @@ public class TunerResourceManagerServiceTest { // Init frontend resources. TunerFrontendInfo[] infos = new TunerFrontendInfo[3]; - infos[0] = new TunerFrontendInfo( + infos[0] = tunerFrontendInfo( 0 /*handle*/, FrontendSettings.TYPE_DVBT, 0 /*exclusiveGroupId*/); - infos[1] = new TunerFrontendInfo( + infos[1] = tunerFrontendInfo( 1 /*handle*/, FrontendSettings.TYPE_DVBT, 1 /*exclusiveGroupId*/); - infos[2] = new TunerFrontendInfo( + infos[2] = tunerFrontendInfo( 2 /*handle*/, FrontendSettings.TYPE_DVBS, 1 /*exclusiveGroupId*/); @@ -328,19 +333,19 @@ public class TunerResourceManagerServiceTest { int[] frontendHandle = new int[1]; TunerFrontendRequest request = - new TunerFrontendRequest(clientId1[0] /*clientId*/, FrontendSettings.TYPE_DVBT); + tunerFrontendRequest(clientId1[0] /*clientId*/, FrontendSettings.TYPE_DVBT); assertThat(mTunerResourceManagerService .requestFrontendInternal(request, frontendHandle)).isTrue(); - assertThat(frontendHandle[0]).isEqualTo(infos[0].getHandle()); + assertThat(frontendHandle[0]).isEqualTo(infos[0].handle); request = - new TunerFrontendRequest(clientId0[0] /*clientId*/, FrontendSettings.TYPE_DVBT); + tunerFrontendRequest(clientId0[0] /*clientId*/, FrontendSettings.TYPE_DVBT); assertThat(mTunerResourceManagerService .requestFrontendInternal(request, frontendHandle)).isTrue(); - assertThat(frontendHandle[0]).isEqualTo(infos[1].getHandle()); - assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].getHandle()).isInUse()) + assertThat(frontendHandle[0]).isEqualTo(infos[1].handle); + assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].handle).isInUse()) .isTrue(); - assertThat(mTunerResourceManagerService.getFrontendResource(infos[2].getHandle()).isInUse()) + assertThat(mTunerResourceManagerService.getFrontendResource(infos[2].handle).isInUse()) .isTrue(); } @@ -348,9 +353,9 @@ public class TunerResourceManagerServiceTest { public void requestFrontendTest_NoFrontendAvailable_RequestWithLowerPriority() { // Register clients ResourceClientProfile[] profiles = new ResourceClientProfile[2]; - profiles[0] = new ResourceClientProfile("0" /*sessionId*/, + profiles[0] = resourceClientProfile("0" /*sessionId*/, TvInputService.PRIORITY_HINT_USE_CASE_TYPE_PLAYBACK); - profiles[1] = new ResourceClientProfile("1" /*sessionId*/, + profiles[1] = resourceClientProfile("1" /*sessionId*/, TvInputService.PRIORITY_HINT_USE_CASE_TYPE_PLAYBACK); int[] clientPriorities = {100, 50}; int[] clientId0 = new int[1]; @@ -371,25 +376,25 @@ public class TunerResourceManagerServiceTest { // Init frontend resources. TunerFrontendInfo[] infos = new TunerFrontendInfo[2]; infos[0] = - new TunerFrontendInfo(0 /*id*/, FrontendSettings.TYPE_DVBT, 1 /*exclusiveGroupId*/); + tunerFrontendInfo(0 /*handle*/, FrontendSettings.TYPE_DVBT, 1 /*exclusiveGroupId*/); infos[1] = - new TunerFrontendInfo(1 /*id*/, FrontendSettings.TYPE_DVBS, 1 /*exclusiveGroupId*/); + tunerFrontendInfo(1 /*handle*/, FrontendSettings.TYPE_DVBS, 1 /*exclusiveGroupId*/); mTunerResourceManagerService.setFrontendInfoListInternal(infos); TunerFrontendRequest request = - new TunerFrontendRequest(clientId0[0] /*clientId*/, FrontendSettings.TYPE_DVBT); + tunerFrontendRequest(clientId0[0] /*clientId*/, FrontendSettings.TYPE_DVBT); int[] frontendHandle = new int[1]; assertThat(mTunerResourceManagerService .requestFrontendInternal(request, frontendHandle)).isTrue(); request = - new TunerFrontendRequest(clientId1[0] /*clientId*/, FrontendSettings.TYPE_DVBT); + tunerFrontendRequest(clientId1[0] /*clientId*/, FrontendSettings.TYPE_DVBT); assertThat(mTunerResourceManagerService .requestFrontendInternal(request, frontendHandle)).isFalse(); assertThat(listener.isReclaimed()).isFalse(); request = - new TunerFrontendRequest(clientId1[0] /*clientId*/, FrontendSettings.TYPE_DVBS); + tunerFrontendRequest(clientId1[0] /*clientId*/, FrontendSettings.TYPE_DVBS); assertThat(mTunerResourceManagerService .requestFrontendInternal(request, frontendHandle)).isFalse(); assertThat(listener.isReclaimed()).isFalse(); @@ -399,9 +404,9 @@ public class TunerResourceManagerServiceTest { public void requestFrontendTest_NoFrontendAvailable_RequestWithHigherPriority() { // Register clients ResourceClientProfile[] profiles = new ResourceClientProfile[2]; - profiles[0] = new ResourceClientProfile("0" /*sessionId*/, + profiles[0] = resourceClientProfile("0" /*sessionId*/, TvInputService.PRIORITY_HINT_USE_CASE_TYPE_PLAYBACK); - profiles[1] = new ResourceClientProfile("1" /*sessionId*/, + profiles[1] = resourceClientProfile("1" /*sessionId*/, TvInputService.PRIORITY_HINT_USE_CASE_TYPE_PLAYBACK); int[] clientPriorities = {100, 500}; int[] clientId0 = new int[1]; @@ -421,33 +426,33 @@ public class TunerResourceManagerServiceTest { // Init frontend resources. TunerFrontendInfo[] infos = new TunerFrontendInfo[2]; infos[0] = - new TunerFrontendInfo(0 /*id*/, FrontendSettings.TYPE_DVBT, 1 /*exclusiveGroupId*/); + tunerFrontendInfo(0 /*handle*/, FrontendSettings.TYPE_DVBT, 1 /*exclusiveGroupId*/); infos[1] = - new TunerFrontendInfo(1 /*id*/, FrontendSettings.TYPE_DVBS, 1 /*exclusiveGroupId*/); + tunerFrontendInfo(1 /*handle*/, FrontendSettings.TYPE_DVBS, 1 /*exclusiveGroupId*/); mTunerResourceManagerService.setFrontendInfoListInternal(infos); TunerFrontendRequest request = - new TunerFrontendRequest(clientId0[0] /*clientId*/, FrontendSettings.TYPE_DVBT); + tunerFrontendRequest(clientId0[0] /*clientId*/, FrontendSettings.TYPE_DVBT); int[] frontendHandle = new int[1]; assertThat(mTunerResourceManagerService .requestFrontendInternal(request, frontendHandle)).isTrue(); - assertThat(frontendHandle[0]).isEqualTo(infos[0].getHandle()); + assertThat(frontendHandle[0]).isEqualTo(infos[0].handle); assertThat(mTunerResourceManagerService.getClientProfile(clientId0[0]) .getInUseFrontendHandles()).isEqualTo(new HashSet(Arrays.asList( - infos[0].getHandle(), infos[1].getHandle()))); + infos[0].handle, infos[1].handle))); request = - new TunerFrontendRequest(clientId1[0] /*clientId*/, FrontendSettings.TYPE_DVBS); + tunerFrontendRequest(clientId1[0] /*clientId*/, FrontendSettings.TYPE_DVBS); assertThat(mTunerResourceManagerService .requestFrontendInternal(request, frontendHandle)).isTrue(); - assertThat(frontendHandle[0]).isEqualTo(infos[1].getHandle()); - assertThat(mTunerResourceManagerService.getFrontendResource(infos[0].getHandle()) + assertThat(frontendHandle[0]).isEqualTo(infos[1].handle); + assertThat(mTunerResourceManagerService.getFrontendResource(infos[0].handle) .isInUse()).isTrue(); - assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].getHandle()) + assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].handle) .isInUse()).isTrue(); - assertThat(mTunerResourceManagerService.getFrontendResource(infos[0].getHandle()) + assertThat(mTunerResourceManagerService.getFrontendResource(infos[0].handle) .getOwnerClientId()).isEqualTo(clientId1[0]); - assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].getHandle()) + assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].handle) .getOwnerClientId()).isEqualTo(clientId1[0]); assertThat(listener.isReclaimed()).isTrue(); } @@ -456,7 +461,7 @@ public class TunerResourceManagerServiceTest { public void releaseFrontendTest_UnderTheSameExclusiveGroup() { // Register clients ResourceClientProfile[] profiles = new ResourceClientProfile[1]; - profiles[0] = new ResourceClientProfile("0" /*sessionId*/, + profiles[0] = resourceClientProfile("0" /*sessionId*/, TvInputService.PRIORITY_HINT_USE_CASE_TYPE_PLAYBACK); int[] clientId = new int[1]; TestResourcesReclaimListener listener = new TestResourcesReclaimListener(); @@ -466,19 +471,19 @@ public class TunerResourceManagerServiceTest { // Init frontend resources. TunerFrontendInfo[] infos = new TunerFrontendInfo[2]; infos[0] = - new TunerFrontendInfo(0 /*id*/, FrontendSettings.TYPE_DVBT, 1 /*exclusiveGroupId*/); + tunerFrontendInfo(0 /*handle*/, FrontendSettings.TYPE_DVBT, 1 /*exclusiveGroupId*/); infos[1] = - new TunerFrontendInfo(1 /*id*/, FrontendSettings.TYPE_DVBS, 1 /*exclusiveGroupId*/); + tunerFrontendInfo(1 /*handle*/, FrontendSettings.TYPE_DVBS, 1 /*exclusiveGroupId*/); mTunerResourceManagerService.setFrontendInfoListInternal(infos); TunerFrontendRequest request = - new TunerFrontendRequest(clientId[0] /*clientId*/, FrontendSettings.TYPE_DVBT); + tunerFrontendRequest(clientId[0] /*clientId*/, FrontendSettings.TYPE_DVBT); int[] frontendHandle = new int[1]; assertThat(mTunerResourceManagerService .requestFrontendInternal(request, frontendHandle)).isTrue(); - assertThat(frontendHandle[0]).isEqualTo(infos[0].getHandle()); + assertThat(frontendHandle[0]).isEqualTo(infos[0].handle); assertThat(mTunerResourceManagerService - .getFrontendResource(infos[1].getHandle()).isInUse()).isTrue(); + .getFrontendResource(infos[1].handle).isInUse()).isTrue(); // Release frontend mTunerResourceManagerService.releaseFrontendInternal(mTunerResourceManagerService @@ -486,7 +491,7 @@ public class TunerResourceManagerServiceTest { assertThat(mTunerResourceManagerService .getFrontendResource(frontendHandle[0]).isInUse()).isFalse(); assertThat(mTunerResourceManagerService - .getFrontendResource(infos[1].getHandle()).isInUse()).isFalse(); + .getFrontendResource(infos[1].handle).isInUse()).isFalse(); assertThat(mTunerResourceManagerService .getClientProfile(clientId[0]).getInUseFrontendHandles().size()).isEqualTo(0); } @@ -495,9 +500,9 @@ public class TunerResourceManagerServiceTest { public void requestCasTest_NoCasAvailable_RequestWithHigherPriority() { // Register clients ResourceClientProfile[] profiles = new ResourceClientProfile[2]; - profiles[0] = new ResourceClientProfile("0" /*sessionId*/, + profiles[0] = resourceClientProfile("0" /*sessionId*/, TvInputService.PRIORITY_HINT_USE_CASE_TYPE_PLAYBACK); - profiles[1] = new ResourceClientProfile("1" /*sessionId*/, + profiles[1] = resourceClientProfile("1" /*sessionId*/, TvInputService.PRIORITY_HINT_USE_CASE_TYPE_PLAYBACK); int[] clientPriorities = {100, 500}; int[] clientId0 = new int[1]; @@ -517,7 +522,7 @@ public class TunerResourceManagerServiceTest { // Init cas resources. mTunerResourceManagerService.updateCasInfoInternal(1 /*casSystemId*/, 2 /*maxSessionNum*/); - CasSessionRequest request = new CasSessionRequest(clientId0[0], 1 /*casSystemId*/); + CasSessionRequest request = casSessionRequest(clientId0[0], 1 /*casSystemId*/); int[] casSessionHandle = new int[1]; // Request for 2 cas sessions. assertThat(mTunerResourceManagerService @@ -532,7 +537,7 @@ public class TunerResourceManagerServiceTest { .getOwnerClientIds()).isEqualTo(new HashSet(Arrays.asList(clientId0[0]))); assertThat(mTunerResourceManagerService.getCasResource(1).isFullyUsed()).isTrue(); - request = new CasSessionRequest(clientId1[0], 1); + request = casSessionRequest(clientId1[0], 1); assertThat(mTunerResourceManagerService .requestCasSessionInternal(request, casSessionHandle)).isTrue(); assertThat(mTunerResourceManagerService.getResourceIdFromHandle(casSessionHandle[0])) @@ -547,11 +552,67 @@ public class TunerResourceManagerServiceTest { assertThat(listener.isReclaimed()).isTrue(); } + @Test + public void requestCiCamTest_NoCiCamAvailable_RequestWithHigherPriority() { + // Register clients + ResourceClientProfile[] profiles = new ResourceClientProfile[2]; + profiles[0] = resourceClientProfile("0" /*sessionId*/, + TvInputService.PRIORITY_HINT_USE_CASE_TYPE_PLAYBACK); + profiles[1] = 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 cicam/cas resources. + mTunerResourceManagerService.updateCasInfoInternal(1 /*casSystemId*/, 2 /*maxSessionNum*/); + + TunerCiCamRequest request = tunerCiCamRequest(clientId0[0], 1 /*ciCamId*/); + int[] ciCamHandle = new int[1]; + // Request for 2 ciCam sessions. + assertThat(mTunerResourceManagerService + .requestCiCamInternal(request, ciCamHandle)).isTrue(); + assertThat(mTunerResourceManagerService + .requestCiCamInternal(request, ciCamHandle)).isTrue(); + assertThat(mTunerResourceManagerService.getResourceIdFromHandle(ciCamHandle[0])) + .isEqualTo(1); + assertThat(mTunerResourceManagerService.getClientProfile(clientId0[0]) + .getInUseCiCamId()).isEqualTo(1); + assertThat(mTunerResourceManagerService.getCiCamResource(1) + .getOwnerClientIds()).isEqualTo(new HashSet(Arrays.asList(clientId0[0]))); + assertThat(mTunerResourceManagerService.getCiCamResource(1).isFullyUsed()).isTrue(); + + request = tunerCiCamRequest(clientId1[0], 1); + assertThat(mTunerResourceManagerService + .requestCiCamInternal(request, ciCamHandle)).isTrue(); + assertThat(mTunerResourceManagerService.getResourceIdFromHandle(ciCamHandle[0])) + .isEqualTo(1); + assertThat(mTunerResourceManagerService.getClientProfile(clientId1[0]) + .getInUseCiCamId()).isEqualTo(1); + assertThat(mTunerResourceManagerService.getClientProfile(clientId0[0]) + .getInUseCiCamId()).isEqualTo(ClientProfile.INVALID_RESOURCE_ID); + assertThat(mTunerResourceManagerService.getCiCamResource(1) + .getOwnerClientIds()).isEqualTo(new HashSet(Arrays.asList(clientId1[0]))); + assertThat(mTunerResourceManagerService.getCiCamResource(1).isFullyUsed()).isFalse(); + assertThat(listener.isReclaimed()).isTrue(); + } + @Test public void releaseCasTest() { // Register clients ResourceClientProfile[] profiles = new ResourceClientProfile[1]; - profiles[0] = new ResourceClientProfile("0" /*sessionId*/, + profiles[0] = resourceClientProfile("0" /*sessionId*/, TvInputService.PRIORITY_HINT_USE_CASE_TYPE_PLAYBACK); int[] clientId = new int[1]; TestResourcesReclaimListener listener = new TestResourcesReclaimListener(); @@ -561,7 +622,7 @@ public class TunerResourceManagerServiceTest { // Init cas resources. mTunerResourceManagerService.updateCasInfoInternal(1 /*casSystemId*/, 2 /*maxSessionNum*/); - CasSessionRequest request = new CasSessionRequest(clientId[0], 1 /*casSystemId*/); + CasSessionRequest request = casSessionRequest(clientId[0], 1 /*casSystemId*/); int[] casSessionHandle = new int[1]; // Request for 1 cas sessions. assertThat(mTunerResourceManagerService @@ -584,13 +645,50 @@ public class TunerResourceManagerServiceTest { .getOwnerClientIds()).isEmpty(); } + @Test + public void releaseCiCamTest() { + // Register clients + ResourceClientProfile[] profiles = new ResourceClientProfile[1]; + profiles[0] = 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 cas resources. + mTunerResourceManagerService.updateCasInfoInternal(1 /*casSystemId*/, 2 /*maxSessionNum*/); + + TunerCiCamRequest request = tunerCiCamRequest(clientId[0], 1 /*ciCamId*/); + int[] ciCamHandle = new int[1]; + // Request for 1 ciCam sessions. + assertThat(mTunerResourceManagerService + .requestCiCamInternal(request, ciCamHandle)).isTrue(); + assertThat(mTunerResourceManagerService.getResourceIdFromHandle(ciCamHandle[0])) + .isEqualTo(1); + assertThat(mTunerResourceManagerService.getClientProfile(clientId[0]) + .getInUseCiCamId()).isEqualTo(1); + assertThat(mTunerResourceManagerService.getCiCamResource(1) + .getOwnerClientIds()).isEqualTo(new HashSet(Arrays.asList(clientId[0]))); + assertThat(mTunerResourceManagerService.getCiCamResource(1).isFullyUsed()).isFalse(); + + // Release ciCam + mTunerResourceManagerService.releaseCiCamInternal(mTunerResourceManagerService + .getCiCamResource(1), clientId[0]); + assertThat(mTunerResourceManagerService.getClientProfile(clientId[0]) + .getInUseCiCamId()).isEqualTo(ClientProfile.INVALID_RESOURCE_ID); + assertThat(mTunerResourceManagerService.getCiCamResource(1).isFullyUsed()).isFalse(); + assertThat(mTunerResourceManagerService.getCiCamResource(1) + .getOwnerClientIds()).isEmpty(); + } + @Test public void requestLnbTest_NoLnbAvailable_RequestWithHigherPriority() { // Register clients ResourceClientProfile[] profiles = new ResourceClientProfile[2]; - profiles[0] = new ResourceClientProfile("0" /*sessionId*/, + profiles[0] = resourceClientProfile("0" /*sessionId*/, TvInputService.PRIORITY_HINT_USE_CASE_TYPE_PLAYBACK); - profiles[1] = new ResourceClientProfile("1" /*sessionId*/, + profiles[1] = resourceClientProfile("1" /*sessionId*/, TvInputService.PRIORITY_HINT_USE_CASE_TYPE_PLAYBACK); int[] clientPriorities = {100, 500}; int[] clientId0 = new int[1]; @@ -611,7 +709,8 @@ public class TunerResourceManagerServiceTest { int[] lnbHandles = {1}; mTunerResourceManagerService.setLnbInfoListInternal(lnbHandles); - TunerLnbRequest request = new TunerLnbRequest(clientId0[0]); + TunerLnbRequest request = new TunerLnbRequest(); + request.clientId = clientId0[0]; int[] lnbHandle = new int[1]; assertThat(mTunerResourceManagerService .requestLnbInternal(request, lnbHandle)).isTrue(); @@ -619,7 +718,9 @@ public class TunerResourceManagerServiceTest { assertThat(mTunerResourceManagerService.getClientProfile(clientId0[0]).getInUseLnbHandles()) .isEqualTo(new HashSet(Arrays.asList(lnbHandles[0]))); - request = new TunerLnbRequest(clientId1[0]); + request = new TunerLnbRequest(); + request.clientId = clientId1[0]; + assertThat(mTunerResourceManagerService .requestLnbInternal(request, lnbHandle)).isTrue(); assertThat(lnbHandle[0]).isEqualTo(lnbHandles[0]); @@ -636,7 +737,7 @@ public class TunerResourceManagerServiceTest { public void releaseLnbTest() { // Register clients ResourceClientProfile[] profiles = new ResourceClientProfile[1]; - profiles[0] = new ResourceClientProfile("0" /*sessionId*/, + profiles[0] = resourceClientProfile("0" /*sessionId*/, TvInputService.PRIORITY_HINT_USE_CASE_TYPE_PLAYBACK); int[] clientId = new int[1]; TestResourcesReclaimListener listener = new TestResourcesReclaimListener(); @@ -647,7 +748,8 @@ public class TunerResourceManagerServiceTest { int[] lnbHandles = {0}; mTunerResourceManagerService.setLnbInfoListInternal(lnbHandles); - TunerLnbRequest request = new TunerLnbRequest(clientId[0]); + TunerLnbRequest request = new TunerLnbRequest(); + request.clientId = clientId[0]; int[] lnbHandle = new int[1]; assertThat(mTunerResourceManagerService .requestLnbInternal(request, lnbHandle)).isTrue(); @@ -665,7 +767,7 @@ public class TunerResourceManagerServiceTest { @Test public void unregisterClientTest_usingFrontend() { // Register client - ResourceClientProfile profile = new ResourceClientProfile("0" /*sessionId*/, + ResourceClientProfile profile = resourceClientProfile("0" /*sessionId*/, TvInputService.PRIORITY_HINT_USE_CASE_TYPE_PLAYBACK); int[] clientId = new int[1]; mTunerResourceManagerService.registerClientProfileInternal( @@ -675,27 +777,27 @@ public class TunerResourceManagerServiceTest { // Init frontend resources. TunerFrontendInfo[] infos = new TunerFrontendInfo[2]; infos[0] = - new TunerFrontendInfo(0 /*id*/, FrontendSettings.TYPE_DVBT, 1 /*exclusiveGroupId*/); + tunerFrontendInfo(0 /*handle*/, FrontendSettings.TYPE_DVBT, 1 /*exclusiveGroupId*/); infos[1] = - new TunerFrontendInfo(1 /*id*/, FrontendSettings.TYPE_DVBS, 1 /*exclusiveGroupId*/); + tunerFrontendInfo(1 /*handle*/, FrontendSettings.TYPE_DVBS, 1 /*exclusiveGroupId*/); mTunerResourceManagerService.setFrontendInfoListInternal(infos); TunerFrontendRequest request = - new TunerFrontendRequest(clientId[0] /*clientId*/, FrontendSettings.TYPE_DVBT); + tunerFrontendRequest(clientId[0] /*clientId*/, FrontendSettings.TYPE_DVBT); int[] frontendHandle = new int[1]; assertThat(mTunerResourceManagerService .requestFrontendInternal(request, frontendHandle)).isTrue(); - assertThat(frontendHandle[0]).isEqualTo(infos[0].getHandle()); - assertThat(mTunerResourceManagerService.getFrontendResource(infos[0].getHandle()) + assertThat(frontendHandle[0]).isEqualTo(infos[0].handle); + assertThat(mTunerResourceManagerService.getFrontendResource(infos[0].handle) .isInUse()).isTrue(); - assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].getHandle()) + assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].handle) .isInUse()).isTrue(); // Unregister client when using frontend mTunerResourceManagerService.unregisterClientProfileInternal(clientId[0]); - assertThat(mTunerResourceManagerService.getFrontendResource(infos[0].getHandle()) + assertThat(mTunerResourceManagerService.getFrontendResource(infos[0].handle) .isInUse()).isFalse(); - assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].getHandle()) + assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].handle) .isInUse()).isFalse(); assertThat(mTunerResourceManagerService.checkClientExists(clientId[0])).isFalse(); @@ -704,7 +806,7 @@ public class TunerResourceManagerServiceTest { @Test public void requestDemuxTest() { // Register client - ResourceClientProfile profile = new ResourceClientProfile("0" /*sessionId*/, + ResourceClientProfile profile = resourceClientProfile("0" /*sessionId*/, TvInputService.PRIORITY_HINT_USE_CASE_TYPE_PLAYBACK); int[] clientId = new int[1]; mTunerResourceManagerService.registerClientProfileInternal( @@ -712,7 +814,8 @@ public class TunerResourceManagerServiceTest { assertThat(clientId[0]).isNotEqualTo(TunerResourceManagerService.INVALID_CLIENT_ID); int[] demuxHandle = new int[1]; - TunerDemuxRequest request = new TunerDemuxRequest(clientId[0]); + TunerDemuxRequest request = new TunerDemuxRequest(); + request.clientId = clientId[0]; assertThat(mTunerResourceManagerService.requestDemuxInternal(request, demuxHandle)) .isTrue(); assertThat(mTunerResourceManagerService.getResourceIdFromHandle(demuxHandle[0])) @@ -722,7 +825,7 @@ public class TunerResourceManagerServiceTest { @Test public void requestDescramblerTest() { // Register client - ResourceClientProfile profile = new ResourceClientProfile("0" /*sessionId*/, + ResourceClientProfile profile = resourceClientProfile("0" /*sessionId*/, TvInputService.PRIORITY_HINT_USE_CASE_TYPE_PLAYBACK); int[] clientId = new int[1]; mTunerResourceManagerService.registerClientProfileInternal( @@ -730,7 +833,8 @@ public class TunerResourceManagerServiceTest { assertThat(clientId[0]).isNotEqualTo(TunerResourceManagerService.INVALID_CLIENT_ID); int[] desHandle = new int[1]; - TunerDescramblerRequest request = new TunerDescramblerRequest(clientId[0]); + TunerDescramblerRequest request = new TunerDescramblerRequest(); + request.clientId = clientId[0]; assertThat(mTunerResourceManagerService.requestDescramblerInternal(request, desHandle)) .isTrue(); assertThat(mTunerResourceManagerService.getResourceIdFromHandle(desHandle[0])).isEqualTo(0); @@ -740,15 +844,15 @@ public class TunerResourceManagerServiceTest { public void isHigherPriorityTest() { mIsForeground = false; ResourceClientProfile backgroundPlaybackProfile = - new ResourceClientProfile(null /*sessionId*/, + resourceClientProfile(null /*sessionId*/, TvInputService.PRIORITY_HINT_USE_CASE_TYPE_PLAYBACK); ResourceClientProfile backgroundRecordProfile = - new ResourceClientProfile(null /*sessionId*/, + resourceClientProfile(null /*sessionId*/, TvInputService.PRIORITY_HINT_USE_CASE_TYPE_RECORD); int backgroundPlaybackPriority = mTunerResourceManagerService.getClientPriority( - TvInputService.PRIORITY_HINT_USE_CASE_TYPE_PLAYBACK, 0); + TvInputService.PRIORITY_HINT_USE_CASE_TYPE_PLAYBACK, mIsForeground); int backgroundRecordPriority = mTunerResourceManagerService.getClientPriority( - TvInputService.PRIORITY_HINT_USE_CASE_TYPE_RECORD, 0); + TvInputService.PRIORITY_HINT_USE_CASE_TYPE_RECORD, mIsForeground); assertThat(mTunerResourceManagerService.isHigherPriorityInternal(backgroundPlaybackProfile, backgroundRecordProfile)).isEqualTo( (backgroundPlaybackPriority > backgroundRecordPriority)); @@ -767,16 +871,16 @@ public class TunerResourceManagerServiceTest { // Predefined client profiles ResourceClientProfile[] ownerProfiles = new ResourceClientProfile[2]; ResourceClientProfile[] shareProfiles = new ResourceClientProfile[2]; - ownerProfiles[0] = new ResourceClientProfile( + ownerProfiles[0] = resourceClientProfile( "0" /*sessionId*/, TvInputService.PRIORITY_HINT_USE_CASE_TYPE_LIVE); - ownerProfiles[1] = new ResourceClientProfile( + ownerProfiles[1] = resourceClientProfile( "1" /*sessionId*/, TvInputService.PRIORITY_HINT_USE_CASE_TYPE_LIVE); - shareProfiles[0] = new ResourceClientProfile( + shareProfiles[0] = resourceClientProfile( "2" /*sessionId*/, TvInputService.PRIORITY_HINT_USE_CASE_TYPE_RECORD); - shareProfiles[1] = new ResourceClientProfile( + shareProfiles[1] = resourceClientProfile( "3" /*sessionId*/, TvInputService.PRIORITY_HINT_USE_CASE_TYPE_RECORD); @@ -828,12 +932,12 @@ public class TunerResourceManagerServiceTest { // Predefined frontend info TunerFrontendInfo[] infos = new TunerFrontendInfo[2]; - infos[0] = new TunerFrontendInfo( - 0 /*id*/, + infos[0] = tunerFrontendInfo( + 0 /*handle*/, FrontendSettings.TYPE_DVBT, 1 /*exclusiveGroupId*/); - infos[1] = new TunerFrontendInfo( - 1 /*id*/, + infos[1] = tunerFrontendInfo( + 1 /*handle*/, FrontendSettings.TYPE_DVBS, 1 /*exclusiveGroupId*/); @@ -848,7 +952,7 @@ public class TunerResourceManagerServiceTest { // Predefined frontend request and array to save returned frontend handle int[] frontendHandle = new int[1]; - TunerFrontendRequest request = new TunerFrontendRequest( + TunerFrontendRequest request = tunerFrontendRequest( ownerClientId0[0] /*clientId*/, FrontendSettings.TYPE_DVBT); @@ -856,13 +960,13 @@ public class TunerResourceManagerServiceTest { assertThat(mTunerResourceManagerService .requestFrontendInternal(request, frontendHandle)) .isTrue(); - assertThat(frontendHandle[0]).isEqualTo(infos[0].getHandle()); + assertThat(frontendHandle[0]).isEqualTo(infos[0].handle); assertThat(mTunerResourceManagerService .getClientProfile(ownerClientId0[0]) .getInUseFrontendHandles()) .isEqualTo(new HashSet(Arrays.asList( - infos[0].getHandle(), - infos[1].getHandle()))); + infos[0].handle, + infos[1].handle))); /**** Share Frontend ****/ @@ -874,14 +978,14 @@ public class TunerResourceManagerServiceTest { shareClientId1[0]/*selfClientId*/, ownerClientId0[0]/*targetClientId*/); // Verify fe in use status - assertThat(mTunerResourceManagerService.getFrontendResource(infos[0].getHandle()) + assertThat(mTunerResourceManagerService.getFrontendResource(infos[0].handle) .isInUse()).isTrue(); - assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].getHandle()) + assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].handle) .isInUse()).isTrue(); // Verify fe owner status - assertThat(mTunerResourceManagerService.getFrontendResource(infos[0].getHandle()) + assertThat(mTunerResourceManagerService.getFrontendResource(infos[0].handle) .getOwnerClientId()).isEqualTo(ownerClientId0[0]); - assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].getHandle()) + assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].handle) .getOwnerClientId()).isEqualTo(ownerClientId0[0]); // Verify share fe client status in the primary owner client assertThat(mTunerResourceManagerService.getClientProfile(ownerClientId0[0]) @@ -894,20 +998,20 @@ public class TunerResourceManagerServiceTest { .getClientProfile(ownerClientId0[0]) .getInUseFrontendHandles()) .isEqualTo(new HashSet(Arrays.asList( - infos[0].getHandle(), - infos[1].getHandle()))); + infos[0].handle, + infos[1].handle))); assertThat(mTunerResourceManagerService .getClientProfile(shareClientId0[0]) .getInUseFrontendHandles()) .isEqualTo(new HashSet(Arrays.asList( - infos[0].getHandle(), - infos[1].getHandle()))); + infos[0].handle, + infos[1].handle))); assertThat(mTunerResourceManagerService .getClientProfile(shareClientId1[0]) .getInUseFrontendHandles()) .isEqualTo(new HashSet(Arrays.asList( - infos[0].getHandle(), - infos[1].getHandle()))); + infos[0].handle, + infos[1].handle))); /**** Remove Frontend Share Owner ****/ @@ -923,19 +1027,19 @@ public class TunerResourceManagerServiceTest { .getClientProfile(ownerClientId0[0]) .getInUseFrontendHandles()) .isEqualTo(new HashSet(Arrays.asList( - infos[0].getHandle(), - infos[1].getHandle()))); + infos[0].handle, + infos[1].handle))); assertThat(mTunerResourceManagerService .getClientProfile(shareClientId0[0]) .getInUseFrontendHandles()) .isEqualTo(new HashSet(Arrays.asList( - infos[0].getHandle(), - infos[1].getHandle()))); + infos[0].handle, + infos[1].handle))); /**** Request Shared Frontend with Higher Priority Client ****/ // Predefined second frontend request - request = new TunerFrontendRequest( + request = tunerFrontendRequest( ownerClientId1[0] /*clientId*/, FrontendSettings.TYPE_DVBT); @@ -945,17 +1049,17 @@ public class TunerResourceManagerServiceTest { .isTrue(); // Validate granted resource and internal mapping - assertThat(frontendHandle[0]).isEqualTo(infos[0].getHandle()); - assertThat(mTunerResourceManagerService.getFrontendResource(infos[0].getHandle()) + assertThat(frontendHandle[0]).isEqualTo(infos[0].handle); + assertThat(mTunerResourceManagerService.getFrontendResource(infos[0].handle) .getOwnerClientId()).isEqualTo(ownerClientId1[0]); - assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].getHandle()) + assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].handle) .getOwnerClientId()).isEqualTo(ownerClientId1[0]); assertThat(mTunerResourceManagerService .getClientProfile(ownerClientId1[0]) .getInUseFrontendHandles()) .isEqualTo(new HashSet(Arrays.asList( - infos[0].getHandle(), - infos[1].getHandle()))); + infos[0].handle, + infos[1].handle))); assertThat(mTunerResourceManagerService .getClientProfile(ownerClientId0[0]) .getInUseFrontendHandles() @@ -983,12 +1087,12 @@ public class TunerResourceManagerServiceTest { // Release the frontend resource from the primary owner mTunerResourceManagerService.releaseFrontendInternal(mTunerResourceManagerService - .getFrontendResource(infos[0].getHandle()), ownerClientId1[0]); + .getFrontendResource(infos[0].handle), ownerClientId1[0]); // Validate the internal mapping - assertThat(mTunerResourceManagerService.getFrontendResource(infos[0].getHandle()) + assertThat(mTunerResourceManagerService.getFrontendResource(infos[0].handle) .isInUse()).isFalse(); - assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].getHandle()) + assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].handle) .isInUse()).isFalse(); // Verify client status assertThat(mTunerResourceManagerService @@ -1010,7 +1114,8 @@ public class TunerResourceManagerServiceTest { /**** Unregister Primary Owner when the Share owner owns an Lnb ****/ // Predefined Lnb request and handle array - TunerLnbRequest requestLnb = new TunerLnbRequest(shareClientId0[0]); + TunerLnbRequest requestLnb = new TunerLnbRequest(); + requestLnb.clientId = shareClientId0[0]; int[] lnbHandle = new int[1]; // Request for an Lnb @@ -1030,9 +1135,9 @@ public class TunerResourceManagerServiceTest { mTunerResourceManagerService.unregisterClientProfileInternal(ownerClientId1[0]); // Validate the internal mapping - assertThat(mTunerResourceManagerService.getFrontendResource(infos[0].getHandle()) + assertThat(mTunerResourceManagerService.getFrontendResource(infos[0].handle) .isInUse()).isFalse(); - assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].getHandle()) + assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].handle) .isInUse()).isFalse(); // Verify client status assertThat(mTunerResourceManagerService @@ -1046,4 +1151,41 @@ public class TunerResourceManagerServiceTest { .isEqualTo(new HashSet(Arrays.asList( lnbHandles[0]))); } + + private TunerFrontendInfo tunerFrontendInfo( + int handle, int frontendType, int exclusiveGroupId) { + TunerFrontendInfo info = new TunerFrontendInfo(); + info.handle = handle; + info.frontendType = frontendType; + info.exclusiveGroupId = exclusiveGroupId; + return info; + } + + private TunerFrontendRequest tunerFrontendRequest(int clientId, int frontendType) { + TunerFrontendRequest request = new TunerFrontendRequest(); + request.clientId = clientId; + request.frontendType = frontendType; + return request; + } + + private ResourceClientProfile resourceClientProfile(String sessionId, int useCase) { + ResourceClientProfile profile = new ResourceClientProfile(); + profile.tvInputSessionId = sessionId; + profile.useCase = useCase; + return profile; + } + + private CasSessionRequest casSessionRequest(int clientId, int casSystemId) { + CasSessionRequest request = new CasSessionRequest(); + request.clientId = clientId; + request.casSystemId = casSystemId; + return request; + } + + private TunerCiCamRequest tunerCiCamRequest(int clientId, int ciCamId) { + TunerCiCamRequest request = new TunerCiCamRequest(); + request.clientId = clientId; + request.ciCamId = ciCamId; + return request; + } }