Loading Android.mk +2 −4 Original line number Diff line number Diff line Loading @@ -438,10 +438,6 @@ LOCAL_SRC_FILES += \ location/java/android/location/INetInitiatedListener.aidl \ location/java/com/android/internal/location/ILocationProvider.aidl \ media/java/android/media/IAudioService.aidl \ ../av/drm/libmediadrm/aidl/android/media/ICas.aidl \ ../av/drm/libmediadrm/aidl/android/media/ICasListener.aidl \ ../av/drm/libmediadrm/aidl/android/media/IDescrambler.aidl \ ../av/drm/libmediadrm/aidl/android/media/IMediaCasService.aidl \ media/java/android/media/IAudioFocusDispatcher.aidl \ media/java/android/media/IAudioRoutesObserver.aidl \ media/java/android/media/IMediaHTTPConnection.aidl \ Loading Loading @@ -614,6 +610,8 @@ LOCAL_STATIC_JAVA_LIBRARIES := \ android.hardware.vibrator-V1.1-java-constants \ android.hardware.wifi-V1.0-java-constants \ include hardware/interfaces/cas/1.0/CasHal.mk # Loaded with System.loadLibrary by android.view.textclassifier LOCAL_REQUIRED_MODULES += libtextclassifier Loading media/java/android/media/MediaCas.java +78 −130 Original line number Diff line number Diff line Loading @@ -18,21 +18,20 @@ package android.media; import android.annotation.NonNull; import android.annotation.Nullable; import android.hardware.cas.V1_0.*; import android.media.MediaCasException.*; import android.os.Handler; import android.os.HandlerThread; import android.os.IBinder; import android.os.IHwBinder; import android.os.Looper; import android.os.Message; import android.os.Parcel; import android.os.Parcelable; import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; import android.os.ServiceSpecificException; import android.util.Log; import android.util.Singleton; import java.util.ArrayList; /** * MediaCas can be used to obtain keys for descrambling protected media streams, in * conjunction with {@link android.media.MediaDescrambler}. The MediaCas APIs are Loading Loading @@ -95,7 +94,6 @@ import android.util.Singleton; */ public final class MediaCas implements AutoCloseable { private static final String TAG = "MediaCas"; private final ParcelableCasData mCasData = new ParcelableCasData(); private ICas mICas; private EventListener mListener; private HandlerThread mHandlerThread; Loading @@ -105,8 +103,10 @@ public final class MediaCas implements AutoCloseable { new Singleton<IMediaCasService>() { @Override protected IMediaCasService create() { return IMediaCasService.Stub.asInterface( ServiceManager.getService("media.cas")); try { return IMediaCasService.getService(); } catch (RemoteException e) {} return null; } }; Loading Loading @@ -136,65 +136,21 @@ public final class MediaCas implements AutoCloseable { @Override public void handleMessage(Message msg) { if (msg.what == MSG_CAS_EVENT) { mListener.onEvent(MediaCas.this, msg.arg1, msg.arg2, (byte[]) msg.obj); mListener.onEvent(MediaCas.this, msg.arg1, msg.arg2, toBytes((ArrayList<Byte>) msg.obj)); } } } private final ICasListener.Stub mBinder = new ICasListener.Stub() { @Override public void onEvent(int event, int arg, @Nullable byte[] data) public void onEvent(int event, int arg, @Nullable ArrayList<Byte> data) throws RemoteException { mEventHandler.sendMessage(mEventHandler.obtainMessage( EventHandler.MSG_CAS_EVENT, event, arg, data)); } }; /** * Class for parceling byte array data over ICas binder. */ static class ParcelableCasData implements Parcelable { private byte[] mData; private int mOffset; private int mLength; ParcelableCasData() { mData = null; mOffset = mLength = 0; } private ParcelableCasData(Parcel in) { this(); } void set(@NonNull byte[] data, int offset, int length) { mData = data; mOffset = offset; mLength = length; } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeByteArray(mData, mOffset, mLength); } public static final Parcelable.Creator<ParcelableCasData> CREATOR = new Parcelable.Creator<ParcelableCasData>() { public ParcelableCasData createFromParcel(Parcel in) { return new ParcelableCasData(in); } public ParcelableCasData[] newArray(int size) { return new ParcelableCasData[size]; } }; } /** * Describe a CAS plugin with its CA_system_ID and string name. * Loading @@ -210,9 +166,9 @@ public final class MediaCas implements AutoCloseable { mName = null; } PluginDescriptor(int CA_system_id, String name) { mCASystemId = CA_system_id; mName = name; PluginDescriptor(@NonNull HidlCasPluginDescriptor descriptor) { mCASystemId = descriptor.caSystemId; mName = descriptor.name; } public int getSystemId() { Loading @@ -230,13 +186,38 @@ public final class MediaCas implements AutoCloseable { } } private ArrayList<Byte> toByteArray(@NonNull byte[] data, int offset, int length) { ArrayList<Byte> byteArray = new ArrayList<Byte>(length); for (int i = 0; i < length; i++) { byteArray.add(Byte.valueOf(data[offset + i])); } return byteArray; } private ArrayList<Byte> toByteArray(@Nullable byte[] data) { if (data == null) { return new ArrayList<Byte>(); } return toByteArray(data, 0, data.length); } private byte[] toBytes(@NonNull ArrayList<Byte> byteArray) { byte[] data = null; if (byteArray != null) { data = new byte[byteArray.size()]; for (int i = 0; i < data.length; i++) { data[i] = byteArray.get(i); } } return data; } /** * Class for an open session with the CA system. */ public final class Session implements AutoCloseable { final byte[] mSessionId; final ArrayList<Byte> mSessionId; Session(@NonNull byte[] sessionId) { Session(@NonNull ArrayList<Byte> sessionId) { mSessionId = sessionId; } Loading @@ -254,9 +235,8 @@ public final class MediaCas implements AutoCloseable { validateInternalStates(); try { mICas.setSessionPrivateData(mSessionId, data); } catch (ServiceSpecificException e) { MediaCasException.throwExceptions(e); MediaCasException.throwExceptionIfNeeded( mICas.setSessionPrivateData(mSessionId, toByteArray(data, 0, data.length))); } catch (RemoteException e) { cleanupAndRethrowIllegalState(); } Loading @@ -279,10 +259,8 @@ public final class MediaCas implements AutoCloseable { validateInternalStates(); try { mCasData.set(data, offset, length); mICas.processEcm(mSessionId, mCasData); } catch (ServiceSpecificException e) { MediaCasException.throwExceptions(e); MediaCasException.throwExceptionIfNeeded( mICas.processEcm(mSessionId, toByteArray(data, offset, length))); } catch (RemoteException e) { cleanupAndRethrowIllegalState(); } Loading Loading @@ -314,56 +292,21 @@ public final class MediaCas implements AutoCloseable { validateInternalStates(); try { mICas.closeSession(mSessionId); } catch (ServiceSpecificException e) { MediaCasStateException.throwExceptions(e); MediaCasStateException.throwExceptionIfNeeded( mICas.closeSession(mSessionId)); } catch (RemoteException e) { cleanupAndRethrowIllegalState(); } } } Session createFromSessionId(byte[] sessionId) { if (sessionId == null || sessionId.length == 0) { Session createFromSessionId(@NonNull ArrayList<Byte> sessionId) { if (sessionId == null || sessionId.size() == 0) { return null; } return new Session(sessionId); } /** * Class for parceling CAS plugin descriptors over IMediaCasService binder. */ static class ParcelableCasPluginDescriptor extends PluginDescriptor implements Parcelable { private ParcelableCasPluginDescriptor(int CA_system_id, String name) { super(CA_system_id, name); } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { Log.w(TAG, "ParcelableCasPluginDescriptor.writeToParcel shouldn't be called!"); } public static final Parcelable.Creator<ParcelableCasPluginDescriptor> CREATOR = new Parcelable.Creator<ParcelableCasPluginDescriptor>() { public ParcelableCasPluginDescriptor createFromParcel(Parcel in) { int CA_system_id = in.readInt(); String name = in.readString(); return new ParcelableCasPluginDescriptor(CA_system_id, name); } public ParcelableCasPluginDescriptor[] newArray(int size) { return new ParcelableCasPluginDescriptor[size]; } }; } /** * Query if a certain CA system is supported on this device. * Loading Loading @@ -393,13 +336,14 @@ public final class MediaCas implements AutoCloseable { if (service != null) { try { ParcelableCasPluginDescriptor[] descriptors = service.enumeratePlugins(); if (descriptors.length == 0) { ArrayList<HidlCasPluginDescriptor> descriptors = service.enumeratePlugins(); if (descriptors.size() == 0) { return null; } PluginDescriptor[] results = new PluginDescriptor[descriptors.length]; PluginDescriptor[] results = new PluginDescriptor[descriptors.size()]; for (int i = 0; i < results.length; i++) { results[i] = descriptors[i]; results[i] = new PluginDescriptor(descriptors.get(i)); } return results; } catch (RemoteException e) { Loading Loading @@ -430,7 +374,7 @@ public final class MediaCas implements AutoCloseable { } } IBinder getBinder() { IHwBinder getBinder() { validateInternalStates(); return mICas.asBinder(); Loading Loading @@ -497,14 +441,22 @@ public final class MediaCas implements AutoCloseable { validateInternalStates(); try { mICas.setPrivateData(data); } catch (ServiceSpecificException e) { MediaCasException.throwExceptions(e); MediaCasException.throwExceptionIfNeeded( mICas.setPrivateData(toByteArray(data, 0, data.length))); } catch (RemoteException e) { cleanupAndRethrowIllegalState(); } } private class OpenSessionCallback implements ICas.openSessionCallback { public Session mSession; public int mStatus; @Override public void onValues(int status, ArrayList<Byte> sessionId) { mStatus = status; mSession = createFromSessionId(sessionId); } } /** * Open a session to descramble one or more streams scrambled by the * conditional access system. Loading @@ -519,9 +471,10 @@ public final class MediaCas implements AutoCloseable { validateInternalStates(); try { return createFromSessionId(mICas.openSession()); } catch (ServiceSpecificException e) { MediaCasException.throwExceptions(e); OpenSessionCallback cb = new OpenSessionCallback(); mICas.openSession(cb); MediaCasException.throwExceptionIfNeeded(cb.mStatus); return cb.mSession; } catch (RemoteException e) { cleanupAndRethrowIllegalState(); } Loading @@ -544,10 +497,8 @@ public final class MediaCas implements AutoCloseable { validateInternalStates(); try { mCasData.set(data, offset, length); mICas.processEmm(mCasData); } catch (ServiceSpecificException e) { MediaCasException.throwExceptions(e); MediaCasException.throwExceptionIfNeeded( mICas.processEmm(toByteArray(data, offset, length))); } catch (RemoteException e) { cleanupAndRethrowIllegalState(); } Loading Loading @@ -585,9 +536,8 @@ public final class MediaCas implements AutoCloseable { validateInternalStates(); try { mICas.sendEvent(event, arg, data); } catch (ServiceSpecificException e) { MediaCasException.throwExceptions(e); MediaCasException.throwExceptionIfNeeded( mICas.sendEvent(event, arg, toByteArray(data))); } catch (RemoteException e) { cleanupAndRethrowIllegalState(); } Loading @@ -608,9 +558,8 @@ public final class MediaCas implements AutoCloseable { validateInternalStates(); try { mICas.provision(provisionString); } catch (ServiceSpecificException e) { MediaCasException.throwExceptions(e); MediaCasException.throwExceptionIfNeeded( mICas.provision(provisionString)); } catch (RemoteException e) { cleanupAndRethrowIllegalState(); } Loading @@ -631,9 +580,8 @@ public final class MediaCas implements AutoCloseable { validateInternalStates(); try { mICas.refreshEntitlements(refreshType, refreshData); } catch (ServiceSpecificException e) { MediaCasException.throwExceptions(e); MediaCasException.throwExceptionIfNeeded( mICas.refreshEntitlements(refreshType, toByteArray(refreshData))); } catch (RemoteException e) { cleanupAndRethrowIllegalState(); } Loading media/java/android/media/MediaCasException.java +14 −45 Original line number Diff line number Diff line Loading @@ -16,60 +16,29 @@ package android.media; import android.os.ServiceSpecificException; import android.hardware.cas.V1_0.Status; /** * Base class for MediaCas exceptions */ public class MediaCasException extends Exception { /** @hide */ public static final int DRM_ERROR_BASE = -2000; /** @hide */ public static final int ERROR_DRM_UNKNOWN = DRM_ERROR_BASE; /** @hide */ public static final int ERROR_DRM_NO_LICENSE = DRM_ERROR_BASE - 1; /** @hide */ public static final int ERROR_DRM_LICENSE_EXPIRED = DRM_ERROR_BASE - 2; /** @hide */ public static final int ERROR_DRM_SESSION_NOT_OPENED = DRM_ERROR_BASE - 3; /** @hide */ public static final int ERROR_DRM_DECRYPT_UNIT_NOT_INITIALIZED = DRM_ERROR_BASE - 4; /** @hide */ public static final int ERROR_DRM_DECRYPT = DRM_ERROR_BASE - 5; /** @hide */ public static final int ERROR_DRM_CANNOT_HANDLE = DRM_ERROR_BASE - 6; /** @hide */ public static final int ERROR_DRM_TAMPER_DETECTED = DRM_ERROR_BASE - 7; /** @hide */ public static final int ERROR_DRM_NOT_PROVISIONED = DRM_ERROR_BASE - 8; /** @hide */ public static final int ERROR_DRM_DEVICE_REVOKED = DRM_ERROR_BASE - 9; /** @hide */ public static final int ERROR_DRM_RESOURCE_BUSY = DRM_ERROR_BASE - 10; /** @hide */ public static final int ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION = DRM_ERROR_BASE - 11; /** @hide */ public static final int ERROR_DRM_LAST_USED_ERRORCODE = DRM_ERROR_BASE - 11; /** @hide */ public static final int ERROR_DRM_VENDOR_MAX = DRM_ERROR_BASE - 500; /** @hide */ public static final int ERROR_DRM_VENDOR_MIN = DRM_ERROR_BASE - 999; /** @hide */ public MediaCasException(String detailMessage) { private MediaCasException(String detailMessage) { super(detailMessage); } static void throwExceptions(ServiceSpecificException e) throws MediaCasException { if (e.errorCode == ERROR_DRM_NOT_PROVISIONED) { throw new NotProvisionedException(e.getMessage()); } else if (e.errorCode == ERROR_DRM_RESOURCE_BUSY) { throw new ResourceBusyException(e.getMessage()); } else if (e.errorCode == ERROR_DRM_DEVICE_REVOKED) { throw new DeniedByServerException(e.getMessage()); static void throwExceptionIfNeeded(int error) throws MediaCasException { if (error == Status.OK) { return; } if (error == Status.ERROR_CAS_NOT_PROVISIONED) { throw new NotProvisionedException(null); } else if (error == Status.ERROR_CAS_RESOURCE_BUSY) { throw new ResourceBusyException(null); } else if (error == Status.ERROR_CAS_DEVICE_REVOKED) { throw new DeniedByServerException(null); } else { MediaCasStateException.throwExceptions(e); MediaCasStateException.throwExceptionIfNeeded(error); } } Loading media/java/android/media/MediaCasStateException.java +34 −19 Original line number Diff line number Diff line Loading @@ -18,9 +18,8 @@ package android.media; import android.annotation.NonNull; import android.annotation.Nullable; import android.os.ServiceSpecificException; import static android.media.MediaCasException.*; import android.hardware.cas.V1_0.Status; /** * Base class for MediaCas runtime exceptions Loading @@ -29,46 +28,62 @@ public class MediaCasStateException extends IllegalStateException { private final int mErrorCode; private final String mDiagnosticInfo; /** @hide */ public MediaCasStateException(int err, @Nullable String msg, @Nullable String diagnosticInfo) { private MediaCasStateException(int err, @Nullable String msg, @Nullable String diagnosticInfo) { super(msg); mErrorCode = err; mDiagnosticInfo = diagnosticInfo; } static void throwExceptions(ServiceSpecificException e) { static void throwExceptionIfNeeded(int err) { throwExceptionIfNeeded(err, null /* msg */); } static void throwExceptionIfNeeded(int err, @Nullable String msg) { if (err == Status.OK) { return; } if (err == Status.BAD_VALUE) { throw new IllegalArgumentException(); } String diagnosticInfo = ""; switch (e.errorCode) { case ERROR_DRM_UNKNOWN: switch (err) { case Status.ERROR_CAS_UNKNOWN: diagnosticInfo = "General CAS error"; break; case ERROR_DRM_NO_LICENSE: case Status.ERROR_CAS_NO_LICENSE: diagnosticInfo = "No license"; break; case ERROR_DRM_LICENSE_EXPIRED: case Status.ERROR_CAS_LICENSE_EXPIRED: diagnosticInfo = "License expired"; break; case ERROR_DRM_SESSION_NOT_OPENED: case Status.ERROR_CAS_SESSION_NOT_OPENED: diagnosticInfo = "Session not opened"; break; case ERROR_DRM_DECRYPT_UNIT_NOT_INITIALIZED: diagnosticInfo = "Not initialized"; case Status.ERROR_CAS_CANNOT_HANDLE: diagnosticInfo = "Unsupported scheme or data format"; break; case ERROR_DRM_DECRYPT: diagnosticInfo = "Decrypt error"; case Status.ERROR_CAS_INVALID_STATE: diagnosticInfo = "Invalid CAS state"; break; case ERROR_DRM_CANNOT_HANDLE: diagnosticInfo = "Unsupported scheme or data format"; case Status.ERROR_CAS_INSUFFICIENT_OUTPUT_PROTECTION: diagnosticInfo = "Insufficient output protection"; break; case ERROR_DRM_TAMPER_DETECTED: case Status.ERROR_CAS_TAMPER_DETECTED: diagnosticInfo = "Tamper detected"; break; case Status.ERROR_CAS_DECRYPT_UNIT_NOT_INITIALIZED: diagnosticInfo = "Not initialized"; break; case Status.ERROR_CAS_DECRYPT: diagnosticInfo = "Decrypt error"; break; default: diagnosticInfo = "Unknown CAS state exception"; break; } throw new MediaCasStateException(e.errorCode, e.getMessage(), String.format("%s (err=%d)", diagnosticInfo, e.errorCode)); throw new MediaCasStateException(err, msg, String.format("%s (err=%d)", diagnosticInfo, err)); } /** Loading media/java/android/media/MediaCodec.java +3 −2 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ import android.media.MediaCodecInfo.CodecCapabilities; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.IHwBinder; import android.os.Looper; import android.os.Message; import android.os.PersistableBundle; Loading Loading @@ -1903,7 +1904,7 @@ final public class MediaCodec { private void configure( @Nullable MediaFormat format, @Nullable Surface surface, @Nullable MediaCrypto crypto, @Nullable IBinder descramblerBinder, @Nullable MediaCrypto crypto, @Nullable IHwBinder descramblerBinder, @ConfigureFlag int flags) { if (crypto != null && descramblerBinder != null) { throw new IllegalArgumentException("Can't use crypto and descrambler together!"); Loading Loading @@ -2018,7 +2019,7 @@ final public class MediaCodec { private native final void native_configure( @Nullable String[] keys, @Nullable Object[] values, @Nullable Surface surface, @Nullable MediaCrypto crypto, @Nullable IBinder descramblerBinder, @ConfigureFlag int flags); @Nullable IHwBinder descramblerBinder, @ConfigureFlag int flags); /** * Requests a Surface to use as the input to an encoder, in place of input buffers. This Loading Loading
Android.mk +2 −4 Original line number Diff line number Diff line Loading @@ -438,10 +438,6 @@ LOCAL_SRC_FILES += \ location/java/android/location/INetInitiatedListener.aidl \ location/java/com/android/internal/location/ILocationProvider.aidl \ media/java/android/media/IAudioService.aidl \ ../av/drm/libmediadrm/aidl/android/media/ICas.aidl \ ../av/drm/libmediadrm/aidl/android/media/ICasListener.aidl \ ../av/drm/libmediadrm/aidl/android/media/IDescrambler.aidl \ ../av/drm/libmediadrm/aidl/android/media/IMediaCasService.aidl \ media/java/android/media/IAudioFocusDispatcher.aidl \ media/java/android/media/IAudioRoutesObserver.aidl \ media/java/android/media/IMediaHTTPConnection.aidl \ Loading Loading @@ -614,6 +610,8 @@ LOCAL_STATIC_JAVA_LIBRARIES := \ android.hardware.vibrator-V1.1-java-constants \ android.hardware.wifi-V1.0-java-constants \ include hardware/interfaces/cas/1.0/CasHal.mk # Loaded with System.loadLibrary by android.view.textclassifier LOCAL_REQUIRED_MODULES += libtextclassifier Loading
media/java/android/media/MediaCas.java +78 −130 Original line number Diff line number Diff line Loading @@ -18,21 +18,20 @@ package android.media; import android.annotation.NonNull; import android.annotation.Nullable; import android.hardware.cas.V1_0.*; import android.media.MediaCasException.*; import android.os.Handler; import android.os.HandlerThread; import android.os.IBinder; import android.os.IHwBinder; import android.os.Looper; import android.os.Message; import android.os.Parcel; import android.os.Parcelable; import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; import android.os.ServiceSpecificException; import android.util.Log; import android.util.Singleton; import java.util.ArrayList; /** * MediaCas can be used to obtain keys for descrambling protected media streams, in * conjunction with {@link android.media.MediaDescrambler}. The MediaCas APIs are Loading Loading @@ -95,7 +94,6 @@ import android.util.Singleton; */ public final class MediaCas implements AutoCloseable { private static final String TAG = "MediaCas"; private final ParcelableCasData mCasData = new ParcelableCasData(); private ICas mICas; private EventListener mListener; private HandlerThread mHandlerThread; Loading @@ -105,8 +103,10 @@ public final class MediaCas implements AutoCloseable { new Singleton<IMediaCasService>() { @Override protected IMediaCasService create() { return IMediaCasService.Stub.asInterface( ServiceManager.getService("media.cas")); try { return IMediaCasService.getService(); } catch (RemoteException e) {} return null; } }; Loading Loading @@ -136,65 +136,21 @@ public final class MediaCas implements AutoCloseable { @Override public void handleMessage(Message msg) { if (msg.what == MSG_CAS_EVENT) { mListener.onEvent(MediaCas.this, msg.arg1, msg.arg2, (byte[]) msg.obj); mListener.onEvent(MediaCas.this, msg.arg1, msg.arg2, toBytes((ArrayList<Byte>) msg.obj)); } } } private final ICasListener.Stub mBinder = new ICasListener.Stub() { @Override public void onEvent(int event, int arg, @Nullable byte[] data) public void onEvent(int event, int arg, @Nullable ArrayList<Byte> data) throws RemoteException { mEventHandler.sendMessage(mEventHandler.obtainMessage( EventHandler.MSG_CAS_EVENT, event, arg, data)); } }; /** * Class for parceling byte array data over ICas binder. */ static class ParcelableCasData implements Parcelable { private byte[] mData; private int mOffset; private int mLength; ParcelableCasData() { mData = null; mOffset = mLength = 0; } private ParcelableCasData(Parcel in) { this(); } void set(@NonNull byte[] data, int offset, int length) { mData = data; mOffset = offset; mLength = length; } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeByteArray(mData, mOffset, mLength); } public static final Parcelable.Creator<ParcelableCasData> CREATOR = new Parcelable.Creator<ParcelableCasData>() { public ParcelableCasData createFromParcel(Parcel in) { return new ParcelableCasData(in); } public ParcelableCasData[] newArray(int size) { return new ParcelableCasData[size]; } }; } /** * Describe a CAS plugin with its CA_system_ID and string name. * Loading @@ -210,9 +166,9 @@ public final class MediaCas implements AutoCloseable { mName = null; } PluginDescriptor(int CA_system_id, String name) { mCASystemId = CA_system_id; mName = name; PluginDescriptor(@NonNull HidlCasPluginDescriptor descriptor) { mCASystemId = descriptor.caSystemId; mName = descriptor.name; } public int getSystemId() { Loading @@ -230,13 +186,38 @@ public final class MediaCas implements AutoCloseable { } } private ArrayList<Byte> toByteArray(@NonNull byte[] data, int offset, int length) { ArrayList<Byte> byteArray = new ArrayList<Byte>(length); for (int i = 0; i < length; i++) { byteArray.add(Byte.valueOf(data[offset + i])); } return byteArray; } private ArrayList<Byte> toByteArray(@Nullable byte[] data) { if (data == null) { return new ArrayList<Byte>(); } return toByteArray(data, 0, data.length); } private byte[] toBytes(@NonNull ArrayList<Byte> byteArray) { byte[] data = null; if (byteArray != null) { data = new byte[byteArray.size()]; for (int i = 0; i < data.length; i++) { data[i] = byteArray.get(i); } } return data; } /** * Class for an open session with the CA system. */ public final class Session implements AutoCloseable { final byte[] mSessionId; final ArrayList<Byte> mSessionId; Session(@NonNull byte[] sessionId) { Session(@NonNull ArrayList<Byte> sessionId) { mSessionId = sessionId; } Loading @@ -254,9 +235,8 @@ public final class MediaCas implements AutoCloseable { validateInternalStates(); try { mICas.setSessionPrivateData(mSessionId, data); } catch (ServiceSpecificException e) { MediaCasException.throwExceptions(e); MediaCasException.throwExceptionIfNeeded( mICas.setSessionPrivateData(mSessionId, toByteArray(data, 0, data.length))); } catch (RemoteException e) { cleanupAndRethrowIllegalState(); } Loading @@ -279,10 +259,8 @@ public final class MediaCas implements AutoCloseable { validateInternalStates(); try { mCasData.set(data, offset, length); mICas.processEcm(mSessionId, mCasData); } catch (ServiceSpecificException e) { MediaCasException.throwExceptions(e); MediaCasException.throwExceptionIfNeeded( mICas.processEcm(mSessionId, toByteArray(data, offset, length))); } catch (RemoteException e) { cleanupAndRethrowIllegalState(); } Loading Loading @@ -314,56 +292,21 @@ public final class MediaCas implements AutoCloseable { validateInternalStates(); try { mICas.closeSession(mSessionId); } catch (ServiceSpecificException e) { MediaCasStateException.throwExceptions(e); MediaCasStateException.throwExceptionIfNeeded( mICas.closeSession(mSessionId)); } catch (RemoteException e) { cleanupAndRethrowIllegalState(); } } } Session createFromSessionId(byte[] sessionId) { if (sessionId == null || sessionId.length == 0) { Session createFromSessionId(@NonNull ArrayList<Byte> sessionId) { if (sessionId == null || sessionId.size() == 0) { return null; } return new Session(sessionId); } /** * Class for parceling CAS plugin descriptors over IMediaCasService binder. */ static class ParcelableCasPluginDescriptor extends PluginDescriptor implements Parcelable { private ParcelableCasPluginDescriptor(int CA_system_id, String name) { super(CA_system_id, name); } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { Log.w(TAG, "ParcelableCasPluginDescriptor.writeToParcel shouldn't be called!"); } public static final Parcelable.Creator<ParcelableCasPluginDescriptor> CREATOR = new Parcelable.Creator<ParcelableCasPluginDescriptor>() { public ParcelableCasPluginDescriptor createFromParcel(Parcel in) { int CA_system_id = in.readInt(); String name = in.readString(); return new ParcelableCasPluginDescriptor(CA_system_id, name); } public ParcelableCasPluginDescriptor[] newArray(int size) { return new ParcelableCasPluginDescriptor[size]; } }; } /** * Query if a certain CA system is supported on this device. * Loading Loading @@ -393,13 +336,14 @@ public final class MediaCas implements AutoCloseable { if (service != null) { try { ParcelableCasPluginDescriptor[] descriptors = service.enumeratePlugins(); if (descriptors.length == 0) { ArrayList<HidlCasPluginDescriptor> descriptors = service.enumeratePlugins(); if (descriptors.size() == 0) { return null; } PluginDescriptor[] results = new PluginDescriptor[descriptors.length]; PluginDescriptor[] results = new PluginDescriptor[descriptors.size()]; for (int i = 0; i < results.length; i++) { results[i] = descriptors[i]; results[i] = new PluginDescriptor(descriptors.get(i)); } return results; } catch (RemoteException e) { Loading Loading @@ -430,7 +374,7 @@ public final class MediaCas implements AutoCloseable { } } IBinder getBinder() { IHwBinder getBinder() { validateInternalStates(); return mICas.asBinder(); Loading Loading @@ -497,14 +441,22 @@ public final class MediaCas implements AutoCloseable { validateInternalStates(); try { mICas.setPrivateData(data); } catch (ServiceSpecificException e) { MediaCasException.throwExceptions(e); MediaCasException.throwExceptionIfNeeded( mICas.setPrivateData(toByteArray(data, 0, data.length))); } catch (RemoteException e) { cleanupAndRethrowIllegalState(); } } private class OpenSessionCallback implements ICas.openSessionCallback { public Session mSession; public int mStatus; @Override public void onValues(int status, ArrayList<Byte> sessionId) { mStatus = status; mSession = createFromSessionId(sessionId); } } /** * Open a session to descramble one or more streams scrambled by the * conditional access system. Loading @@ -519,9 +471,10 @@ public final class MediaCas implements AutoCloseable { validateInternalStates(); try { return createFromSessionId(mICas.openSession()); } catch (ServiceSpecificException e) { MediaCasException.throwExceptions(e); OpenSessionCallback cb = new OpenSessionCallback(); mICas.openSession(cb); MediaCasException.throwExceptionIfNeeded(cb.mStatus); return cb.mSession; } catch (RemoteException e) { cleanupAndRethrowIllegalState(); } Loading @@ -544,10 +497,8 @@ public final class MediaCas implements AutoCloseable { validateInternalStates(); try { mCasData.set(data, offset, length); mICas.processEmm(mCasData); } catch (ServiceSpecificException e) { MediaCasException.throwExceptions(e); MediaCasException.throwExceptionIfNeeded( mICas.processEmm(toByteArray(data, offset, length))); } catch (RemoteException e) { cleanupAndRethrowIllegalState(); } Loading Loading @@ -585,9 +536,8 @@ public final class MediaCas implements AutoCloseable { validateInternalStates(); try { mICas.sendEvent(event, arg, data); } catch (ServiceSpecificException e) { MediaCasException.throwExceptions(e); MediaCasException.throwExceptionIfNeeded( mICas.sendEvent(event, arg, toByteArray(data))); } catch (RemoteException e) { cleanupAndRethrowIllegalState(); } Loading @@ -608,9 +558,8 @@ public final class MediaCas implements AutoCloseable { validateInternalStates(); try { mICas.provision(provisionString); } catch (ServiceSpecificException e) { MediaCasException.throwExceptions(e); MediaCasException.throwExceptionIfNeeded( mICas.provision(provisionString)); } catch (RemoteException e) { cleanupAndRethrowIllegalState(); } Loading @@ -631,9 +580,8 @@ public final class MediaCas implements AutoCloseable { validateInternalStates(); try { mICas.refreshEntitlements(refreshType, refreshData); } catch (ServiceSpecificException e) { MediaCasException.throwExceptions(e); MediaCasException.throwExceptionIfNeeded( mICas.refreshEntitlements(refreshType, toByteArray(refreshData))); } catch (RemoteException e) { cleanupAndRethrowIllegalState(); } Loading
media/java/android/media/MediaCasException.java +14 −45 Original line number Diff line number Diff line Loading @@ -16,60 +16,29 @@ package android.media; import android.os.ServiceSpecificException; import android.hardware.cas.V1_0.Status; /** * Base class for MediaCas exceptions */ public class MediaCasException extends Exception { /** @hide */ public static final int DRM_ERROR_BASE = -2000; /** @hide */ public static final int ERROR_DRM_UNKNOWN = DRM_ERROR_BASE; /** @hide */ public static final int ERROR_DRM_NO_LICENSE = DRM_ERROR_BASE - 1; /** @hide */ public static final int ERROR_DRM_LICENSE_EXPIRED = DRM_ERROR_BASE - 2; /** @hide */ public static final int ERROR_DRM_SESSION_NOT_OPENED = DRM_ERROR_BASE - 3; /** @hide */ public static final int ERROR_DRM_DECRYPT_UNIT_NOT_INITIALIZED = DRM_ERROR_BASE - 4; /** @hide */ public static final int ERROR_DRM_DECRYPT = DRM_ERROR_BASE - 5; /** @hide */ public static final int ERROR_DRM_CANNOT_HANDLE = DRM_ERROR_BASE - 6; /** @hide */ public static final int ERROR_DRM_TAMPER_DETECTED = DRM_ERROR_BASE - 7; /** @hide */ public static final int ERROR_DRM_NOT_PROVISIONED = DRM_ERROR_BASE - 8; /** @hide */ public static final int ERROR_DRM_DEVICE_REVOKED = DRM_ERROR_BASE - 9; /** @hide */ public static final int ERROR_DRM_RESOURCE_BUSY = DRM_ERROR_BASE - 10; /** @hide */ public static final int ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION = DRM_ERROR_BASE - 11; /** @hide */ public static final int ERROR_DRM_LAST_USED_ERRORCODE = DRM_ERROR_BASE - 11; /** @hide */ public static final int ERROR_DRM_VENDOR_MAX = DRM_ERROR_BASE - 500; /** @hide */ public static final int ERROR_DRM_VENDOR_MIN = DRM_ERROR_BASE - 999; /** @hide */ public MediaCasException(String detailMessage) { private MediaCasException(String detailMessage) { super(detailMessage); } static void throwExceptions(ServiceSpecificException e) throws MediaCasException { if (e.errorCode == ERROR_DRM_NOT_PROVISIONED) { throw new NotProvisionedException(e.getMessage()); } else if (e.errorCode == ERROR_DRM_RESOURCE_BUSY) { throw new ResourceBusyException(e.getMessage()); } else if (e.errorCode == ERROR_DRM_DEVICE_REVOKED) { throw new DeniedByServerException(e.getMessage()); static void throwExceptionIfNeeded(int error) throws MediaCasException { if (error == Status.OK) { return; } if (error == Status.ERROR_CAS_NOT_PROVISIONED) { throw new NotProvisionedException(null); } else if (error == Status.ERROR_CAS_RESOURCE_BUSY) { throw new ResourceBusyException(null); } else if (error == Status.ERROR_CAS_DEVICE_REVOKED) { throw new DeniedByServerException(null); } else { MediaCasStateException.throwExceptions(e); MediaCasStateException.throwExceptionIfNeeded(error); } } Loading
media/java/android/media/MediaCasStateException.java +34 −19 Original line number Diff line number Diff line Loading @@ -18,9 +18,8 @@ package android.media; import android.annotation.NonNull; import android.annotation.Nullable; import android.os.ServiceSpecificException; import static android.media.MediaCasException.*; import android.hardware.cas.V1_0.Status; /** * Base class for MediaCas runtime exceptions Loading @@ -29,46 +28,62 @@ public class MediaCasStateException extends IllegalStateException { private final int mErrorCode; private final String mDiagnosticInfo; /** @hide */ public MediaCasStateException(int err, @Nullable String msg, @Nullable String diagnosticInfo) { private MediaCasStateException(int err, @Nullable String msg, @Nullable String diagnosticInfo) { super(msg); mErrorCode = err; mDiagnosticInfo = diagnosticInfo; } static void throwExceptions(ServiceSpecificException e) { static void throwExceptionIfNeeded(int err) { throwExceptionIfNeeded(err, null /* msg */); } static void throwExceptionIfNeeded(int err, @Nullable String msg) { if (err == Status.OK) { return; } if (err == Status.BAD_VALUE) { throw new IllegalArgumentException(); } String diagnosticInfo = ""; switch (e.errorCode) { case ERROR_DRM_UNKNOWN: switch (err) { case Status.ERROR_CAS_UNKNOWN: diagnosticInfo = "General CAS error"; break; case ERROR_DRM_NO_LICENSE: case Status.ERROR_CAS_NO_LICENSE: diagnosticInfo = "No license"; break; case ERROR_DRM_LICENSE_EXPIRED: case Status.ERROR_CAS_LICENSE_EXPIRED: diagnosticInfo = "License expired"; break; case ERROR_DRM_SESSION_NOT_OPENED: case Status.ERROR_CAS_SESSION_NOT_OPENED: diagnosticInfo = "Session not opened"; break; case ERROR_DRM_DECRYPT_UNIT_NOT_INITIALIZED: diagnosticInfo = "Not initialized"; case Status.ERROR_CAS_CANNOT_HANDLE: diagnosticInfo = "Unsupported scheme or data format"; break; case ERROR_DRM_DECRYPT: diagnosticInfo = "Decrypt error"; case Status.ERROR_CAS_INVALID_STATE: diagnosticInfo = "Invalid CAS state"; break; case ERROR_DRM_CANNOT_HANDLE: diagnosticInfo = "Unsupported scheme or data format"; case Status.ERROR_CAS_INSUFFICIENT_OUTPUT_PROTECTION: diagnosticInfo = "Insufficient output protection"; break; case ERROR_DRM_TAMPER_DETECTED: case Status.ERROR_CAS_TAMPER_DETECTED: diagnosticInfo = "Tamper detected"; break; case Status.ERROR_CAS_DECRYPT_UNIT_NOT_INITIALIZED: diagnosticInfo = "Not initialized"; break; case Status.ERROR_CAS_DECRYPT: diagnosticInfo = "Decrypt error"; break; default: diagnosticInfo = "Unknown CAS state exception"; break; } throw new MediaCasStateException(e.errorCode, e.getMessage(), String.format("%s (err=%d)", diagnosticInfo, e.errorCode)); throw new MediaCasStateException(err, msg, String.format("%s (err=%d)", diagnosticInfo, err)); } /** Loading
media/java/android/media/MediaCodec.java +3 −2 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ import android.media.MediaCodecInfo.CodecCapabilities; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.IHwBinder; import android.os.Looper; import android.os.Message; import android.os.PersistableBundle; Loading Loading @@ -1903,7 +1904,7 @@ final public class MediaCodec { private void configure( @Nullable MediaFormat format, @Nullable Surface surface, @Nullable MediaCrypto crypto, @Nullable IBinder descramblerBinder, @Nullable MediaCrypto crypto, @Nullable IHwBinder descramblerBinder, @ConfigureFlag int flags) { if (crypto != null && descramblerBinder != null) { throw new IllegalArgumentException("Can't use crypto and descrambler together!"); Loading Loading @@ -2018,7 +2019,7 @@ final public class MediaCodec { private native final void native_configure( @Nullable String[] keys, @Nullable Object[] values, @Nullable Surface surface, @Nullable MediaCrypto crypto, @Nullable IBinder descramblerBinder, @ConfigureFlag int flags); @Nullable IHwBinder descramblerBinder, @ConfigureFlag int flags); /** * Requests a Surface to use as the input to an encoder, in place of input buffers. This Loading