1d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang/* 2d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang * Copyright (C) 2017 The Android Open Source Project 3d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang * 4d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang * Licensed under the Apache License, Version 2.0 (the "License"); 5d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang * you may not use this file except in compliance with the License. 6d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang * You may obtain a copy of the License at 7d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang * 8d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang * http://www.apache.org/licenses/LICENSE-2.0 9d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang * 10d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang * Unless required by applicable law or agreed to in writing, software 11d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang * distributed under the License is distributed on an "AS IS" BASIS, 12d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang * See the License for the specific language governing permissions and 14d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang * limitations under the License. 15d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang */ 16d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang 17d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhangpackage android.media; 18d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang 19d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhangimport android.annotation.NonNull; 20dadee0c33e6cb659978ce4fa6aa21f7c384fc43cChong Zhangimport android.media.MediaCasException.UnsupportedCasException; 21d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhangimport android.os.IBinder; 22d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhangimport android.os.Parcel; 23d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhangimport android.os.Parcelable; 24d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhangimport android.os.RemoteException; 25dadee0c33e6cb659978ce4fa6aa21f7c384fc43cChong Zhangimport android.os.ServiceSpecificException; 26d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhangimport android.util.Log; 27d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang 28d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhangimport java.nio.ByteBuffer; 29d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang 30d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang/** 31d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang * MediaDescrambler class can be used in conjunction with {@link android.media.MediaCodec} 32d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang * and {@link android.media.MediaExtractor} to decode media data scrambled by conditional 33d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang * access (CA) systems such as those in the ISO/IEC13818-1. 34d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang * 35d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang * A MediaDescrambler object is initialized from a session opened by a MediaCas object, 36d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang * and can be used to descramble media streams scrambled with that session's keys. 37d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang * 38d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang * Scrambling schemes are identified by 16-bit unsigned integer as in CA_system_id. 39d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang * 40d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang */ 41addc39ec27f3eb9b61ad8565804201a866d16abdChong Zhangpublic final class MediaDescrambler implements AutoCloseable { 42d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang private static final String TAG = "MediaDescrambler"; 43d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang private IDescrambler mIDescrambler; 44d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang 45d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang private final void validateInternalStates() { 46d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang if (mIDescrambler == null) { 47d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang throw new IllegalStateException(); 48d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang } 49d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang } 50d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang 51d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang private final void cleanupAndRethrowIllegalState() { 52d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang mIDescrambler = null; 53d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang throw new IllegalStateException(); 54d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang } 55d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang 56d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang /** 57d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang * Class for parceling descrambling parameters over IDescrambler binder. 58d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang */ 59dadee0c33e6cb659978ce4fa6aa21f7c384fc43cChong Zhang // This class currently is not used by Java binder. descramble() goes through 60dadee0c33e6cb659978ce4fa6aa21f7c384fc43cChong Zhang // jni to use shared memory. However, the parcelable is still required for AIDL. 61d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang static class DescrambleInfo implements Parcelable { 62d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang private DescrambleInfo() { 63d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang } 64d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang 65d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang private DescrambleInfo(Parcel in) { 66d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang } 67d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang 68d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang @Override 69d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang public int describeContents() { 70d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang return 0; 71d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang } 72d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang 73d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang @Override 74d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang public void writeToParcel(Parcel dest, int flags) { 75d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang } 76d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang 77d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang public static final Parcelable.Creator<DescrambleInfo> CREATOR 78d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang = new Parcelable.Creator<DescrambleInfo>() { 79d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang public DescrambleInfo createFromParcel(Parcel in) { 80d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang return new DescrambleInfo(in); 81d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang } 82d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang 83d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang public DescrambleInfo[] newArray(int size) { 84d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang return new DescrambleInfo[size]; 85d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang } 86d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang }; 87d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang } 88d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang 89d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang /** 90d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang * Instantiate a MediaDescrambler. 91d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang * 92d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang * @param CA_system_id The system id of the scrambling scheme. 93d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang * 94d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang * @throws UnsupportedCasException if the scrambling scheme is not supported. 95d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang */ 96d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang public MediaDescrambler(int CA_system_id) throws UnsupportedCasException { 97d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang try { 98d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang mIDescrambler = MediaCas.getService().createDescrambler(CA_system_id); 99d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang } catch(Exception e) { 100d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang Log.e(TAG, "Failed to create descrambler: " + e); 101d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang mIDescrambler = null; 102d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang } finally { 103d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang if (mIDescrambler == null) { 104d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang throw new UnsupportedCasException("Unsupported CA_system_id " + CA_system_id); 105d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang } 106d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang } 107d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang native_setup(mIDescrambler.asBinder()); 108d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang } 109d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang 110d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang IBinder getBinder() { 111d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang validateInternalStates(); 112d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang 113d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang return mIDescrambler.asBinder(); 114d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang } 115d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang 116d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang /** 117d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang * Query if the scrambling scheme requires the use of a secure decoder 118d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang * to decode data of the given mime type. 119d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang * 120d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang * @param mime The mime type of the media data 121d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang * 122d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang * @throws IllegalStateException if the descrambler instance is not valid. 123d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang */ 124d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang public final boolean requiresSecureDecoderComponent(@NonNull String mime) { 125d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang validateInternalStates(); 126d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang 127d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang try { 128d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang return mIDescrambler.requiresSecureDecoderComponent(mime); 129d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang } catch (RemoteException e) { 130d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang cleanupAndRethrowIllegalState(); 131d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang } 132d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang return true; 133d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang } 134d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang 135d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang /** 136d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang * Associate a MediaCas session with this MediaDescrambler instance. 137d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang * The MediaCas session is used to securely load decryption keys for 138d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang * the descrambler. The crypto keys loaded through the MediaCas session 139d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang * may be selected for use during the descrambling operation performed 140d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang * by {@link android.media.MediaExtractor or @link 141d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang * android.media.MediaCodec#queueSecureInputBuffer} by specifying even 142d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang * or odd key in the {@link android.media.MediaCodec.CryptoInfo#key} field. 143d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang * 144addc39ec27f3eb9b61ad8565804201a866d16abdChong Zhang * @param session the MediaCas session to associate with this 145d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang * MediaDescrambler instance. 146d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang * 147dadee0c33e6cb659978ce4fa6aa21f7c384fc43cChong Zhang * @throws IllegalStateException if the descrambler instance is not valid. 148dadee0c33e6cb659978ce4fa6aa21f7c384fc43cChong Zhang * @throws MediaCasStateException for CAS-specific state exceptions. 149d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang */ 150addc39ec27f3eb9b61ad8565804201a866d16abdChong Zhang public final void setMediaCasSession(@NonNull MediaCas.Session session) { 151d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang validateInternalStates(); 152d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang 153d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang try { 154addc39ec27f3eb9b61ad8565804201a866d16abdChong Zhang mIDescrambler.setMediaCasSession(session.mSessionId); 155dadee0c33e6cb659978ce4fa6aa21f7c384fc43cChong Zhang } catch (ServiceSpecificException e) { 156dadee0c33e6cb659978ce4fa6aa21f7c384fc43cChong Zhang MediaCasStateException.throwExceptions(e); 157d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang } catch (RemoteException e) { 158d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang cleanupAndRethrowIllegalState(); 159d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang } 160d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang } 161d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang 162d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang /** 163d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang * Descramble a ByteBuffer of data described by a 164d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang * {@link android.media.MediaCodec.CryptoInfo} structure. 165d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang * 166addc39ec27f3eb9b61ad8565804201a866d16abdChong Zhang * @param srcBuf ByteBuffer containing the scrambled data, which starts at 167addc39ec27f3eb9b61ad8565804201a866d16abdChong Zhang * srcBuf.position(). 168addc39ec27f3eb9b61ad8565804201a866d16abdChong Zhang * @param dstBuf ByteBuffer to hold the descrambled data, which starts at 169addc39ec27f3eb9b61ad8565804201a866d16abdChong Zhang * dstBuf.position(). 170d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang * @param cryptoInfo a {@link android.media.MediaCodec.CryptoInfo} structure 171d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang * describing the subsamples contained in src. 172d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang * 173d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang * @return number of bytes that have been successfully descrambled, with negative 174d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang * values indicating errors. 175d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang * 176d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang * @throws IllegalStateException if the descrambler instance is not valid. 177dadee0c33e6cb659978ce4fa6aa21f7c384fc43cChong Zhang * @throws MediaCasStateException for CAS-specific state exceptions. 178d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang */ 179d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang public final int descramble( 180addc39ec27f3eb9b61ad8565804201a866d16abdChong Zhang @NonNull ByteBuffer srcBuf, @NonNull ByteBuffer dstBuf, 181d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang @NonNull MediaCodec.CryptoInfo cryptoInfo) { 182d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang validateInternalStates(); 183d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang 184d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang if (cryptoInfo.numSubSamples <= 0) { 185d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang throw new IllegalArgumentException( 186d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang "Invalid CryptoInfo: invalid numSubSamples=" + cryptoInfo.numSubSamples); 187d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang } else if (cryptoInfo.numBytesOfClearData == null 188d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang && cryptoInfo.numBytesOfEncryptedData == null) { 189d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang throw new IllegalArgumentException( 190d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang "Invalid CryptoInfo: clearData and encryptedData size arrays are both null!"); 191d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang } else if (cryptoInfo.numBytesOfClearData != null 192d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang && cryptoInfo.numBytesOfClearData.length < cryptoInfo.numSubSamples) { 193d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang throw new IllegalArgumentException( 194d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang "Invalid CryptoInfo: numBytesOfClearData is too small!"); 195d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang } else if (cryptoInfo.numBytesOfEncryptedData != null 196d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang && cryptoInfo.numBytesOfEncryptedData.length < cryptoInfo.numSubSamples) { 197d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang throw new IllegalArgumentException( 198d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang "Invalid CryptoInfo: numBytesOfEncryptedData is too small!"); 199d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang } else if (cryptoInfo.key == null || cryptoInfo.key.length != 16) { 200d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang throw new IllegalArgumentException( 201d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang "Invalid CryptoInfo: key array is invalid!"); 202d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang } 203d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang 204dadee0c33e6cb659978ce4fa6aa21f7c384fc43cChong Zhang try { 205dadee0c33e6cb659978ce4fa6aa21f7c384fc43cChong Zhang return native_descramble( 206dadee0c33e6cb659978ce4fa6aa21f7c384fc43cChong Zhang cryptoInfo.key[0], 207dadee0c33e6cb659978ce4fa6aa21f7c384fc43cChong Zhang cryptoInfo.numSubSamples, 208dadee0c33e6cb659978ce4fa6aa21f7c384fc43cChong Zhang cryptoInfo.numBytesOfClearData, 209dadee0c33e6cb659978ce4fa6aa21f7c384fc43cChong Zhang cryptoInfo.numBytesOfEncryptedData, 210addc39ec27f3eb9b61ad8565804201a866d16abdChong Zhang srcBuf, srcBuf.position(), srcBuf.limit(), 211addc39ec27f3eb9b61ad8565804201a866d16abdChong Zhang dstBuf, dstBuf.position(), dstBuf.limit()); 212dadee0c33e6cb659978ce4fa6aa21f7c384fc43cChong Zhang } catch (ServiceSpecificException e) { 213dadee0c33e6cb659978ce4fa6aa21f7c384fc43cChong Zhang MediaCasStateException.throwExceptions(e); 214dadee0c33e6cb659978ce4fa6aa21f7c384fc43cChong Zhang } 215dadee0c33e6cb659978ce4fa6aa21f7c384fc43cChong Zhang return -1; 216d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang } 217d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang 218addc39ec27f3eb9b61ad8565804201a866d16abdChong Zhang @Override 219addc39ec27f3eb9b61ad8565804201a866d16abdChong Zhang public void close() { 220d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang if (mIDescrambler != null) { 221d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang try { 222d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang mIDescrambler.release(); 223d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang } catch (RemoteException e) { 224d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang } finally { 225d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang mIDescrambler = null; 226d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang } 227d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang } 228d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang native_release(); 229d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang } 230d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang 231d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang @Override 232d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang protected void finalize() { 233addc39ec27f3eb9b61ad8565804201a866d16abdChong Zhang close(); 234d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang } 235d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang 236d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang private static native final void native_init(); 237d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang private native final void native_setup(@NonNull IBinder decramblerBinder); 238d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang private native final void native_release(); 239d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang private native final int native_descramble( 240d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang byte key, int numSubSamples, int[] numBytesOfClearData, int[] numBytesOfEncryptedData, 241addc39ec27f3eb9b61ad8565804201a866d16abdChong Zhang @NonNull ByteBuffer srcBuf, int srcOffset, int srcLimit, 242addc39ec27f3eb9b61ad8565804201a866d16abdChong Zhang ByteBuffer dstBuf, int dstOffset, int dstLimit); 243d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang 244d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang static { 245d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang System.loadLibrary("media_jni"); 246d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang native_init(); 247d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang } 248d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang 249d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang private long mNativeContext; 250d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang}