Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9346b8b9 authored by Yixiao Luo's avatar Yixiao Luo Committed by Gerrit Code Review
Browse files

Merge changes from topic "CAS AIDL Integration"

* changes:
  CAS: Fix integration issues with AIDL
  CAS: Add openSessionDefault
  CAS: Disable Descrambler API for AIDL
parents 826dbaf5 245f729d
Loading
Loading
Loading
Loading
+79 −26
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@ import android.os.Message;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.ServiceSpecificException;
import android.util.Log;
import android.util.Singleton;

@@ -360,14 +361,14 @@ 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,
                        toBytes((ArrayList<Byte>) msg.obj));
                byte[] data = (msg.obj == null) ? new byte[0] : (byte[]) msg.obj;
                mListener.onEvent(MediaCas.this, msg.arg1, msg.arg2, data);
            } else if (msg.what == MSG_CAS_SESSION_EVENT) {
                Bundle bundle = msg.getData();
                byte[] sessionId = bundle.getByteArray(SESSION_KEY);
                mListener.onSessionEvent(MediaCas.this,
                        createFromSessionId(sessionId), msg.arg1, msg.arg2,
                        bundle.getByteArray(DATA_KEY));
                byte[] data = bundle.getByteArray(DATA_KEY);
                mListener.onSessionEvent(
                        MediaCas.this, createFromSessionId(sessionId), msg.arg1, msg.arg2, data);
            } else if (msg.what == MSG_CAS_STATUS_EVENT) {
                if ((msg.arg1 == PLUGIN_STATUS_SESSION_NUMBER_CHANGED)
                        && (mTunerResourceManager != null)) {
@@ -599,7 +600,11 @@ public final class MediaCas implements AutoCloseable {

            try {
                if (mICas != null) {
                    try {
                        mICas.setSessionPrivateData(mSessionId, data);
                    } catch (ServiceSpecificException se) {
                        MediaCasException.throwExceptionIfNeeded(se.errorCode);
                    }
                } else {
                    MediaCasException.throwExceptionIfNeeded(
                            mICasHidl.setSessionPrivateData(
@@ -628,7 +633,12 @@ public final class MediaCas implements AutoCloseable {

            try {
                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 {
                    MediaCasException.throwExceptionIfNeeded(
                            mICasHidl.processEcm(
@@ -671,12 +681,14 @@ public final class MediaCas implements AutoCloseable {
            validateSessionInternalStates();
            if (mICas != null) {
                try {
                    if (data == null) {
                        data = new byte[0];
                    }
                    mICas.sendSessionEvent(mSessionId, event, arg, data);
                } catch (RemoteException e) {
                    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");
@@ -690,6 +702,7 @@ public final class MediaCas implements AutoCloseable {
                    cleanupAndRethrowIllegalState();
                }
            }
        }

        /**
         * Get Session Id.
@@ -1038,7 +1051,11 @@ public final class MediaCas implements AutoCloseable {

        try {
            if (mICas != null) {
                try {
                    mICas.setPrivateData(data);
                } catch (ServiceSpecificException se) {
                    MediaCasException.throwExceptionIfNeeded(se.errorCode);
                }
            } else {
                MediaCasException.throwExceptionIfNeeded(
                        mICasHidl.setPrivateData(toByteArray(data, 0, data.length)));
@@ -1126,7 +1143,21 @@ public final class MediaCas implements AutoCloseable {
        int sessionResourceHandle = getSessionResourceHandle();

        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();
                mICasHidl.openSession(cb);
                MediaCasException.throwExceptionIfNeeded(cb.mStatus);
@@ -1183,7 +1214,7 @@ public final class MediaCas implements AutoCloseable {
                        mCasSystemId,
                        FrameworkStatsLog.TV_CAS_SESSION_OPEN_STATUS__STATE__SUCCEEDED);
                return session;
            } catch (RemoteException e) {
            } catch (ServiceSpecificException | RemoteException e) {
                cleanupAndRethrowIllegalState();
            }
        }
@@ -1229,7 +1260,11 @@ public final class MediaCas implements AutoCloseable {

        try {
            if (mICas != null) {
                try {
                    mICas.processEmm(Arrays.copyOfRange(data, offset, length));
                } catch (ServiceSpecificException se) {
                    MediaCasException.throwExceptionIfNeeded(se.errorCode);
                }
            } else {
                MediaCasException.throwExceptionIfNeeded(
                        mICasHidl.processEmm(toByteArray(data, offset, length)));
@@ -1272,7 +1307,14 @@ public final class MediaCas implements AutoCloseable {

        try {
            if (mICas != null) {
                try {
                    if (data == null) {
                        data = new byte[0];
                    }
                    mICas.sendEvent(event, arg, data);
                } catch (ServiceSpecificException se) {
                    MediaCasException.throwExceptionIfNeeded(se.errorCode);
                }
            } else {
                MediaCasException.throwExceptionIfNeeded(
                        mICasHidl.sendEvent(event, arg, toByteArray(data)));
@@ -1298,7 +1340,11 @@ public final class MediaCas implements AutoCloseable {

        try {
            if (mICas != null) {
                try {
                    mICas.provision(provisionString);
                } catch (ServiceSpecificException se) {
                    MediaCasException.throwExceptionIfNeeded(se.errorCode);
                }
            } else {
                MediaCasException.throwExceptionIfNeeded(mICasHidl.provision(provisionString));
            }
@@ -1323,7 +1369,14 @@ public final class MediaCas implements AutoCloseable {

        try {
            if (mICas != null) {
                try {
                    if (refreshData == null) {
                        refreshData = new byte[0];
                    }
                    mICas.refreshEntitlements(refreshType, refreshData);
                } catch (ServiceSpecificException se) {
                    MediaCasException.throwExceptionIfNeeded(se.errorCode);
                }
            } else {
                MediaCasException.throwExceptionIfNeeded(
                        mICasHidl.refreshEntitlements(refreshType, toByteArray(refreshData)));
+31 −84
Original line number Diff line number Diff line
@@ -17,24 +17,15 @@
package android.media;

import android.annotation.NonNull;
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;

@@ -52,6 +43,7 @@ import java.util.ArrayList;
public final class MediaDescrambler implements AutoCloseable {
    private static final String TAG = "MediaDescrambler";
    private DescramblerWrapper mIDescrambler;
    private boolean mIsAidlHal;

    private interface DescramblerWrapper {

@@ -68,50 +60,18 @@ public final class MediaDescrambler implements AutoCloseable {
        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) {
        AidlDescrambler(IDescrambler aidlDescrambler) throws Exception {
            if (aidlDescrambler != null) {
                mAidlDescrambler = aidlDescrambler;
            } else {
                throw new Exception("Descrambler could not be created");
            }
        }

        @Override
@@ -125,47 +85,17 @@ public final class MediaDescrambler implements AutoCloseable {
                @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());
            throw new RemoteException("Not supported");
        }

        @Override
        public boolean requiresSecureDecoderComponent(@NonNull String mime) throws RemoteException {
            return mAidlDescrambler.requiresSecureDecoderComponent(mime);
            throw new RemoteException("Not supported");
        }

        @Override
        public void setMediaCasSession(byte[] sessionId) throws RemoteException {
            mAidlDescrambler.setMediaCasSession(sessionId);
            throw new RemoteException("Not supported");
        }

        @Override
@@ -178,9 +108,13 @@ public final class MediaDescrambler implements AutoCloseable {

        IDescramblerBase mHidlDescrambler;

        HidlDescrambler(IDescramblerBase hidlDescrambler) {
        HidlDescrambler(IDescramblerBase hidlDescrambler) throws Exception {
            if (hidlDescrambler != null) {
                mHidlDescrambler = hidlDescrambler;
                native_setup(hidlDescrambler.asBinder());
            } else {
                throw new Exception("Descrambler could not be created");
            }
        }

        @Override
@@ -267,10 +201,14 @@ public final class MediaDescrambler implements AutoCloseable {
            if (MediaCas.getService() != null) {
                mIDescrambler =
                        new AidlDescrambler(MediaCas.getService().createDescrambler(CA_system_id));
                mIsAidlHal = true;
            } else if (MediaCas.getServiceHidl() != null) {
                mIDescrambler =
                        new HidlDescrambler(
                                MediaCas.getServiceHidl().createDescrambler(CA_system_id));
                mIsAidlHal = false;
            } else {
                throw new Exception("No CAS service found!");
            }
        } catch(Exception 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() {
        validateInternalStates();