Merge changes from topic "CAS AIDL Integration"
* changes: CAS: Fix integration issues with AIDL CAS: Add openSessionDefault CAS: Disable Descrambler API for AIDL
This commit is contained in:
@@ -41,6 +41,7 @@ import android.os.Message;
|
|||||||
import android.os.Process;
|
import android.os.Process;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.os.ServiceManager;
|
import android.os.ServiceManager;
|
||||||
|
import android.os.ServiceSpecificException;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.Singleton;
|
import android.util.Singleton;
|
||||||
|
|
||||||
@@ -360,14 +361,14 @@ public final class MediaCas implements AutoCloseable {
|
|||||||
@Override
|
@Override
|
||||||
public void handleMessage(Message msg) {
|
public void handleMessage(Message msg) {
|
||||||
if (msg.what == MSG_CAS_EVENT) {
|
if (msg.what == MSG_CAS_EVENT) {
|
||||||
mListener.onEvent(MediaCas.this, msg.arg1, msg.arg2,
|
byte[] data = (msg.obj == null) ? new byte[0] : (byte[]) msg.obj;
|
||||||
toBytes((ArrayList<Byte>) msg.obj));
|
mListener.onEvent(MediaCas.this, msg.arg1, msg.arg2, data);
|
||||||
} else if (msg.what == MSG_CAS_SESSION_EVENT) {
|
} else if (msg.what == MSG_CAS_SESSION_EVENT) {
|
||||||
Bundle bundle = msg.getData();
|
Bundle bundle = msg.getData();
|
||||||
byte[] sessionId = bundle.getByteArray(SESSION_KEY);
|
byte[] sessionId = bundle.getByteArray(SESSION_KEY);
|
||||||
mListener.onSessionEvent(MediaCas.this,
|
byte[] data = bundle.getByteArray(DATA_KEY);
|
||||||
createFromSessionId(sessionId), msg.arg1, msg.arg2,
|
mListener.onSessionEvent(
|
||||||
bundle.getByteArray(DATA_KEY));
|
MediaCas.this, createFromSessionId(sessionId), msg.arg1, msg.arg2, data);
|
||||||
} else if (msg.what == MSG_CAS_STATUS_EVENT) {
|
} else if (msg.what == MSG_CAS_STATUS_EVENT) {
|
||||||
if ((msg.arg1 == PLUGIN_STATUS_SESSION_NUMBER_CHANGED)
|
if ((msg.arg1 == PLUGIN_STATUS_SESSION_NUMBER_CHANGED)
|
||||||
&& (mTunerResourceManager != null)) {
|
&& (mTunerResourceManager != null)) {
|
||||||
@@ -599,7 +600,11 @@ public final class MediaCas implements AutoCloseable {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
if (mICas != null) {
|
if (mICas != null) {
|
||||||
mICas.setSessionPrivateData(mSessionId, data);
|
try {
|
||||||
|
mICas.setSessionPrivateData(mSessionId, data);
|
||||||
|
} catch (ServiceSpecificException se) {
|
||||||
|
MediaCasException.throwExceptionIfNeeded(se.errorCode);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
MediaCasException.throwExceptionIfNeeded(
|
MediaCasException.throwExceptionIfNeeded(
|
||||||
mICasHidl.setSessionPrivateData(
|
mICasHidl.setSessionPrivateData(
|
||||||
@@ -628,7 +633,12 @@ public final class MediaCas implements AutoCloseable {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
if (mICas != null) {
|
if (mICas != null) {
|
||||||
mICas.processEcm(mSessionId, data);
|
try {
|
||||||
|
mICas.processEcm(
|
||||||
|
mSessionId, Arrays.copyOfRange(data, offset, length + offset));
|
||||||
|
} catch (ServiceSpecificException se) {
|
||||||
|
MediaCasException.throwExceptionIfNeeded(se.errorCode);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
MediaCasException.throwExceptionIfNeeded(
|
MediaCasException.throwExceptionIfNeeded(
|
||||||
mICasHidl.processEcm(
|
mICasHidl.processEcm(
|
||||||
@@ -671,23 +681,26 @@ public final class MediaCas implements AutoCloseable {
|
|||||||
validateSessionInternalStates();
|
validateSessionInternalStates();
|
||||||
if (mICas != null) {
|
if (mICas != null) {
|
||||||
try {
|
try {
|
||||||
|
if (data == null) {
|
||||||
|
data = new byte[0];
|
||||||
|
}
|
||||||
mICas.sendSessionEvent(mSessionId, event, arg, data);
|
mICas.sendSessionEvent(mSessionId, event, arg, data);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
cleanupAndRethrowIllegalState();
|
cleanupAndRethrowIllegalState();
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
|
||||||
if (mICasHidl11 == null) {
|
try {
|
||||||
Log.d(TAG, "Send Session Event isn't supported by cas@1.0 interface");
|
MediaCasException.throwExceptionIfNeeded(
|
||||||
throw new UnsupportedCasException("Send Session Event is not supported");
|
mICasHidl11.sendSessionEvent(
|
||||||
}
|
toByteArray(mSessionId), event, arg, toByteArray(data)));
|
||||||
|
} catch (RemoteException e) {
|
||||||
try {
|
cleanupAndRethrowIllegalState();
|
||||||
MediaCasException.throwExceptionIfNeeded(
|
}
|
||||||
mICasHidl11.sendSessionEvent(
|
|
||||||
toByteArray(mSessionId), event, arg, toByteArray(data)));
|
|
||||||
} catch (RemoteException e) {
|
|
||||||
cleanupAndRethrowIllegalState();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1038,7 +1051,11 @@ public final class MediaCas implements AutoCloseable {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
if (mICas != null) {
|
if (mICas != null) {
|
||||||
mICas.setPrivateData(data);
|
try {
|
||||||
|
mICas.setPrivateData(data);
|
||||||
|
} catch (ServiceSpecificException se) {
|
||||||
|
MediaCasException.throwExceptionIfNeeded(se.errorCode);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
MediaCasException.throwExceptionIfNeeded(
|
MediaCasException.throwExceptionIfNeeded(
|
||||||
mICasHidl.setPrivateData(toByteArray(data, 0, data.length)));
|
mICasHidl.setPrivateData(toByteArray(data, 0, data.length)));
|
||||||
@@ -1126,7 +1143,21 @@ public final class MediaCas implements AutoCloseable {
|
|||||||
int sessionResourceHandle = getSessionResourceHandle();
|
int sessionResourceHandle = getSessionResourceHandle();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (mICasHidl != null) {
|
if (mICas != null) {
|
||||||
|
try {
|
||||||
|
byte[] sessionId = mICas.openSessionDefault();
|
||||||
|
Session session = createFromSessionId(sessionId);
|
||||||
|
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 (ServiceSpecificException se) {
|
||||||
|
MediaCasException.throwExceptionIfNeeded(se.errorCode);
|
||||||
|
}
|
||||||
|
} else if (mICasHidl != null) {
|
||||||
OpenSessionCallback cb = new OpenSessionCallback();
|
OpenSessionCallback cb = new OpenSessionCallback();
|
||||||
mICasHidl.openSession(cb);
|
mICasHidl.openSession(cb);
|
||||||
MediaCasException.throwExceptionIfNeeded(cb.mStatus);
|
MediaCasException.throwExceptionIfNeeded(cb.mStatus);
|
||||||
@@ -1183,7 +1214,7 @@ public final class MediaCas implements AutoCloseable {
|
|||||||
mCasSystemId,
|
mCasSystemId,
|
||||||
FrameworkStatsLog.TV_CAS_SESSION_OPEN_STATUS__STATE__SUCCEEDED);
|
FrameworkStatsLog.TV_CAS_SESSION_OPEN_STATUS__STATE__SUCCEEDED);
|
||||||
return session;
|
return session;
|
||||||
} catch (RemoteException e) {
|
} catch (ServiceSpecificException | RemoteException e) {
|
||||||
cleanupAndRethrowIllegalState();
|
cleanupAndRethrowIllegalState();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1229,7 +1260,11 @@ public final class MediaCas implements AutoCloseable {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
if (mICas != null) {
|
if (mICas != null) {
|
||||||
mICas.processEmm(Arrays.copyOfRange(data, offset, length));
|
try {
|
||||||
|
mICas.processEmm(Arrays.copyOfRange(data, offset, length));
|
||||||
|
} catch (ServiceSpecificException se) {
|
||||||
|
MediaCasException.throwExceptionIfNeeded(se.errorCode);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
MediaCasException.throwExceptionIfNeeded(
|
MediaCasException.throwExceptionIfNeeded(
|
||||||
mICasHidl.processEmm(toByteArray(data, offset, length)));
|
mICasHidl.processEmm(toByteArray(data, offset, length)));
|
||||||
@@ -1272,7 +1307,14 @@ public final class MediaCas implements AutoCloseable {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
if (mICas != null) {
|
if (mICas != null) {
|
||||||
mICas.sendEvent(event, arg, data);
|
try {
|
||||||
|
if (data == null) {
|
||||||
|
data = new byte[0];
|
||||||
|
}
|
||||||
|
mICas.sendEvent(event, arg, data);
|
||||||
|
} catch (ServiceSpecificException se) {
|
||||||
|
MediaCasException.throwExceptionIfNeeded(se.errorCode);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
MediaCasException.throwExceptionIfNeeded(
|
MediaCasException.throwExceptionIfNeeded(
|
||||||
mICasHidl.sendEvent(event, arg, toByteArray(data)));
|
mICasHidl.sendEvent(event, arg, toByteArray(data)));
|
||||||
@@ -1298,7 +1340,11 @@ public final class MediaCas implements AutoCloseable {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
if (mICas != null) {
|
if (mICas != null) {
|
||||||
mICas.provision(provisionString);
|
try {
|
||||||
|
mICas.provision(provisionString);
|
||||||
|
} catch (ServiceSpecificException se) {
|
||||||
|
MediaCasException.throwExceptionIfNeeded(se.errorCode);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
MediaCasException.throwExceptionIfNeeded(mICasHidl.provision(provisionString));
|
MediaCasException.throwExceptionIfNeeded(mICasHidl.provision(provisionString));
|
||||||
}
|
}
|
||||||
@@ -1323,7 +1369,14 @@ public final class MediaCas implements AutoCloseable {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
if (mICas != null) {
|
if (mICas != null) {
|
||||||
mICas.refreshEntitlements(refreshType, refreshData);
|
try {
|
||||||
|
if (refreshData == null) {
|
||||||
|
refreshData = new byte[0];
|
||||||
|
}
|
||||||
|
mICas.refreshEntitlements(refreshType, refreshData);
|
||||||
|
} catch (ServiceSpecificException se) {
|
||||||
|
MediaCasException.throwExceptionIfNeeded(se.errorCode);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
MediaCasException.throwExceptionIfNeeded(
|
MediaCasException.throwExceptionIfNeeded(
|
||||||
mICasHidl.refreshEntitlements(refreshType, toByteArray(refreshData)));
|
mICasHidl.refreshEntitlements(refreshType, toByteArray(refreshData)));
|
||||||
|
|||||||
@@ -17,24 +17,15 @@
|
|||||||
package android.media;
|
package android.media;
|
||||||
|
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.hardware.cas.DestinationBuffer;
|
|
||||||
import android.hardware.cas.IDescrambler;
|
import android.hardware.cas.IDescrambler;
|
||||||
import android.hardware.cas.ScramblingControl;
|
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.cas.V1_0.IDescramblerBase;
|
||||||
import android.hardware.common.Ashmem;
|
|
||||||
import android.hardware.common.NativeHandle;
|
|
||||||
import android.media.MediaCasException.UnsupportedCasException;
|
import android.media.MediaCasException.UnsupportedCasException;
|
||||||
import android.os.IHwBinder;
|
import android.os.IHwBinder;
|
||||||
import android.os.ParcelFileDescriptor;
|
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.os.ServiceSpecificException;
|
import android.os.ServiceSpecificException;
|
||||||
import android.os.SharedMemory;
|
|
||||||
import android.system.ErrnoException;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
@@ -52,6 +43,7 @@ import java.util.ArrayList;
|
|||||||
public final class MediaDescrambler implements AutoCloseable {
|
public final class MediaDescrambler implements AutoCloseable {
|
||||||
private static final String TAG = "MediaDescrambler";
|
private static final String TAG = "MediaDescrambler";
|
||||||
private DescramblerWrapper mIDescrambler;
|
private DescramblerWrapper mIDescrambler;
|
||||||
|
private boolean mIsAidlHal;
|
||||||
|
|
||||||
private interface DescramblerWrapper {
|
private interface DescramblerWrapper {
|
||||||
|
|
||||||
@@ -68,50 +60,18 @@ public final class MediaDescrambler implements AutoCloseable {
|
|||||||
void setMediaCasSession(byte[] sessionId) throws RemoteException;
|
void setMediaCasSession(byte[] sessionId) throws RemoteException;
|
||||||
|
|
||||||
void release() 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 {
|
private class AidlDescrambler implements DescramblerWrapper {
|
||||||
|
|
||||||
IDescrambler mAidlDescrambler;
|
IDescrambler mAidlDescrambler;
|
||||||
|
|
||||||
AidlDescrambler(IDescrambler aidlDescrambler) {
|
AidlDescrambler(IDescrambler aidlDescrambler) throws Exception {
|
||||||
mAidlDescrambler = aidlDescrambler;
|
if (aidlDescrambler != null) {
|
||||||
|
mAidlDescrambler = aidlDescrambler;
|
||||||
|
} else {
|
||||||
|
throw new Exception("Descrambler could not be created");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -125,47 +85,17 @@ public final class MediaDescrambler implements AutoCloseable {
|
|||||||
@NonNull ByteBuffer dst,
|
@NonNull ByteBuffer dst,
|
||||||
@NonNull MediaCodec.CryptoInfo cryptoInfo)
|
@NonNull MediaCodec.CryptoInfo cryptoInfo)
|
||||||
throws RemoteException {
|
throws RemoteException {
|
||||||
SubSample[] subSamples = new SubSample[cryptoInfo.numSubSamples];
|
throw new RemoteException("Not supported");
|
||||||
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
|
@Override
|
||||||
public boolean requiresSecureDecoderComponent(@NonNull String mime) throws RemoteException {
|
public boolean requiresSecureDecoderComponent(@NonNull String mime) throws RemoteException {
|
||||||
return mAidlDescrambler.requiresSecureDecoderComponent(mime);
|
throw new RemoteException("Not supported");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setMediaCasSession(byte[] sessionId) throws RemoteException {
|
public void setMediaCasSession(byte[] sessionId) throws RemoteException {
|
||||||
mAidlDescrambler.setMediaCasSession(sessionId);
|
throw new RemoteException("Not supported");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -178,9 +108,13 @@ public final class MediaDescrambler implements AutoCloseable {
|
|||||||
|
|
||||||
IDescramblerBase mHidlDescrambler;
|
IDescramblerBase mHidlDescrambler;
|
||||||
|
|
||||||
HidlDescrambler(IDescramblerBase hidlDescrambler) {
|
HidlDescrambler(IDescramblerBase hidlDescrambler) throws Exception {
|
||||||
mHidlDescrambler = hidlDescrambler;
|
if (hidlDescrambler != null) {
|
||||||
native_setup(hidlDescrambler.asBinder());
|
mHidlDescrambler = hidlDescrambler;
|
||||||
|
native_setup(hidlDescrambler.asBinder());
|
||||||
|
} else {
|
||||||
|
throw new Exception("Descrambler could not be created");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -267,10 +201,14 @@ public final class MediaDescrambler implements AutoCloseable {
|
|||||||
if (MediaCas.getService() != null) {
|
if (MediaCas.getService() != null) {
|
||||||
mIDescrambler =
|
mIDescrambler =
|
||||||
new AidlDescrambler(MediaCas.getService().createDescrambler(CA_system_id));
|
new AidlDescrambler(MediaCas.getService().createDescrambler(CA_system_id));
|
||||||
|
mIsAidlHal = true;
|
||||||
} else if (MediaCas.getServiceHidl() != null) {
|
} else if (MediaCas.getServiceHidl() != null) {
|
||||||
mIDescrambler =
|
mIDescrambler =
|
||||||
new HidlDescrambler(
|
new HidlDescrambler(
|
||||||
MediaCas.getServiceHidl().createDescrambler(CA_system_id));
|
MediaCas.getServiceHidl().createDescrambler(CA_system_id));
|
||||||
|
mIsAidlHal = false;
|
||||||
|
} else {
|
||||||
|
throw new Exception("No CAS service found!");
|
||||||
}
|
}
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
Log.e(TAG, "Failed to create descrambler: " + e);
|
Log.e(TAG, "Failed to create descrambler: " + e);
|
||||||
@@ -282,6 +220,15 @@ public final class MediaDescrambler implements AutoCloseable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the underlying HAL is AIDL. Used only for CTS.
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public boolean isAidlHal() {
|
||||||
|
return mIsAidlHal;
|
||||||
|
}
|
||||||
|
|
||||||
IHwBinder getBinder() {
|
IHwBinder getBinder() {
|
||||||
validateInternalStates();
|
validateInternalStates();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user