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:
Yixiao Luo
2023-02-06 18:36:22 +00:00
committed by Gerrit Code Review
2 changed files with 110 additions and 110 deletions

View File

@@ -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)));

View File

@@ -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();