• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2019 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.tuner;
18 
19 import android.annotation.IntDef;
20 import android.annotation.NonNull;
21 import android.annotation.Nullable;
22 import android.annotation.SystemApi;
23 import android.media.tv.tuner.Tuner.Result;
24 import android.media.tv.tuner.filter.Filter;
25 import android.util.Log;
26 
27 import java.lang.annotation.Retention;
28 import java.lang.annotation.RetentionPolicy;
29 import java.util.Objects;
30 
31 /**
32  * This class is used to interact with descramblers.
33  *
34  * <p> Descrambler is a hardware component used to descramble data.
35  *
36  * <p> This class controls the TIS interaction with Tuner HAL.
37  *
38  * @hide
39  */
40 @SystemApi
41 public class Descrambler implements AutoCloseable {
42     /** @hide */
43     @IntDef(prefix = "PID_TYPE_", value = {PID_TYPE_T, PID_TYPE_MMTP})
44     @Retention(RetentionPolicy.SOURCE)
45     public @interface PidType {}
46 
47     /**
48      * Packet ID is used to specify packets in transport stream.
49      */
50     public static final int PID_TYPE_T = 1;
51     /**
52      * Packet ID is used to specify packets in MMTP.
53      */
54     public static final int PID_TYPE_MMTP = 2;
55 
56     private static final String TAG = "Descrambler";
57 
58 
59     private long mNativeContext;
60     private boolean mIsClosed = false;
61     private final Object mLock = new Object();
62 
nativeAddPid(int pidType, int pid, Filter filter)63     private native int nativeAddPid(int pidType, int pid, Filter filter);
nativeRemovePid(int pidType, int pid, Filter filter)64     private native int nativeRemovePid(int pidType, int pid, Filter filter);
nativeSetKeyToken(byte[] keyToken)65     private native int nativeSetKeyToken(byte[] keyToken);
nativeClose()66     private native int nativeClose();
67 
68     // Called by JNI code
Descrambler()69     private Descrambler() {}
70 
71     /**
72      * Add packets' PID to the descrambler for descrambling.
73      *
74      * The descrambler will start descrambling packets with this PID. Multiple PIDs can be added
75      * into one descrambler instance because descambling can happen simultaneously on packets
76      * from different PIDs.
77      *
78      * If the Descrambler previously contained a filter for the PID, the old filter is replaced
79      * by the specified filter.
80      *
81      * @param pidType the type of the PID.
82      * @param pid the PID of packets to start to be descrambled.
83      * @param filter an optional filter instance to identify upper stream.
84      * @return result status of the operation.
85      */
86     @Result
addPid(@idType int pidType, int pid, @Nullable Filter filter)87     public int addPid(@PidType int pidType, int pid, @Nullable Filter filter) {
88         synchronized (mLock) {
89             TunerUtils.checkResourceState(TAG, mIsClosed);
90             return nativeAddPid(pidType, pid, filter);
91         }
92     }
93 
94     /**
95      * Remove packets' PID from the descrambler
96      *
97      * The descrambler will stop descrambling packets with this PID.
98      *
99      * @param pidType the type of the PID.
100      * @param pid the PID of packets to stop to be descrambled.
101      * @param filter an optional filter instance to identify upper stream.
102      * @return result status of the operation.
103      */
104     @Result
removePid(@idType int pidType, int pid, @Nullable Filter filter)105     public int removePid(@PidType int pidType, int pid, @Nullable Filter filter) {
106         synchronized (mLock) {
107             TunerUtils.checkResourceState(TAG, mIsClosed);
108             return nativeRemovePid(pidType, pid, filter);
109         }
110     }
111 
112     /**
113      * Set a key token to link descrambler to a key slot. Use {@link isValidKeyToken(byte[])} to
114      * validate the key token format. Invalid key token would cause no-op and return
115      * {@link Tuner.RESULT_INVALID_ARGUMENT}.
116      *
117      * <p>A descrambler instance can have only one key slot to link, but a key slot can hold a few
118      * keys for different purposes. {@link Tuner.VOID_KEYTOKEN} is considered valid.
119      *
120      * @param keyToken the token to be used to link the key slot. Use {@link Tuner#VOID_KEYTOKEN}
121      *        to remove the current key from descrambler. If the current keyToken comes from a
122      *        MediaCas session, use {@link Tuner#VOID_KEYTOKEN} to remove current key before
123      *        closing the MediaCas session.
124      * @return result status of the operation.
125      */
126     @Result
setKeyToken(@onNull byte[] keyToken)127     public int setKeyToken(@NonNull byte[] keyToken) {
128         synchronized (mLock) {
129             TunerUtils.checkResourceState(TAG, mIsClosed);
130             Objects.requireNonNull(keyToken, "key token must not be null");
131             if (!isValidKeyToken(keyToken)) {
132                 return Tuner.RESULT_INVALID_ARGUMENT;
133             }
134             return nativeSetKeyToken(keyToken);
135         }
136     }
137 
138     /**
139      * Validate the key token format as the parameter of {@link setKeyToken(byte[])}.
140      *
141      * <p>The key token is expected to be less than 128 bits.
142      *
143      * @param keyToken the token to be validated.
144      * @return true if the given key token is a valid one.
145      */
isValidKeyToken(@onNull byte[] keyToken)146     public static boolean isValidKeyToken(@NonNull byte[] keyToken) {
147         if (keyToken.length == 0 || keyToken.length > 16) {
148             Log.d(TAG, "Invalid key token size: " + (keyToken.length * 8) + " bit.");
149             return false;
150         }
151         return true;
152     }
153 
154     /**
155      * Release the descrambler instance.
156      */
157     @Override
close()158     public void close() {
159         synchronized (mLock) {
160             if (mIsClosed) {
161                 return;
162             }
163             int res = nativeClose();
164             if (res != Tuner.RESULT_SUCCESS) {
165                 TunerUtils.throwExceptionForResult(res, "Failed to close descrambler");
166             } else {
167                 mIsClosed = true;
168             }
169         }
170     }
171 }
172