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