diff options
-rw-r--r-- | Android.bp | 2 | ||||
-rw-r--r-- | core/api/current.txt | 1 | ||||
-rw-r--r-- | media/java/android/media/MediaCas.java | 639 | ||||
-rw-r--r-- | media/java/android/media/MediaDescrambler.java | 244 | ||||
-rw-r--r-- | media/java/android/media/MediaExtractor.java | 11 |
5 files changed, 646 insertions, 251 deletions
diff --git a/Android.bp b/Android.bp index 8e09157bb461..67902b310481 100644 --- a/Android.bp +++ b/Android.bp @@ -106,6 +106,7 @@ filegroup { ":android.security.maintenance-java-source", ":android.security.metrics-java-source", ":android.system.keystore2-V3-java-source", + ":android.hardware.cas-V1-java-source", ":credstore_aidl", ":dumpstate_aidl", ":framework_native_aidl", @@ -196,6 +197,7 @@ java_library { "updatable-driver-protos", "ota_metadata_proto_java", "android.hidl.base-V1.0-java", + "android.hardware.cas-V1-java", // AIDL "android.hardware.cas-V1.0-java", "android.hardware.cas-V1.1-java", "android.hardware.cas-V1.2-java", diff --git a/core/api/current.txt b/core/api/current.txt index d1327067c0b8..a0c132f980dc 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -21142,6 +21142,7 @@ package android.media { field public static final int PLUGIN_STATUS_PHYSICAL_MODULE_CHANGED = 0; // 0x0 field public static final int PLUGIN_STATUS_SESSION_NUMBER_CHANGED = 1; // 0x1 field public static final int SCRAMBLING_MODE_AES128 = 9; // 0x9 + field public static final int SCRAMBLING_MODE_AES_CBC = 14; // 0xe field public static final int SCRAMBLING_MODE_AES_ECB = 10; // 0xa field public static final int SCRAMBLING_MODE_AES_SCTE52 = 11; // 0xb field public static final int SCRAMBLING_MODE_DVB_CISSA_V1 = 6; // 0x6 diff --git a/media/java/android/media/MediaCas.java b/media/java/android/media/MediaCas.java index 582a28ee278e..015602e95533 100644 --- a/media/java/android/media/MediaCas.java +++ b/media/java/android/media/MediaCas.java @@ -21,11 +21,12 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.TestApi; import android.content.Context; +import android.hardware.cas.AidlCasPluginDescriptor; +import android.hardware.cas.ICas; +import android.hardware.cas.ICasListener; +import android.hardware.cas.IMediaCasService; +import android.hardware.cas.Status; import android.hardware.cas.V1_0.HidlCasPluginDescriptor; -import android.hardware.cas.V1_0.ICas; -import android.hardware.cas.V1_0.IMediaCasService; -import android.hardware.cas.V1_2.ICasListener; -import android.hardware.cas.V1_2.Status; import android.media.MediaCasException.*; import android.media.tv.TvInputService.PriorityHintUseCaseType; import android.media.tv.tunerresourcemanager.CasSessionRequest; @@ -39,6 +40,7 @@ import android.os.Looper; import android.os.Message; import android.os.Process; import android.os.RemoteException; +import android.os.ServiceManager; import android.util.Log; import android.util.Singleton; @@ -47,6 +49,7 @@ import com.android.internal.util.FrameworkStatsLog; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -114,9 +117,10 @@ import java.util.Objects; */ public final class MediaCas implements AutoCloseable { private static final String TAG = "MediaCas"; - private ICas mICas; - private android.hardware.cas.V1_1.ICas mICasV11; - private android.hardware.cas.V1_2.ICas mICasV12; + private ICas mICas = null; + private android.hardware.cas.V1_0.ICas mICasHidl = null; + private android.hardware.cas.V1_1.ICas mICasHidl11 = null; + private android.hardware.cas.V1_2.ICas mICasHidl12 = null; private EventListener mListener; private HandlerThread mHandlerThread; private EventHandler mEventHandler; @@ -133,88 +137,84 @@ public final class MediaCas implements AutoCloseable { * * @hide */ - @IntDef(prefix = "SCRAMBLING_MODE_", - value = {SCRAMBLING_MODE_RESERVED, SCRAMBLING_MODE_DVB_CSA1, SCRAMBLING_MODE_DVB_CSA2, - SCRAMBLING_MODE_DVB_CSA3_STANDARD, - SCRAMBLING_MODE_DVB_CSA3_MINIMAL, SCRAMBLING_MODE_DVB_CSA3_ENHANCE, - SCRAMBLING_MODE_DVB_CISSA_V1, SCRAMBLING_MODE_DVB_IDSA, - SCRAMBLING_MODE_MULTI2, SCRAMBLING_MODE_AES128, SCRAMBLING_MODE_AES_ECB, - SCRAMBLING_MODE_AES_SCTE52, SCRAMBLING_MODE_TDES_ECB, SCRAMBLING_MODE_TDES_SCTE52}) + @IntDef( + prefix = "SCRAMBLING_MODE_", + value = { + SCRAMBLING_MODE_RESERVED, + SCRAMBLING_MODE_DVB_CSA1, + SCRAMBLING_MODE_DVB_CSA2, + SCRAMBLING_MODE_DVB_CSA3_STANDARD, + SCRAMBLING_MODE_DVB_CSA3_MINIMAL, + SCRAMBLING_MODE_DVB_CSA3_ENHANCE, + SCRAMBLING_MODE_DVB_CISSA_V1, + SCRAMBLING_MODE_DVB_IDSA, + SCRAMBLING_MODE_MULTI2, + SCRAMBLING_MODE_AES128, + SCRAMBLING_MODE_AES_CBC, + SCRAMBLING_MODE_AES_ECB, + SCRAMBLING_MODE_AES_SCTE52, + SCRAMBLING_MODE_TDES_ECB, + SCRAMBLING_MODE_TDES_SCTE52 + }) @Retention(RetentionPolicy.SOURCE) public @interface ScramblingMode {} - /** - * DVB (Digital Video Broadcasting) reserved mode. - */ - public static final int SCRAMBLING_MODE_RESERVED = - android.hardware.cas.V1_2.ScramblingMode.RESERVED; - /** - * DVB (Digital Video Broadcasting) Common Scrambling Algorithm (CSA) 1. - */ - public static final int SCRAMBLING_MODE_DVB_CSA1 = - android.hardware.cas.V1_2.ScramblingMode.DVB_CSA1; - /** - * DVB CSA 2. - */ - public static final int SCRAMBLING_MODE_DVB_CSA2 = - android.hardware.cas.V1_2.ScramblingMode.DVB_CSA2; - /** - * DVB CSA 3 in standard mode. - */ + /** DVB (Digital Video Broadcasting) reserved mode. */ + public static final int SCRAMBLING_MODE_RESERVED = android.hardware.cas.ScramblingMode.RESERVED; + + /** DVB (Digital Video Broadcasting) Common Scrambling Algorithm (CSA) 1. */ + public static final int SCRAMBLING_MODE_DVB_CSA1 = android.hardware.cas.ScramblingMode.DVB_CSA1; + + /** DVB CSA 2. */ + public static final int SCRAMBLING_MODE_DVB_CSA2 = android.hardware.cas.ScramblingMode.DVB_CSA2; + + /** DVB CSA 3 in standard mode. */ public static final int SCRAMBLING_MODE_DVB_CSA3_STANDARD = - android.hardware.cas.V1_2.ScramblingMode.DVB_CSA3_STANDARD; - /** - * DVB CSA 3 in minimally enhanced mode. - */ + android.hardware.cas.ScramblingMode.DVB_CSA3_STANDARD; + + /** DVB CSA 3 in minimally enhanced mode. */ public static final int SCRAMBLING_MODE_DVB_CSA3_MINIMAL = - android.hardware.cas.V1_2.ScramblingMode.DVB_CSA3_MINIMAL; - /** - * DVB CSA 3 in fully enhanced mode. - */ + android.hardware.cas.ScramblingMode.DVB_CSA3_MINIMAL; + + /** DVB CSA 3 in fully enhanced mode. */ public static final int SCRAMBLING_MODE_DVB_CSA3_ENHANCE = - android.hardware.cas.V1_2.ScramblingMode.DVB_CSA3_ENHANCE; - /** - * DVB Common IPTV Software-oriented Scrambling Algorithm (CISSA) Version 1. - */ + android.hardware.cas.ScramblingMode.DVB_CSA3_ENHANCE; + + /** DVB Common IPTV Software-oriented Scrambling Algorithm (CISSA) Version 1. */ public static final int SCRAMBLING_MODE_DVB_CISSA_V1 = - android.hardware.cas.V1_2.ScramblingMode.DVB_CISSA_V1; - /** - * ATIS-0800006 IIF Default Scrambling Algorithm (IDSA). - */ - public static final int SCRAMBLING_MODE_DVB_IDSA = - android.hardware.cas.V1_2.ScramblingMode.DVB_IDSA; - /** - * A symmetric key algorithm. - */ - public static final int SCRAMBLING_MODE_MULTI2 = - android.hardware.cas.V1_2.ScramblingMode.MULTI2; - /** - * Advanced Encryption System (AES) 128-bit Encryption mode. - */ - public static final int SCRAMBLING_MODE_AES128 = - android.hardware.cas.V1_2.ScramblingMode.AES128; - /** - * Advanced Encryption System (AES) Electronic Code Book (ECB) mode. - */ - public static final int SCRAMBLING_MODE_AES_ECB = - android.hardware.cas.V1_2.ScramblingMode.AES_ECB; + android.hardware.cas.ScramblingMode.DVB_CISSA_V1; + + /** ATIS-0800006 IIF Default Scrambling Algorithm (IDSA). */ + public static final int SCRAMBLING_MODE_DVB_IDSA = android.hardware.cas.ScramblingMode.DVB_IDSA; + + /** A symmetric key algorithm. */ + public static final int SCRAMBLING_MODE_MULTI2 = android.hardware.cas.ScramblingMode.MULTI2; + + /** Advanced Encryption System (AES) 128-bit Encryption mode. */ + public static final int SCRAMBLING_MODE_AES128 = android.hardware.cas.ScramblingMode.AES128; + + /** Advanced Encryption System (AES) Cipher Block Chaining (CBC) mode. */ + public static final int SCRAMBLING_MODE_AES_CBC = android.hardware.cas.ScramblingMode.AES_CBC; + + /** Advanced Encryption System (AES) Electronic Code Book (ECB) mode. */ + public static final int SCRAMBLING_MODE_AES_ECB = android.hardware.cas.ScramblingMode.AES_ECB; + /** * Advanced Encryption System (AES) Society of Cable Telecommunications Engineers (SCTE) 52 * mode. */ public static final int SCRAMBLING_MODE_AES_SCTE52 = - android.hardware.cas.V1_2.ScramblingMode.AES_SCTE52; - /** - * Triple Data Encryption Algorithm (TDES) Electronic Code Book (ECB) mode. - */ - public static final int SCRAMBLING_MODE_TDES_ECB = - android.hardware.cas.V1_2.ScramblingMode.TDES_ECB; + android.hardware.cas.ScramblingMode.AES_SCTE52; + + /** Triple Data Encryption Algorithm (TDES) Electronic Code Book (ECB) mode. */ + public static final int SCRAMBLING_MODE_TDES_ECB = android.hardware.cas.ScramblingMode.TDES_ECB; + /** * Triple Data Encryption Algorithm (TDES) Society of Cable Telecommunications Engineers (SCTE) * 52 mode. */ public static final int SCRAMBLING_MODE_TDES_SCTE52 = - android.hardware.cas.V1_2.ScramblingMode.TDES_SCTE52; + android.hardware.cas.ScramblingMode.TDES_SCTE52; /** * Usages used to open cas sessions. @@ -226,25 +226,21 @@ public final class MediaCas implements AutoCloseable { SESSION_USAGE_TIMESHIFT}) @Retention(RetentionPolicy.SOURCE) public @interface SessionUsage {} - /** - * Cas session is used to descramble live streams. - */ - public static final int SESSION_USAGE_LIVE = android.hardware.cas.V1_2.SessionIntent.LIVE; - /** - * Cas session is used to descramble recoreded streams. - */ - public static final int SESSION_USAGE_PLAYBACK = - android.hardware.cas.V1_2.SessionIntent.PLAYBACK; - /** - * Cas session is used to descramble live streams and encrypt local recorded content - */ - public static final int SESSION_USAGE_RECORD = android.hardware.cas.V1_2.SessionIntent.RECORD; + + /** Cas session is used to descramble live streams. */ + public static final int SESSION_USAGE_LIVE = android.hardware.cas.SessionIntent.LIVE; + + /** Cas session is used to descramble recoreded streams. */ + public static final int SESSION_USAGE_PLAYBACK = android.hardware.cas.SessionIntent.PLAYBACK; + + /** Cas session is used to descramble live streams and encrypt local recorded content */ + public static final int SESSION_USAGE_RECORD = android.hardware.cas.SessionIntent.RECORD; + /** * Cas session is used to descramble live streams , encrypt local recorded content and playback * local encrypted content. */ - public static final int SESSION_USAGE_TIMESHIFT = - android.hardware.cas.V1_2.SessionIntent.TIMESHIFT; + public static final int SESSION_USAGE_TIMESHIFT = android.hardware.cas.SessionIntent.TIMESHIFT; /** * Plugin status events sent from cas system. @@ -261,63 +257,90 @@ public final class MediaCas implements AutoCloseable { * physical CAS modules. */ public static final int PLUGIN_STATUS_PHYSICAL_MODULE_CHANGED = - android.hardware.cas.V1_2.StatusEvent.PLUGIN_PHYSICAL_MODULE_CHANGED; - /** - * The event to indicate that the number of CAS system's session is changed. - */ - public static final int PLUGIN_STATUS_SESSION_NUMBER_CHANGED = - android.hardware.cas.V1_2.StatusEvent.PLUGIN_SESSION_NUMBER_CHANGED; + android.hardware.cas.StatusEvent.PLUGIN_PHYSICAL_MODULE_CHANGED; - private static final Singleton<IMediaCasService> sService = new Singleton<IMediaCasService>() { - @Override - protected IMediaCasService create() { - try { - Log.d(TAG, "Trying to get cas@1.2 service"); - android.hardware.cas.V1_2.IMediaCasService serviceV12 = - android.hardware.cas.V1_2.IMediaCasService.getService(true /*wait*/); - if (serviceV12 != null) { - return serviceV12; + /** The event to indicate that the number of CAS system's session is changed. */ + public static final int PLUGIN_STATUS_SESSION_NUMBER_CHANGED = + android.hardware.cas.StatusEvent.PLUGIN_SESSION_NUMBER_CHANGED; + + private static final Singleton<IMediaCasService> sService = + new Singleton<IMediaCasService>() { + @Override + protected IMediaCasService create() { + try { + Log.d(TAG, "Trying to get AIDL service"); + IMediaCasService serviceAidl = + IMediaCasService.Stub.asInterface( + ServiceManager.getService( + IMediaCasService.DESCRIPTOR + "/default")); + if (serviceAidl != null) { + return serviceAidl; + } + } catch (Exception eAidl) { + Log.d(TAG, "Failed to get cas AIDL service"); + } + return null; } - } catch (Exception eV1_2) { - Log.d(TAG, "Failed to get cas@1.2 service"); - } + }; + + private static final Singleton<android.hardware.cas.V1_0.IMediaCasService> sServiceHidl = + new Singleton<android.hardware.cas.V1_0.IMediaCasService>() { + @Override + protected android.hardware.cas.V1_0.IMediaCasService create() { + try { + Log.d(TAG, "Trying to get cas@1.2 service"); + android.hardware.cas.V1_2.IMediaCasService serviceV12 = + android.hardware.cas.V1_2.IMediaCasService.getService( + true /*wait*/); + if (serviceV12 != null) { + return serviceV12; + } + } catch (Exception eV1_2) { + Log.d(TAG, "Failed to get cas@1.2 service"); + } - try { - Log.d(TAG, "Trying to get cas@1.1 service"); - android.hardware.cas.V1_1.IMediaCasService serviceV11 = - android.hardware.cas.V1_1.IMediaCasService.getService(true /*wait*/); - if (serviceV11 != null) { - return serviceV11; + try { + Log.d(TAG, "Trying to get cas@1.1 service"); + android.hardware.cas.V1_1.IMediaCasService serviceV11 = + android.hardware.cas.V1_1.IMediaCasService.getService( + true /*wait*/); + if (serviceV11 != null) { + return serviceV11; + } + } catch (Exception eV1_1) { + Log.d(TAG, "Failed to get cas@1.1 service"); } - } catch (Exception eV1_1) { - Log.d(TAG, "Failed to get cas@1.1 service"); - } - try { - Log.d(TAG, "Trying to get cas@1.0 service"); - return IMediaCasService.getService(true /*wait*/); - } catch (Exception eV1_0) { - Log.d(TAG, "Failed to get cas@1.0 service"); - } + try { + Log.d(TAG, "Trying to get cas@1.0 service"); + return android.hardware.cas.V1_0.IMediaCasService.getService(true /*wait*/); + } catch (Exception eV1_0) { + Log.d(TAG, "Failed to get cas@1.0 service"); + } - return null; - } - }; + return null; + } + }; static IMediaCasService getService() { return sService.get(); } + static android.hardware.cas.V1_0.IMediaCasService getServiceHidl() { + return sServiceHidl.get(); + } + private void validateInternalStates() { - if (mICas == null) { + if (mICas == null && mICasHidl == null) { throw new IllegalStateException(); } } private void cleanupAndRethrowIllegalState() { mICas = null; - mICasV11 = null; - mICasV12 = null; + mICasHidl = null; + mICasHidl11 = null; + mICasHidl12 = null; throw new IllegalStateException(); } @@ -341,7 +364,7 @@ public final class MediaCas implements AutoCloseable { toBytes((ArrayList<Byte>) msg.obj)); } else if (msg.what == MSG_CAS_SESSION_EVENT) { Bundle bundle = msg.getData(); - ArrayList<Byte> sessionId = toByteArray(bundle.getByteArray(SESSION_KEY)); + byte[] sessionId = bundle.getByteArray(SESSION_KEY); mListener.onSessionEvent(MediaCas.this, createFromSessionId(sessionId), msg.arg1, msg.arg2, bundle.getByteArray(DATA_KEY)); @@ -357,40 +380,94 @@ public final class MediaCas implements AutoCloseable { } } - private final ICasListener.Stub mBinder = new ICasListener.Stub() { - @Override - public void onEvent(int event, int arg, @Nullable ArrayList<Byte> data) - throws RemoteException { - if (mEventHandler != null) { - mEventHandler.sendMessage(mEventHandler.obtainMessage( - EventHandler.MSG_CAS_EVENT, event, arg, data)); - } - } - @Override - public void onSessionEvent(@NonNull ArrayList<Byte> sessionId, - int event, int arg, @Nullable ArrayList<Byte> data) - throws RemoteException { - if (mEventHandler != null) { - Message msg = mEventHandler.obtainMessage(); - msg.what = EventHandler.MSG_CAS_SESSION_EVENT; - msg.arg1 = event; - msg.arg2 = arg; - Bundle bundle = new Bundle(); - bundle.putByteArray(EventHandler.SESSION_KEY, toBytes(sessionId)); - bundle.putByteArray(EventHandler.DATA_KEY, toBytes(data)); - msg.setData(bundle); - mEventHandler.sendMessage(msg); - } - } - @Override - public void onStatusUpdate(byte status, int arg) - throws RemoteException { - if (mEventHandler != null) { - mEventHandler.sendMessage(mEventHandler.obtainMessage( - EventHandler.MSG_CAS_STATUS_EVENT, status, arg)); - } - } - }; + private final ICasListener.Stub mBinder = + new ICasListener.Stub() { + @Override + public void onEvent(int event, int arg, byte[] data) throws RemoteException { + if (mEventHandler != null) { + mEventHandler.sendMessage( + mEventHandler.obtainMessage( + EventHandler.MSG_CAS_EVENT, event, arg, data)); + } + } + + @Override + public void onSessionEvent(byte[] sessionId, int event, int arg, byte[] data) + throws RemoteException { + if (mEventHandler != null) { + Message msg = mEventHandler.obtainMessage(); + msg.what = EventHandler.MSG_CAS_SESSION_EVENT; + msg.arg1 = event; + msg.arg2 = arg; + Bundle bundle = new Bundle(); + bundle.putByteArray(EventHandler.SESSION_KEY, sessionId); + bundle.putByteArray(EventHandler.DATA_KEY, data); + msg.setData(bundle); + mEventHandler.sendMessage(msg); + } + } + + @Override + public void onStatusUpdate(byte status, int arg) throws RemoteException { + if (mEventHandler != null) { + mEventHandler.sendMessage( + mEventHandler.obtainMessage( + EventHandler.MSG_CAS_STATUS_EVENT, status, arg)); + } + } + + @Override + public synchronized String getInterfaceHash() throws android.os.RemoteException { + return ICasListener.Stub.HASH; + } + + @Override + public int getInterfaceVersion() throws android.os.RemoteException { + return ICasListener.Stub.VERSION; + } + }; + + private final android.hardware.cas.V1_2.ICasListener.Stub mBinderHidl = + new android.hardware.cas.V1_2.ICasListener.Stub() { + @Override + public void onEvent(int event, int arg, @Nullable ArrayList<Byte> data) + throws RemoteException { + if (mEventHandler != null) { + mEventHandler.sendMessage( + mEventHandler.obtainMessage( + EventHandler.MSG_CAS_EVENT, event, arg, data)); + } + } + + @Override + public void onSessionEvent( + @NonNull ArrayList<Byte> sessionId, + int event, + int arg, + @Nullable ArrayList<Byte> data) + throws RemoteException { + if (mEventHandler != null) { + Message msg = mEventHandler.obtainMessage(); + msg.what = EventHandler.MSG_CAS_SESSION_EVENT; + msg.arg1 = event; + msg.arg2 = arg; + Bundle bundle = new Bundle(); + bundle.putByteArray(EventHandler.SESSION_KEY, toBytes(sessionId)); + bundle.putByteArray(EventHandler.DATA_KEY, toBytes(data)); + msg.setData(bundle); + mEventHandler.sendMessage(msg); + } + } + + @Override + public void onStatusUpdate(byte status, int arg) throws RemoteException { + if (mEventHandler != null) { + mEventHandler.sendMessage( + mEventHandler.obtainMessage( + EventHandler.MSG_CAS_STATUS_EVENT, status, arg)); + } + } + }; private final TunerResourceManager.ResourcesReclaimListener mResourceListener = new TunerResourceManager.ResourcesReclaimListener() { @@ -422,6 +499,11 @@ public final class MediaCas implements AutoCloseable { mName = null; } + PluginDescriptor(@NonNull AidlCasPluginDescriptor descriptor) { + mCASystemId = descriptor.caSystemId; + mName = descriptor.name; + } + PluginDescriptor(@NonNull HidlCasPluginDescriptor descriptor) { mCASystemId = descriptor.caSystemId; mName = descriptor.name; @@ -467,19 +549,20 @@ public final class MediaCas implements AutoCloseable { } return data; } + /** * Class for an open session with the CA system. */ public final class Session implements AutoCloseable { - final ArrayList<Byte> mSessionId; + final byte[] mSessionId; boolean mIsClosed = false; - Session(@NonNull ArrayList<Byte> sessionId) { - mSessionId = new ArrayList<Byte>(sessionId); + Session(@NonNull byte[] sessionId) { + mSessionId = sessionId; } private void validateSessionInternalStates() { - if (mICas == null) { + if (mICas == null && mICasHidl == null) { throw new IllegalStateException(); } if (mIsClosed) { @@ -496,7 +579,7 @@ public final class MediaCas implements AutoCloseable { */ public boolean equals(Object obj) { if (obj instanceof Session) { - return mSessionId.equals(((Session) obj).mSessionId); + return Arrays.equals(mSessionId, ((Session) obj).mSessionId); } return false; } @@ -515,8 +598,13 @@ public final class MediaCas implements AutoCloseable { validateSessionInternalStates(); try { - MediaCasException.throwExceptionIfNeeded( - mICas.setSessionPrivateData(mSessionId, toByteArray(data, 0, data.length))); + if (mICas != null) { + mICas.setSessionPrivateData(mSessionId, data); + } else { + MediaCasException.throwExceptionIfNeeded( + mICasHidl.setSessionPrivateData( + toByteArray(mSessionId), toByteArray(data, 0, data.length))); + } } catch (RemoteException e) { cleanupAndRethrowIllegalState(); } @@ -539,8 +627,13 @@ public final class MediaCas implements AutoCloseable { validateSessionInternalStates(); try { - MediaCasException.throwExceptionIfNeeded( - mICas.processEcm(mSessionId, toByteArray(data, offset, length))); + if (mICas != null) { + mICas.processEcm(mSessionId, data); + } else { + MediaCasException.throwExceptionIfNeeded( + mICasHidl.processEcm( + toByteArray(mSessionId), toByteArray(data, offset, length))); + } } catch (RemoteException e) { cleanupAndRethrowIllegalState(); } @@ -576,15 +669,23 @@ public final class MediaCas implements AutoCloseable { public void sendSessionEvent(int event, int arg, @Nullable byte[] data) throws MediaCasException { validateSessionInternalStates(); + if (mICas != null) { + try { + mICas.sendSessionEvent(mSessionId, event, arg, data); + } catch (RemoteException e) { + cleanupAndRethrowIllegalState(); + } + } - if (mICasV11 == null) { + if (mICasHidl11 == null) { Log.d(TAG, "Send Session Event isn't supported by cas@1.0 interface"); throw new UnsupportedCasException("Send Session Event is not supported"); } try { MediaCasException.throwExceptionIfNeeded( - mICasV11.sendSessionEvent(mSessionId, event, arg, toByteArray(data))); + mICasHidl11.sendSessionEvent( + toByteArray(mSessionId), event, arg, toByteArray(data))); } catch (RemoteException e) { cleanupAndRethrowIllegalState(); } @@ -600,7 +701,7 @@ public final class MediaCas implements AutoCloseable { @NonNull public byte[] getSessionId() { validateSessionInternalStates(); - return toBytes(mSessionId); + return mSessionId; } /** @@ -613,8 +714,12 @@ public final class MediaCas implements AutoCloseable { public void close() { validateSessionInternalStates(); try { - MediaCasStateException.throwExceptionIfNeeded( - mICas.closeSession(mSessionId)); + if (mICas != null) { + mICas.closeSession(mSessionId); + } else { + MediaCasStateException.throwExceptionIfNeeded( + mICasHidl.closeSession(toByteArray(mSessionId))); + } mIsClosed = true; removeSessionFromResourceMap(this); } catch (RemoteException e) { @@ -623,8 +728,8 @@ public final class MediaCas implements AutoCloseable { } } - Session createFromSessionId(@NonNull ArrayList<Byte> sessionId) { - if (sessionId == null || sessionId.size() == 0) { + Session createFromSessionId(byte[] sessionId) { + if (sessionId == null || sessionId.length == 0) { return null; } return new Session(sessionId); @@ -638,12 +743,20 @@ public final class MediaCas implements AutoCloseable { * @return Whether the specified CA system is supported on this device. */ public static boolean isSystemIdSupported(int CA_system_id) { - IMediaCasService service = getService(); - + IMediaCasService service = sService.get(); if (service != null) { try { return service.isSystemIdSupported(CA_system_id); } catch (RemoteException e) { + return false; + } + } + + android.hardware.cas.V1_0.IMediaCasService serviceHidl = sServiceHidl.get(); + if (serviceHidl != null) { + try { + return serviceHidl.isSystemIdSupported(CA_system_id); + } catch (RemoteException e) { } } return false; @@ -655,12 +768,26 @@ public final class MediaCas implements AutoCloseable { * @return an array of descriptors for the available CA plugins. */ public static PluginDescriptor[] enumeratePlugins() { - IMediaCasService service = getService(); - + IMediaCasService service = sService.get(); if (service != null) { try { - ArrayList<HidlCasPluginDescriptor> descriptors = - service.enumeratePlugins(); + AidlCasPluginDescriptor[] descriptors = service.enumeratePlugins(); + if (descriptors.length == 0) { + return null; + } + PluginDescriptor[] results = new PluginDescriptor[descriptors.length]; + for (int i = 0; i < results.length; i++) { + results[i] = new PluginDescriptor(descriptors[i]); + } + return results; + } catch (RemoteException e) { + } + } + + android.hardware.cas.V1_0.IMediaCasService serviceHidl = sServiceHidl.get(); + if (serviceHidl != null) { + try { + ArrayList<HidlCasPluginDescriptor> descriptors = serviceHidl.enumeratePlugins(); if (descriptors.size() == 0) { return null; } @@ -680,29 +807,40 @@ public final class MediaCas implements AutoCloseable { mCasSystemId = casSystemId; mUserId = Process.myUid(); IMediaCasService service = getService(); - android.hardware.cas.V1_2.IMediaCasService serviceV12 = - android.hardware.cas.V1_2.IMediaCasService.castFrom(service); - if (serviceV12 == null) { - android.hardware.cas.V1_1.IMediaCasService serviceV11 = - android.hardware.cas.V1_1.IMediaCasService.castFrom(service); - if (serviceV11 == null) { + if (service != null) { + Log.d(TAG, "Use CAS AIDL interface to create plugin"); + mICas = service.createPlugin(casSystemId, mBinder); + } else { + android.hardware.cas.V1_0.IMediaCasService serviceV10 = getServiceHidl(); + android.hardware.cas.V1_2.IMediaCasService serviceV12 = + android.hardware.cas.V1_2.IMediaCasService.castFrom(serviceV10); + if (serviceV12 == null) { + android.hardware.cas.V1_1.IMediaCasService serviceV11 = + android.hardware.cas.V1_1.IMediaCasService.castFrom(serviceV10); + if (serviceV11 == null) { Log.d(TAG, "Used cas@1_0 interface to create plugin"); - mICas = service.createPlugin(casSystemId, mBinder); - } else { + mICasHidl = serviceV10.createPlugin(casSystemId, mBinderHidl); + } else { Log.d(TAG, "Used cas@1.1 interface to create plugin"); - mICas = mICasV11 = serviceV11.createPluginExt(casSystemId, mBinder); + mICasHidl = + mICasHidl11 = serviceV11.createPluginExt(casSystemId, mBinderHidl); + } + } else { + Log.d(TAG, "Used cas@1.2 interface to create plugin"); + mICasHidl = + mICasHidl11 = + mICasHidl12 = + android.hardware.cas.V1_2.ICas.castFrom( + serviceV12.createPluginExt( + casSystemId, mBinderHidl)); } - } else { - Log.d(TAG, "Used cas@1.2 interface to create plugin"); - mICas = mICasV11 = mICasV12 = - android.hardware.cas.V1_2.ICas - .castFrom(serviceV12.createPluginExt(casSystemId, mBinder)); } } catch(Exception e) { Log.e(TAG, "Failed to create plugin: " + e); mICas = null; + mICasHidl = null; } finally { - if (mICas == null) { + if (mICas == null && mICasHidl == null) { throw new UnsupportedCasException( "Unsupported casSystemId " + casSystemId); } @@ -783,9 +921,22 @@ public final class MediaCas implements AutoCloseable { } IHwBinder getBinder() { + if (mICas != null) { + return null; // Return IHwBinder only for HIDL + } + validateInternalStates(); - return mICas.asBinder(); + return mICasHidl.asBinder(); + } + + /** + * Check if the HAL is an AIDL implementation + * + * @hide + */ + public boolean isAidlHal() { + return mICas != null; } /** @@ -886,8 +1037,12 @@ public final class MediaCas implements AutoCloseable { validateInternalStates(); try { - MediaCasException.throwExceptionIfNeeded( - mICas.setPrivateData(toByteArray(data, 0, data.length))); + if (mICas != null) { + mICas.setPrivateData(data); + } else { + MediaCasException.throwExceptionIfNeeded( + mICasHidl.setPrivateData(toByteArray(data, 0, data.length))); + } } catch (RemoteException e) { cleanupAndRethrowIllegalState(); } @@ -899,7 +1054,7 @@ public final class MediaCas implements AutoCloseable { @Override public void onValues(int status, ArrayList<Byte> sessionId) { mStatus = status; - mSession = createFromSessionId(sessionId); + mSession = createFromSessionId(toBytes(sessionId)); } } @@ -912,7 +1067,7 @@ public final class MediaCas implements AutoCloseable { @Override public void onValues(int status, ArrayList<Byte> sessionId) { mStatus = status; - mSession = createFromSessionId(sessionId); + mSession = createFromSessionId(toBytes(sessionId)); } } @@ -971,15 +1126,19 @@ public final class MediaCas implements AutoCloseable { int sessionResourceHandle = getSessionResourceHandle(); try { - OpenSessionCallback cb = new OpenSessionCallback(); - mICas.openSession(cb); - MediaCasException.throwExceptionIfNeeded(cb.mStatus); - addSessionToResourceMap(cb.mSession, sessionResourceHandle); - Log.d(TAG, "Write Stats Log for succeed to Open Session."); - FrameworkStatsLog - .write(FrameworkStatsLog.TV_CAS_SESSION_OPEN_STATUS, mUserId, mCasSystemId, + if (mICasHidl != null) { + OpenSessionCallback cb = new OpenSessionCallback(); + mICasHidl.openSession(cb); + MediaCasException.throwExceptionIfNeeded(cb.mStatus); + addSessionToResourceMap(cb.mSession, sessionResourceHandle); + Log.d(TAG, "Write Stats Log for succeed to Open Session."); + FrameworkStatsLog.write( + FrameworkStatsLog.TV_CAS_SESSION_OPEN_STATUS, + mUserId, + mCasSystemId, FrameworkStatsLog.TV_CAS_SESSION_OPEN_STATUS__STATE__SUCCEEDED); - return cb.mSession; + return cb.mSession; + } } catch (RemoteException e) { cleanupAndRethrowIllegalState(); } @@ -1012,14 +1171,30 @@ public final class MediaCas implements AutoCloseable { throws MediaCasException { int sessionResourceHandle = getSessionResourceHandle(); - if (mICasV12 == null) { + if (mICas != null) { + try { + byte[] sessionId = mICas.openSession(sessionUsage, scramblingMode); + Session session = createFromSessionId(sessionId); + addSessionToResourceMap(session, sessionResourceHandle); + Log.d(TAG, "Write Stats Log for succeed to Open Session."); + FrameworkStatsLog.write( + FrameworkStatsLog.TV_CAS_SESSION_OPEN_STATUS, + mUserId, + mCasSystemId, + FrameworkStatsLog.TV_CAS_SESSION_OPEN_STATUS__STATE__SUCCEEDED); + return session; + } catch (RemoteException e) { + cleanupAndRethrowIllegalState(); + } + } + if (mICasHidl12 == null) { Log.d(TAG, "Open Session with scrambling mode is only supported by cas@1.2+ interface"); throw new UnsupportedCasException("Open Session with scrambling mode is not supported"); } try { OpenSession_1_2_Callback cb = new OpenSession_1_2_Callback(); - mICasV12.openSession_1_2(sessionUsage, scramblingMode, cb); + mICasHidl12.openSession_1_2(sessionUsage, scramblingMode, cb); MediaCasException.throwExceptionIfNeeded(cb.mStatus); addSessionToResourceMap(cb.mSession, sessionResourceHandle); Log.d(TAG, "Write Stats Log for succeed to Open Session."); @@ -1053,8 +1228,12 @@ public final class MediaCas implements AutoCloseable { validateInternalStates(); try { - MediaCasException.throwExceptionIfNeeded( - mICas.processEmm(toByteArray(data, offset, length))); + if (mICas != null) { + mICas.processEmm(Arrays.copyOfRange(data, offset, length)); + } else { + MediaCasException.throwExceptionIfNeeded( + mICasHidl.processEmm(toByteArray(data, offset, length))); + } } catch (RemoteException e) { cleanupAndRethrowIllegalState(); } @@ -1092,8 +1271,12 @@ public final class MediaCas implements AutoCloseable { validateInternalStates(); try { - MediaCasException.throwExceptionIfNeeded( - mICas.sendEvent(event, arg, toByteArray(data))); + if (mICas != null) { + mICas.sendEvent(event, arg, data); + } else { + MediaCasException.throwExceptionIfNeeded( + mICasHidl.sendEvent(event, arg, toByteArray(data))); + } } catch (RemoteException e) { cleanupAndRethrowIllegalState(); } @@ -1114,8 +1297,11 @@ public final class MediaCas implements AutoCloseable { validateInternalStates(); try { - MediaCasException.throwExceptionIfNeeded( - mICas.provision(provisionString)); + if (mICas != null) { + mICas.provision(provisionString); + } else { + MediaCasException.throwExceptionIfNeeded(mICasHidl.provision(provisionString)); + } } catch (RemoteException e) { cleanupAndRethrowIllegalState(); } @@ -1136,8 +1322,12 @@ public final class MediaCas implements AutoCloseable { validateInternalStates(); try { - MediaCasException.throwExceptionIfNeeded( - mICas.refreshEntitlements(refreshType, toByteArray(refreshData))); + if (mICas != null) { + mICas.refreshEntitlements(refreshType, refreshData); + } else { + MediaCasException.throwExceptionIfNeeded( + mICasHidl.refreshEntitlements(refreshType, toByteArray(refreshData))); + } } catch (RemoteException e) { cleanupAndRethrowIllegalState(); } @@ -1163,6 +1353,13 @@ public final class MediaCas implements AutoCloseable { } finally { mICas = null; } + } else if (mICasHidl != null) { + try { + mICasHidl.release(); + } catch (RemoteException e) { + } finally { + mICasHidl = mICasHidl11 = mICasHidl12 = null; + } } if (mTunerResourceManager != null) { diff --git a/media/java/android/media/MediaDescrambler.java b/media/java/android/media/MediaDescrambler.java index 99bd2549cbc7..b4bdf93db3ab 100644 --- a/media/java/android/media/MediaDescrambler.java +++ b/media/java/android/media/MediaDescrambler.java @@ -17,14 +17,26 @@ package android.media; import android.annotation.NonNull; -import android.hardware.cas.V1_0.*; +import android.hardware.cas.DestinationBuffer; +import android.hardware.cas.IDescrambler; +import android.hardware.cas.ScramblingControl; +import android.hardware.cas.SharedBuffer; +import android.hardware.cas.SubSample; +import android.hardware.cas.V1_0.IDescramblerBase; +import android.hardware.common.Ashmem; +import android.hardware.common.NativeHandle; import android.media.MediaCasException.UnsupportedCasException; import android.os.IHwBinder; +import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.os.ServiceSpecificException; +import android.os.SharedMemory; +import android.system.ErrnoException; import android.util.Log; +import java.io.IOException; import java.nio.ByteBuffer; +import java.util.ArrayList; /** * MediaDescrambler class can be used in conjunction with {@link android.media.MediaCodec} @@ -39,7 +51,198 @@ import java.nio.ByteBuffer; */ public final class MediaDescrambler implements AutoCloseable { private static final String TAG = "MediaDescrambler"; - private IDescramblerBase mIDescrambler; + private DescramblerWrapper mIDescrambler; + + private interface DescramblerWrapper { + + IHwBinder asBinder(); + + int descramble( + @NonNull ByteBuffer srcBuf, + @NonNull ByteBuffer dstBuf, + @NonNull MediaCodec.CryptoInfo cryptoInfo) + throws RemoteException; + + boolean requiresSecureDecoderComponent(@NonNull String mime) throws RemoteException; + + void setMediaCasSession(byte[] sessionId) throws RemoteException; + + void release() throws RemoteException; + } + ; + + private long getSubsampleInfo( + int numSubSamples, + int[] numBytesOfClearData, + int[] numBytesOfEncryptedData, + SubSample[] subSamples) { + long totalSize = 0; + + for (int i = 0; i < numSubSamples; i++) { + totalSize += numBytesOfClearData[i]; + subSamples[i].numBytesOfClearData = numBytesOfClearData[i]; + totalSize += numBytesOfEncryptedData[i]; + subSamples[i].numBytesOfEncryptedData = numBytesOfEncryptedData[i]; + } + return totalSize; + } + + private ParcelFileDescriptor createSharedMemory(ByteBuffer buffer, String name) + throws RemoteException { + byte[] source = buffer.array(); + if (source.length == 0) { + return null; + } + ParcelFileDescriptor fd = null; + try { + SharedMemory ashmem = SharedMemory.create(name == null ? "" : name, source.length); + ByteBuffer ptr = ashmem.mapReadWrite(); + ptr.put(buffer); + ashmem.unmap(ptr); + fd = ashmem.getFdDup(); + return fd; + } catch (ErrnoException | IOException e) { + throw new RemoteException(e); + } + } + + private class AidlDescrambler implements DescramblerWrapper { + + IDescrambler mAidlDescrambler; + + AidlDescrambler(IDescrambler aidlDescrambler) { + mAidlDescrambler = aidlDescrambler; + } + + @Override + public IHwBinder asBinder() { + return null; + } + + @Override + public int descramble( + @NonNull ByteBuffer src, + @NonNull ByteBuffer dst, + @NonNull MediaCodec.CryptoInfo cryptoInfo) + throws RemoteException { + SubSample[] subSamples = new SubSample[cryptoInfo.numSubSamples]; + long totalLength = + getSubsampleInfo( + cryptoInfo.numSubSamples, + cryptoInfo.numBytesOfClearData, + cryptoInfo.numBytesOfEncryptedData, + subSamples); + SharedBuffer srcBuffer = new SharedBuffer(); + DestinationBuffer dstBuffer; + srcBuffer.heapBase = new Ashmem(); + srcBuffer.heapBase.fd = createSharedMemory(src, "Descrambler Source Buffer"); + srcBuffer.heapBase.size = src.array().length; + if (dst == null) { + dstBuffer = DestinationBuffer.nonsecureMemory(srcBuffer); + } else { + ParcelFileDescriptor pfd = + createSharedMemory(dst, "Descrambler Destination Buffer"); + NativeHandle nh = new NativeHandle(); + nh.fds = new ParcelFileDescriptor[] {pfd}; + nh.ints = new int[] {1}; // Mark 1 since source buffer also uses it? + dstBuffer = DestinationBuffer.secureMemory(nh); + } + @ScramblingControl int control = cryptoInfo.key[0]; + + return mAidlDescrambler.descramble( + (byte) control, + subSamples, + srcBuffer, + src.position(), + dstBuffer, + dst.position()); + } + + @Override + public boolean requiresSecureDecoderComponent(@NonNull String mime) throws RemoteException { + return mAidlDescrambler.requiresSecureDecoderComponent(mime); + } + + @Override + public void setMediaCasSession(byte[] sessionId) throws RemoteException { + mAidlDescrambler.setMediaCasSession(sessionId); + } + + @Override + public void release() throws RemoteException { + mAidlDescrambler.release(); + } + } + + private class HidlDescrambler implements DescramblerWrapper { + + IDescramblerBase mHidlDescrambler; + + HidlDescrambler(IDescramblerBase hidlDescrambler) { + mHidlDescrambler = hidlDescrambler; + native_setup(hidlDescrambler.asBinder()); + } + + @Override + public IHwBinder asBinder() { + return mHidlDescrambler.asBinder(); + } + + @Override + public int descramble( + @NonNull ByteBuffer srcBuf, + @NonNull ByteBuffer dstBuf, + @NonNull MediaCodec.CryptoInfo cryptoInfo) + throws RemoteException { + + try { + return native_descramble( + cryptoInfo.key[0], + cryptoInfo.key[1], + cryptoInfo.numSubSamples, + cryptoInfo.numBytesOfClearData, + cryptoInfo.numBytesOfEncryptedData, + srcBuf, + srcBuf.position(), + srcBuf.limit(), + dstBuf, + dstBuf.position(), + dstBuf.limit()); + } catch (ServiceSpecificException e) { + MediaCasStateException.throwExceptionIfNeeded(e.errorCode, e.getMessage()); + } catch (RemoteException e) { + cleanupAndRethrowIllegalState(); + } + return -1; + } + + @Override + public boolean requiresSecureDecoderComponent(@NonNull String mime) throws RemoteException { + return mHidlDescrambler.requiresSecureDecoderComponent(mime); + } + + @Override + public void setMediaCasSession(byte[] sessionId) throws RemoteException { + ArrayList<Byte> byteArray = new ArrayList<>(); + + if (sessionId != null) { + int length = sessionId.length; + byteArray = new ArrayList<Byte>(length); + for (int i = 0; i < length; i++) { + byteArray.add(Byte.valueOf(sessionId[i])); + } + } + + MediaCasStateException.throwExceptionIfNeeded( + mHidlDescrambler.setMediaCasSession(byteArray)); + } + + @Override + public void release() throws RemoteException { + mHidlDescrambler.release(); + native_release(); + } + } private final void validateInternalStates() { if (mIDescrambler == null) { @@ -61,7 +264,14 @@ public final class MediaDescrambler implements AutoCloseable { */ public MediaDescrambler(int CA_system_id) throws UnsupportedCasException { try { - mIDescrambler = MediaCas.getService().createDescrambler(CA_system_id); + if (MediaCas.getService() != null) { + mIDescrambler = + new AidlDescrambler(MediaCas.getService().createDescrambler(CA_system_id)); + } else if (MediaCas.getServiceHidl() != null) { + mIDescrambler = + new HidlDescrambler( + MediaCas.getServiceHidl().createDescrambler(CA_system_id)); + } } catch(Exception e) { Log.e(TAG, "Failed to create descrambler: " + e); mIDescrambler = null; @@ -70,7 +280,6 @@ public final class MediaDescrambler implements AutoCloseable { throw new UnsupportedCasException("Unsupported CA_system_id " + CA_system_id); } } - native_setup(mIDescrambler.asBinder()); } IHwBinder getBinder() { @@ -117,8 +326,7 @@ public final class MediaDescrambler implements AutoCloseable { validateInternalStates(); try { - MediaCasStateException.throwExceptionIfNeeded( - mIDescrambler.setMediaCasSession(session.mSessionId)); + mIDescrambler.setMediaCasSession(session.mSessionId); } catch (RemoteException e) { cleanupAndRethrowIllegalState(); } @@ -126,27 +334,31 @@ public final class MediaDescrambler implements AutoCloseable { /** * Scramble control value indicating that the samples are not scrambled. + * * @see #descramble(ByteBuffer, ByteBuffer, android.media.MediaCodec.CryptoInfo) */ - public static final byte SCRAMBLE_CONTROL_UNSCRAMBLED = 0; + public static final byte SCRAMBLE_CONTROL_UNSCRAMBLED = (byte) ScramblingControl.UNSCRAMBLED; /** * Scramble control value reserved and shouldn't be used currently. + * * @see #descramble(ByteBuffer, ByteBuffer, android.media.MediaCodec.CryptoInfo) */ - public static final byte SCRAMBLE_CONTROL_RESERVED = 1; + public static final byte SCRAMBLE_CONTROL_RESERVED = (byte) ScramblingControl.RESERVED; /** * Scramble control value indicating that the even key is used. + * * @see #descramble(ByteBuffer, ByteBuffer, android.media.MediaCodec.CryptoInfo) */ - public static final byte SCRAMBLE_CONTROL_EVEN_KEY = 2; + public static final byte SCRAMBLE_CONTROL_EVEN_KEY = (byte) ScramblingControl.EVENKEY; /** * Scramble control value indicating that the odd key is used. + * * @see #descramble(ByteBuffer, ByteBuffer, android.media.MediaCodec.CryptoInfo) */ - public static final byte SCRAMBLE_CONTROL_ODD_KEY = 3; + public static final byte SCRAMBLE_CONTROL_ODD_KEY = (byte) ScramblingControl.ODDKEY; /** * Scramble flag for a hint indicating that the descrambling request is for @@ -207,14 +419,7 @@ public final class MediaDescrambler implements AutoCloseable { } try { - return native_descramble( - cryptoInfo.key[0], - cryptoInfo.key[1], - cryptoInfo.numSubSamples, - cryptoInfo.numBytesOfClearData, - cryptoInfo.numBytesOfEncryptedData, - srcBuf, srcBuf.position(), srcBuf.limit(), - dstBuf, dstBuf.position(), dstBuf.limit()); + return mIDescrambler.descramble(srcBuf, dstBuf, cryptoInfo); } catch (ServiceSpecificException e) { MediaCasStateException.throwExceptionIfNeeded(e.errorCode, e.getMessage()); } catch (RemoteException e) { @@ -233,7 +438,6 @@ public final class MediaDescrambler implements AutoCloseable { mIDescrambler = null; } } - native_release(); } @Override @@ -256,4 +460,4 @@ public final class MediaDescrambler implements AutoCloseable { } private long mNativeContext; -}
\ No newline at end of file +} diff --git a/media/java/android/media/MediaExtractor.java b/media/java/android/media/MediaExtractor.java index dab188e40c1f..b11a81047bf8 100644 --- a/media/java/android/media/MediaExtractor.java +++ b/media/java/android/media/MediaExtractor.java @@ -36,7 +36,6 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.nio.ByteBuffer; import java.nio.ByteOrder; -import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; @@ -325,14 +324,6 @@ public final class MediaExtractor { } } - private ArrayList<Byte> toByteArray(@NonNull byte[] data) { - ArrayList<Byte> byteArray = new ArrayList<Byte>(data.length); - for (int i = 0; i < data.length; i++) { - byteArray.add(i, Byte.valueOf(data[i])); - } - return byteArray; - } - /** * Retrieves the information about the conditional access system used to scramble * a track. @@ -357,7 +348,7 @@ public final class MediaExtractor { buf.rewind(); final byte[] sessionId = new byte[buf.remaining()]; buf.get(sessionId); - session = mMediaCas.createFromSessionId(toByteArray(sessionId)); + session = mMediaCas.createFromSessionId(sessionId); } return new CasInfo(systemId, session, privateData); } |