1 /*
2  * Copyright 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.media.tv.tunerresourcemanager;
18 
19 import android.annotation.CallbackExecutor;
20 import android.annotation.IntDef;
21 import android.annotation.NonNull;
22 import android.annotation.Nullable;
23 import android.annotation.RequiresFeature;
24 import android.annotation.SuppressLint;
25 import android.annotation.SystemService;
26 import android.annotation.TestApi;
27 import android.content.Context;
28 import android.content.pm.PackageManager;
29 import android.media.tv.TvInputService;
30 import android.os.Binder;
31 import android.os.RemoteException;
32 import android.util.Log;
33 
34 import java.lang.annotation.Retention;
35 import java.lang.annotation.RetentionPolicy;
36 import java.util.concurrent.Executor;
37 
38 /**
39  * Interface of the Tuner Resource Manager(TRM). It manages resources used by TV Tuners.
40  * <p>Resources include:
41  * <ul>
42  * <li>TunerFrontend {@link android.media.tv.tuner.frontend}.
43  * <li>TunerLnb {@link android.media.tv.tuner.Lnb}.
44  * <li>MediaCas {@link android.media.MediaCas}.
45  * <ul>
46  *
47  * <p>Expected workflow is:
48  * <ul>
49  * <li>Tuner Java/MediaCas/TIF update resources of the current device with TRM.
50  * <li>Client registers its profile through {@link #registerClientProfile(ResourceClientProfile,
51  * Executor, ResourcesReclaimListener, int[])}.
52  * <li>Client requests resources through request APIs.
53  * <li>If the resource needs to be handed to a higher priority client from a lower priority
54  * one, TRM calls IResourcesReclaimListener registered by the lower priority client to release
55  * the resource.
56  * <ul>
57  *
58  * <p>TRM also exposes its priority comparison algorithm as a helping method to other services.
59  * {@see #isHigherPriority(ResourceClientProfile, ResourceClientProfile)}.
60  *
61  * @hide
62  */
63 @RequiresFeature(PackageManager.FEATURE_LIVE_TV)
64 @SystemService(Context.TV_TUNER_RESOURCE_MGR_SERVICE)
65 public class TunerResourceManager {
66     private static final String TAG = "TunerResourceManager";
67     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
68 
69     public static final int INVALID_RESOURCE_HANDLE = -1;
70     public static final int INVALID_OWNER_ID = -1;
71     /**
72      * Tuner resource type to help generate resource handle
73      */
74     @IntDef({
75         TUNER_RESOURCE_TYPE_FRONTEND,
76         TUNER_RESOURCE_TYPE_DEMUX,
77         TUNER_RESOURCE_TYPE_DESCRAMBLER,
78         TUNER_RESOURCE_TYPE_LNB,
79         TUNER_RESOURCE_TYPE_CAS_SESSION,
80         TUNER_RESOURCE_TYPE_FRONTEND_CICAM,
81         TUNER_RESOURCE_TYPE_MAX,
82      })
83     @Retention(RetentionPolicy.SOURCE)
84     public @interface TunerResourceType {}
85 
86     public static final int TUNER_RESOURCE_TYPE_FRONTEND = 0;
87     public static final int TUNER_RESOURCE_TYPE_DEMUX = 1;
88     public static final int TUNER_RESOURCE_TYPE_DESCRAMBLER = 2;
89     public static final int TUNER_RESOURCE_TYPE_LNB = 3;
90     public static final int TUNER_RESOURCE_TYPE_CAS_SESSION = 4;
91     public static final int TUNER_RESOURCE_TYPE_FRONTEND_CICAM = 5;
92     public static final int TUNER_RESOURCE_TYPE_MAX = 6;
93 
94     private final ITunerResourceManager mService;
95     private final int mUserId;
96 
97     /**
98      * @hide
99      */
TunerResourceManager(ITunerResourceManager service, int userId)100     public TunerResourceManager(ITunerResourceManager service, int userId) {
101         mService = service;
102         mUserId = userId;
103     }
104 
105     /**
106      * This API is used by the client to register their profile with the Tuner Resource manager.
107      *
108      * <p>The profile contains information that can show the base priority score of the client.
109      *
110      * @param profile {@link ResourceClientProfile} profile of the current client. Undefined use
111      *                case would cause IllegalArgumentException.
112      * @param executor the executor on which the listener would be invoked.
113      * @param listener {@link ResourcesReclaimListener} callback to reclaim clients' resources when
114      *                 needed.
115      * @param clientId returned a clientId from the resource manager when the
116      *                 the client registeres.
117      * @throws IllegalArgumentException when {@code profile} contains undefined use case.
118      */
registerClientProfile(@onNull ResourceClientProfile profile, @NonNull @CallbackExecutor Executor executor, @NonNull ResourcesReclaimListener listener, @NonNull int[] clientId)119     public void registerClientProfile(@NonNull ResourceClientProfile profile,
120                         @NonNull @CallbackExecutor Executor executor,
121                         @NonNull ResourcesReclaimListener listener,
122                         @NonNull int[] clientId) {
123         // TODO: throw new IllegalArgumentException("Unknown client use case")
124         // when the use case is not defined.
125         try {
126             mService.registerClientProfile(profile,
127                     new IResourcesReclaimListener.Stub() {
128                     @Override
129                 public void onReclaimResources() {
130                         final long identity = Binder.clearCallingIdentity();
131                         try {
132                             executor.execute(() -> listener.onReclaimResources());
133                         } finally {
134                             Binder.restoreCallingIdentity(identity);
135                         }
136                     }
137                 }, clientId);
138         } catch (RemoteException e) {
139             throw e.rethrowFromSystemServer();
140         }
141     }
142 
143     /**
144      * This API is used by the client to unregister their profile with the
145      * Tuner Resource manager.
146      *
147      * @param clientId the client id that needs to be unregistered.
148      */
unregisterClientProfile(int clientId)149     public void unregisterClientProfile(int clientId) {
150         try {
151             mService.unregisterClientProfile(clientId);
152         } catch (RemoteException e) {
153             throw e.rethrowFromSystemServer();
154         }
155     }
156 
157     /**
158      * This API is used by client to update its registered {@link ResourceClientProfile}.
159      *
160      * <p>We recommend creating a new tuner instance for different use cases instead of using this
161      * API since different use cases may need different resources.
162      *
163      * <p>If TIS updates use case, it needs to ensure underneath resources are exchangeable between
164      * two different use cases.
165      *
166      * <p>Only the arbitrary priority and niceValue are allowed to be updated.
167      *
168      * @param clientId the id of the client that is updating its profile.
169      * @param priority the priority that the client would like to update to.
170      * @param niceValue the nice value that the client would like to update to.
171      *
172      * @return true if the update is successful.
173      */
updateClientPriority(int clientId, int priority, int niceValue)174     public boolean updateClientPriority(int clientId, int priority, int niceValue) {
175         boolean result = false;
176         try {
177             result = mService.updateClientPriority(clientId, priority, niceValue);
178         } catch (RemoteException e) {
179             throw e.rethrowFromSystemServer();
180         }
181         return result;
182     }
183 
184     /**
185      * Checks if there is an unused frontend resource available.
186      *
187      * @param frontendType The frontend type for the query to be done for.
188      */
hasUnusedFrontend(int frontendType)189     public boolean hasUnusedFrontend(int frontendType) {
190         boolean result = false;
191         try {
192             result = mService.hasUnusedFrontend(frontendType);
193         } catch (RemoteException e) {
194             throw e.rethrowFromSystemServer();
195         }
196         return result;
197     }
198 
199     /**
200      * Checks if the client has the lowest priority among the clients that are holding
201      * the frontend resource of the specified type.
202      *
203      * <p> When this function returns false, it means that there is at least one client with the
204      * strictly lower priority (than clientId) that is reclaimable by the system.
205      *
206      * @param clientId The client ID to be checked the priority for.
207      * @param frontendType The specific frontend type to be checked for.
208      *
209      * @return false if there is another client holding the frontend resource of the specified type
210      * that can be reclaimed. Otherwise true.
211      */
isLowestPriority(int clientId, int frontendType)212     public boolean isLowestPriority(int clientId, int frontendType) {
213         boolean result = false;
214         try {
215             result = mService.isLowestPriority(clientId, frontendType);
216         } catch (RemoteException e) {
217             throw e.rethrowFromSystemServer();
218         }
219         return result;
220     }
221 
222     /**
223      * Stores the frontend resource map if it was stored before.
224      *
225      * <p>This API is only for testing purpose and should be used in pair with
226      * restoreResourceMap(), which allows testing of {@link Tuner} APIs
227      * that behave differently based on different sets of resource map.
228      *
229      * @param resourceType The resource type to store the map for.
230      */
storeResourceMap(int resourceType)231     public void storeResourceMap(int resourceType) {
232         try {
233             mService.storeResourceMap(resourceType);
234         } catch (RemoteException e) {
235             throw e.rethrowFromSystemServer();
236         }
237     }
238 
239     /**
240      * Clears the frontend resource map.
241      *
242      * <p>This API is only for testing purpose and should be called right after
243      * storeResourceMap(), so TRMService#removeFrontendResource() does not
244      * get called in TRMService#setFrontendInfoListInternal() for custom frontend
245      * resource map creation.
246      *
247      * @param resourceType The resource type to clear the map for.
248      */
clearResourceMap(int resourceType)249     public void clearResourceMap(int resourceType) {
250         try {
251             mService.clearResourceMap(resourceType);
252         } catch (RemoteException e) {
253             throw e.rethrowFromSystemServer();
254         }
255     }
256 
257     /**
258      * Restores Frontend resource map for the later restore.
259      *
260      * <p>This API is only for testing purpose and should be used in pair with
261      * storeResourceMap(), which allows testing of {@link Tuner} APIs
262      * that behave differently based on different sets of resource map.
263      *
264      * @param resourceType The resource type to restore the map for.
265      */
restoreResourceMap(int resourceType)266     public void restoreResourceMap(int resourceType) {
267         try {
268             mService.restoreResourceMap(resourceType);
269         } catch (RemoteException e) {
270             throw e.rethrowFromSystemServer();
271         }
272     }
273 
274     /**
275      * Updates the current TRM of the TunerHAL Frontend information.
276      *
277      * <p><strong>Note:</strong> This update must happen before the first
278      * {@link #requestFrontend(TunerFrontendRequest, int[])} and
279      * {@link #releaseFrontend(int, int)} call.
280      *
281      * @param infos an array of the available {@link TunerFrontendInfo} information.
282      */
setFrontendInfoList(@onNull TunerFrontendInfo[] infos)283     public void setFrontendInfoList(@NonNull TunerFrontendInfo[] infos) {
284         try {
285             mService.setFrontendInfoList(infos);
286         } catch (RemoteException e) {
287             throw e.rethrowFromSystemServer();
288         }
289     }
290 
291     /**
292      * Updates the current TRM of the TunerHAL Demux information.
293      *
294      * <p><strong>Note:</strong> This update must happen before the first
295      * {@link #requestDemux(TunerDemuxRequest, int[])} and
296      * {@link #releaseDemux(int, int)} call.
297      *
298      * @param infos an array of the available {@link TunerDemuxInfo} information.
299      */
setDemuxInfoList(@onNull TunerDemuxInfo[] infos)300     public void setDemuxInfoList(@NonNull TunerDemuxInfo[] infos) {
301         try {
302             mService.setDemuxInfoList(infos);
303         } catch (RemoteException e) {
304             throw e.rethrowFromSystemServer();
305         }
306     }
307 
308     /**
309      * Updates the TRM of the current CAS information.
310      *
311      * <p><strong>Note:</strong> This update must happen before the first
312      * {@link #requestCasSession(CasSessionRequest, int[])} and {@link #releaseCasSession(int, int)}
313      * call.
314      *
315      * @param casSystemId id of the updating CAS system.
316      * @param maxSessionNum the max session number of the CAS system that is updated.
317      */
updateCasInfo(int casSystemId, int maxSessionNum)318     public void updateCasInfo(int casSystemId, int maxSessionNum) {
319         try {
320             mService.updateCasInfo(casSystemId, maxSessionNum);
321         } catch (RemoteException e) {
322             throw e.rethrowFromSystemServer();
323         }
324     }
325 
326     /**
327      * Updates the TRM of the current Lnb information.
328      *
329      * <p><strong>Note:</strong> This update must happen before the first
330      * {@link #requestLnb(TunerLnbRequest, int[])} and {@link #releaseLnb(int, int)} call.
331      *
332      * @param lnbIds ids of the updating lnbs.
333      */
setLnbInfoList(int[] lnbIds)334     public void setLnbInfoList(int[] lnbIds) {
335         try {
336             mService.setLnbInfoList(lnbIds);
337         } catch (RemoteException e) {
338             throw e.rethrowFromSystemServer();
339         }
340     }
341 
342     /**
343      * Grants the lock to the caller for public {@link Tuner} APIs
344      *
345      * <p>{@link Tuner} functions that call both [@link TunerResourceManager} APIs and
346      * grabs lock that are also used in {@link IResourcesReclaimListener#onReclaimResources()}
347      * must call this API before acquiring lock used in onReclaimResources().
348      *
349      * <p>This API will block until it releases the lock or fails
350      *
351      * @param clientId The ID of the caller.
352      *
353      * @return true if the lock is granted. If false is returned, calling this API again is not
354      * guaranteed to work and may be unrecoverrable. (This should not happen.)
355      */
acquireLock(int clientId)356     public boolean acquireLock(int clientId) {
357         try {
358             return mService.acquireLock(clientId, Thread.currentThread().getId());
359         } catch (RemoteException e) {
360             throw e.rethrowFromSystemServer();
361         }
362     }
363 
364     /**
365      * Releases the lock to the caller for public {@link Tuner} APIs
366      *
367      * <p>This API must be called in pair with {@link #acquireLock(int, int)}
368      *
369      * <p>This API will block until it releases the lock or fails
370      *
371      * @param clientId The ID of the caller.
372      *
373      * @return true if the lock is granted. If false is returned, calling this API again is not
374      * guaranteed to work and may be unrecoverrable. (This should not happen.)
375      */
releaseLock(int clientId)376     public boolean releaseLock(int clientId) {
377         try {
378             return mService.releaseLock(clientId);
379         } catch (RemoteException e) {
380             throw e.rethrowFromSystemServer();
381         }
382     }
383 
384     /**
385      * Requests a frontend resource.
386      *
387      * <p>There are three possible scenarios:
388      * <ul>
389      * <li>If there is frontend available, the API would send the id back.
390      *
391      * <li>If no Frontend is available but the current request info can show higher priority than
392      * other uses of Frontend, the API will send
393      * {@link IResourcesReclaimListener#onReclaimResources()} to the {@link Tuner}. Tuner would
394      * handle the resource reclaim on the holder of lower priority and notify the holder of its
395      * resource loss.
396      *
397      * <li>If no frontend can be granted, the API would return false.
398      * <ul>
399      *
400      * <p><strong>Note:</strong> {@link #setFrontendInfoList(TunerFrontendInfo[])} must be called
401      * before this request.
402      *
403      * @param request {@link TunerFrontendRequest} information of the current request.
404      * @param frontendHandle a one-element array to return the granted frontendHandle. If
405      *                       no frontend granted, this will return {@link #INVALID_RESOURCE_HANDLE}.
406      *
407      * @return true if there is frontend granted.
408      */
requestFrontend(@onNull TunerFrontendRequest request, @Nullable int[] frontendHandle)409     public boolean requestFrontend(@NonNull TunerFrontendRequest request,
410                 @Nullable int[] frontendHandle) {
411         boolean result = false;
412         try {
413             result = mService.requestFrontend(request, frontendHandle);
414         } catch (RemoteException e) {
415             throw e.rethrowFromSystemServer();
416         }
417         return result;
418     }
419 
420     /**
421      * Sets the maximum usable frontends number of a given frontend type. It is used to enable or
422      * disable frontends when cable connection status is changed by user.
423      *
424      * @param frontendType the frontendType which the maximum usable number will be set for.
425      * @param maxNum the new maximum usable number.
426      *
427      * @return true if  successful and false otherwise.
428      */
setMaxNumberOfFrontends(int frontendType, int maxNum)429     public boolean setMaxNumberOfFrontends(int frontendType, int maxNum) {
430         boolean result = false;
431         try {
432             result = mService.setMaxNumberOfFrontends(frontendType, maxNum);
433         } catch (RemoteException e) {
434             throw e.rethrowFromSystemServer();
435         }
436         return result;
437     }
438 
439     /**
440      * Get the maximum usable frontends number of a given frontend type.
441      *
442      * @param frontendType the frontendType which the maximum usable number will be queried for.
443      *
444      * @return the maximum usable number of the queried frontend type. Returns -1 when the
445      *         frontendType is invalid
446      */
getMaxNumberOfFrontends(int frontendType)447     public int getMaxNumberOfFrontends(int frontendType) {
448         int result = -1;
449         try {
450             result = mService.getMaxNumberOfFrontends(frontendType);
451         } catch (RemoteException e) {
452             throw e.rethrowFromSystemServer();
453         }
454         return result;
455     }
456 
457     /**
458      * Requests from the client to share frontend with an existing client.
459      *
460      * <p><strong>Note:</strong> {@link #setFrontendInfoList(TunerFrontendInfo[])} must be called
461      * before this request.
462      *
463      * @param selfClientId the id of the client that sends the request.
464      * @param targetClientId the id of the client to share the frontend with.
465      */
shareFrontend(int selfClientId, int targetClientId)466     public void shareFrontend(int selfClientId, int targetClientId) {
467         try {
468             mService.shareFrontend(selfClientId, targetClientId);
469         } catch (RemoteException e) {
470             throw e.rethrowFromSystemServer();
471         }
472     }
473 
474     /**
475      * Transfers the ownership of shared resource.
476      *
477      * <p><strong>Note:</strong> Only the existing frontend sharee can be the new owner.
478      *
479      * @param resourceType the type of the resource to transfer the ownership for.
480      * @param currentOwnerId the id of the current owner client.
481      * @param newOwnerId the id of the new owner client.
482      *
483      * @return true if successful and false otherwise.
484      */
transferOwner(int resourceType, int currentOwnerId, int newOwnerId)485     public boolean transferOwner(int resourceType, int currentOwnerId, int newOwnerId) {
486         try {
487             return mService.transferOwner(resourceType, currentOwnerId, newOwnerId);
488         } catch (RemoteException e) {
489             throw e.rethrowFromSystemServer();
490         }
491     }
492 
493     /**
494      * Requests a Tuner Demux resource.
495      *
496      * <p>There are three possible scenarios:
497      * <ul>
498      * <li>If there is Demux available, the API would send the handle back.
499      *
500      * <li>If no Demux is available but the current request has a higher priority than other uses of
501      * demuxes, the API will send {@link IResourcesReclaimListener#onReclaimResources()} to the
502      * {@link Tuner}. Tuner would handle the resource reclaim on the holder of lower priority and
503      * notify the holder of its resource loss.
504      *
505      * <li>If no Demux system can be granted, the API would return false.
506      * <ul>
507      *
508      * @param request {@link TunerDemuxRequest} information of the current request.
509      * @param demuxHandle a one-element array to return the granted Demux handle.
510      *                    If no Demux granted, this will return {@link #INVALID_RESOURCE_HANDLE}.
511      *
512      * @return true if there is Demux granted.
513      */
requestDemux(@onNull TunerDemuxRequest request, @NonNull int[] demuxHandle)514     public boolean requestDemux(@NonNull TunerDemuxRequest request, @NonNull int[] demuxHandle) {
515         boolean result = false;
516         try {
517             result = mService.requestDemux(request, demuxHandle);
518         } catch (RemoteException e) {
519             throw e.rethrowFromSystemServer();
520         }
521         return result;
522     }
523 
524     /**
525      * Requests a Tuner Descrambler resource.
526      *
527      * <p>There are three possible scenarios:
528      * <ul>
529      * <li>If there is Descrambler available, the API would send the handle back.
530      *
531      * <li>If no Descrambler is available but the current request has a higher priority than other
532      * uses of descramblers, the API will send
533      * {@link IResourcesReclaimListener#onReclaimResources()} to the {@link Tuner}. Tuner would
534      * handle the resource reclaim on the holder of lower priority and notify the holder of its
535      * resource loss.
536      *
537      * <li>If no Descrambler system can be granted, the API would return false.
538      * <ul>
539      *
540      * @param request {@link TunerDescramblerRequest} information of the current request.
541      * @param descramblerHandle a one-element array to return the granted Descrambler handle.
542      *                          If no Descrambler granted, this will return
543      *                          {@link #INVALID_RESOURCE_HANDLE}.
544      *
545      * @return true if there is Descrambler granted.
546      */
requestDescrambler(@onNull TunerDescramblerRequest request, @NonNull int[] descramblerHandle)547     public boolean requestDescrambler(@NonNull TunerDescramblerRequest request,
548                 @NonNull int[] descramblerHandle) {
549         boolean result = false;
550         try {
551             result = mService.requestDescrambler(request, descramblerHandle);
552         } catch (RemoteException e) {
553             throw e.rethrowFromSystemServer();
554         }
555         return result;
556     }
557 
558     /**
559      * Requests a CAS session resource.
560      *
561      * <p>There are three possible scenarios:
562      * <ul>
563      * <li>If there is Cas session available, the API would send the id back.
564      *
565      * <li>If no Cas system is available but the current request info can show higher priority than
566      * other uses of the cas sessions under the requested cas system, the API will send
567      * {@link IResourcesReclaimListener#onReclaimResources()} to the {@link Tuner}. Tuner would
568      * handle the resource reclaim on the holder of lower priority and notify the holder of its
569      * resource loss.
570      *
571      * <p><strong>Note:</strong> {@link #updateCasInfo(int, int)} must be called before this
572      * request.
573      *
574      * @param request {@link CasSessionRequest} information of the current request.
575      * @param casSessionHandle a one-element array to return the granted cas session handel.
576      *                         If no CAS granted, this will return {@link #INVALID_RESOURCE_HANDLE}.
577      *
578      * @return true if there is CAS session granted.
579      */
requestCasSession(@onNull CasSessionRequest request, @NonNull int[] casSessionHandle)580     public boolean requestCasSession(@NonNull CasSessionRequest request,
581                 @NonNull int[] casSessionHandle) {
582         boolean result = false;
583         try {
584             result = mService.requestCasSession(request, casSessionHandle);
585         } catch (RemoteException e) {
586             throw e.rethrowFromSystemServer();
587         }
588         return result;
589     }
590 
591     /**
592      * Requests a CiCam resource.
593      *
594      * <p>There are three possible scenarios:
595      * <ul>
596      * <li>If there is CiCam available, the API would send the id back.
597      *
598      * <li>If no CiCam is available but the current request info can show higher priority than
599      * other uses of the CiCam, the API will send
600      * {@link IResourcesReclaimListener#onReclaimResources()} to the {@link Tuner}. Tuner would
601      * handle the resource reclaim on the holder of lower priority and notify the holder of its
602      * resource loss.
603      *
604      * <p><strong>Note:</strong> {@link #updateCasInfo(int, int)} must be called before this
605      * request.
606      *
607      * @param request {@link TunerCiCamRequest} information of the current request.
608      * @param ciCamHandle a one-element array to return the granted ciCam handle.
609      *                    If no ciCam granted, this will return {@link #INVALID_RESOURCE_HANDLE}.
610      *
611      * @return true if there is ciCam granted.
612      */
requestCiCam(TunerCiCamRequest request, int[] ciCamHandle)613     public boolean requestCiCam(TunerCiCamRequest request, int[] ciCamHandle) {
614         boolean result = false;
615         try {
616             result = mService.requestCiCam(request, ciCamHandle);
617         } catch (RemoteException e) {
618             throw e.rethrowFromSystemServer();
619         }
620         return result;
621     }
622 
623     /**
624      * Requests a Tuner Lnb resource.
625      *
626      * <p>There are three possible scenarios:
627      * <ul>
628      * <li>If there is Lnb available, the API would send the id back.
629      *
630      * <li>If no Lnb is available but the current request has a higher priority than other uses of
631      * lnbs, the API will send {@link IResourcesReclaimListener#onReclaimResources()} to the
632      * {@link Tuner}. Tuner would handle the resource reclaim on the holder of lower priority and
633      * notify the holder of its resource loss.
634      *
635      * <li>If no Lnb system can be granted, the API would return false.
636      * <ul>
637      *
638      * <p><strong>Note:</strong> {@link #setLnbInfoList(int[])} must be called before this request.
639      *
640      * @param request {@link TunerLnbRequest} information of the current request.
641      * @param lnbHandle a one-element array to return the granted Lnb handle.
642      *                  If no Lnb granted, this will return {@link #INVALID_RESOURCE_HANDLE}.
643      *
644      * @return true if there is Lnb granted.
645      */
requestLnb(@onNull TunerLnbRequest request, @NonNull int[] lnbHandle)646     public boolean requestLnb(@NonNull TunerLnbRequest request, @NonNull int[] lnbHandle) {
647         boolean result = false;
648         try {
649             result = mService.requestLnb(request, lnbHandle);
650         } catch (RemoteException e) {
651             throw e.rethrowFromSystemServer();
652         }
653         return result;
654     }
655 
656     /**
657      * Notifies the TRM that the given frontend has been released.
658      *
659      * <p>Client must call this whenever it releases a Tuner frontend.
660      *
661      * <p><strong>Note:</strong> {@link #setFrontendInfoList(TunerFrontendInfo[])} must be called
662      * before this release.
663      *
664      * @param frontendHandle the handle of the released frontend.
665      * @param clientId the id of the client that is releasing the frontend.
666      */
releaseFrontend(int frontendHandle, int clientId)667     public void releaseFrontend(int frontendHandle, int clientId) {
668         try {
669             mService.releaseFrontend(frontendHandle, clientId);
670         } catch (RemoteException e) {
671             throw e.rethrowFromSystemServer();
672         }
673     }
674 
675     /**
676      * Notifies the TRM that the Demux with the given handle has been released.
677      *
678      * <p>Client must call this whenever it releases an Demux.
679      *
680      * @param demuxHandle the handle of the released Tuner Demux.
681      * @param clientId the id of the client that is releasing the demux.
682      */
releaseDemux(int demuxHandle, int clientId)683     public void releaseDemux(int demuxHandle, int clientId) {
684         try {
685             mService.releaseDemux(demuxHandle, clientId);
686         } catch (RemoteException e) {
687             throw e.rethrowFromSystemServer();
688         }
689     }
690 
691     /**
692      * Notifies the TRM that the Descrambler with the given handle has been released.
693      *
694      * <p>Client must call this whenever it releases an Descrambler.
695      *
696      * @param descramblerHandle the handle of the released Tuner Descrambler.
697      * @param clientId the id of the client that is releasing the descrambler.
698      */
releaseDescrambler(int descramblerHandle, int clientId)699     public void releaseDescrambler(int descramblerHandle, int clientId) {
700         try {
701             mService.releaseDescrambler(descramblerHandle, clientId);
702         } catch (RemoteException e) {
703             throw e.rethrowFromSystemServer();
704         }
705     }
706 
707     /**
708      * Notifies the TRM that the given Cas session has been released.
709      *
710      * <p>Client must call this whenever it releases a Cas session.
711      *
712      * <p><strong>Note:</strong> {@link #updateCasInfo(int, int)} must be called before this
713      * release.
714      *
715      * @param casSessionHandle the handle of the released CAS session.
716      * @param clientId the id of the client that is releasing the cas session.
717      */
releaseCasSession(int casSessionHandle, int clientId)718     public void releaseCasSession(int casSessionHandle, int clientId) {
719         try {
720             mService.releaseCasSession(casSessionHandle, clientId);
721         } catch (RemoteException e) {
722             throw e.rethrowFromSystemServer();
723         }
724     }
725 
726     /**
727      * Notifies the TRM that the given CiCam has been released.
728      *
729      * <p>Client must call this whenever it releases a CiCam.
730      *
731      * <p><strong>Note:</strong> {@link #updateCasInfo(int, int)} must be called before this
732      * release.
733      *
734      * @param ciCamHandle the handle of the releasing CiCam.
735      * @param clientId the id of the client that is releasing the CiCam.
736      */
releaseCiCam(int ciCamHandle, int clientId)737     public void releaseCiCam(int ciCamHandle, int clientId) {
738         try {
739             mService.releaseCiCam(ciCamHandle, clientId);
740         } catch (RemoteException e) {
741             throw e.rethrowFromSystemServer();
742         }
743     }
744 
745     /**
746      * Notifies the TRM that the Lnb with the given id has been released.
747      *
748      * <p>Client must call this whenever it releases an Lnb.
749      *
750      * <p><strong>Note:</strong> {@link #setLnbInfoList(int[])} must be called before this release.
751      *
752      * @param lnbHandle the handle of the released Tuner Lnb.
753      * @param clientId the id of the client that is releasing the lnb.
754      */
releaseLnb(int lnbHandle, int clientId)755     public void releaseLnb(int lnbHandle, int clientId) {
756         try {
757             mService.releaseLnb(lnbHandle, clientId);
758         } catch (RemoteException e) {
759             throw e.rethrowFromSystemServer();
760         }
761     }
762 
763     /**
764      * Compare two clients' priority.
765      *
766      * @param challengerProfile the {@link ResourceClientProfile} of the challenger.
767      * @param holderProfile the {@link ResourceClientProfile} of the holder of the resource.
768      *
769      * @return true if the challenger has higher priority than the holder.
770      */
isHigherPriority(ResourceClientProfile challengerProfile, ResourceClientProfile holderProfile)771     public boolean isHigherPriority(ResourceClientProfile challengerProfile,
772             ResourceClientProfile holderProfile) {
773         try {
774             return mService.isHigherPriority(challengerProfile, holderProfile);
775         } catch (RemoteException e) {
776             throw e.rethrowFromSystemServer();
777         }
778     }
779 
780     /**
781      * Returns a priority for the given use case type and the client's foreground or background
782      * status.
783      *
784      * @param useCase the use case type of the client. When the given use case type is invalid,
785      *        the default use case type will be used. {@see TvInputService#PriorityHintUseCaseType}.
786      * @param pid the pid of the client. When the pid is invalid, background status will be used as
787      *        a client's status. Otherwise, client's app corresponding to the given session id will
788      *        be used as a client. {@see TvInputService#onCreateSession(String, String)}.
789      *
790      * @return the client priority..
791      */
getClientPriority(@vInputService.PriorityHintUseCaseType int useCase, int pid)792     public int getClientPriority(@TvInputService.PriorityHintUseCaseType int useCase, int pid) {
793         try {
794             return mService.getClientPriority(useCase, pid);
795         } catch (RemoteException e) {
796             throw e.rethrowFromSystemServer();
797         }
798     }
799 
800     /**
801      * Returns a config priority for the given use case type and the foreground or background
802      * status.
803      *
804      * @param useCase the use case type of the client. When the given use case type is invalid,
805      *        the default use case type will be used. {@see TvInputService#PriorityHintUseCaseType}.
806      * @param isForeground {@code true} if foreground, {@code false} otherwise.
807      *
808      * @return the config priority.
809      *
810      * @hide
811      */
812     @TestApi
813     @SuppressLint("ShowingMemberInHiddenClass")
getConfigPriority(@vInputService.PriorityHintUseCaseType int useCase, boolean isForeground)814     public int getConfigPriority(@TvInputService.PriorityHintUseCaseType int useCase,
815             boolean isForeground) {
816         try {
817             return mService.getConfigPriority(useCase, isForeground);
818         } catch (RemoteException e) {
819             throw e.rethrowFromSystemServer();
820         }
821     }
822 
823     /**
824      * Interface used to receive events from TunerResourceManager.
825      */
826     public abstract static class ResourcesReclaimListener {
827         /*
828          * To reclaim all the resources of the callack owner.
829          */
onReclaimResources()830         public abstract void onReclaimResources();
831     }
832 }
833