cas: convert MediaCas to HIDL
- Remove AIDL interfaces.
- Replace usage with corresponding HIDL interfaces.
- Move MediaCasService implementation from frameworks/av
to hardware/interfaces/cas.
bug: 22804304
Change-Id: I56ab22565a43e91481ac2759ce69462bcc194046
diff --git a/media/libmedia/IMediaExtractor.cpp b/media/libmedia/IMediaExtractor.cpp
index f08fabb..19b00f3 100644
--- a/media/libmedia/IMediaExtractor.cpp
+++ b/media/libmedia/IMediaExtractor.cpp
@@ -21,7 +21,6 @@
#include <stdint.h>
#include <sys/types.h>
-#include <android/media/ICas.h>
#include <binder/IPCThreadState.h>
#include <binder/Parcel.h>
#include <media/IMediaExtractor.h>
@@ -117,12 +116,12 @@
return NULL;
}
- virtual status_t setMediaCas(const sp<ICas> & cas) {
+ virtual status_t setMediaCas(const HInterfaceToken &casToken) {
ALOGV("setMediaCas");
Parcel data, reply;
data.writeInterfaceToken(BpMediaExtractor::getInterfaceDescriptor());
- data.writeStrongBinder(IInterface::asBinder(cas));
+ data.writeByteVector(casToken);
status_t err = remote()->transact(SETMEDIACAS, data, &reply);
if (err != NO_ERROR) {
@@ -206,15 +205,14 @@
ALOGV("setMediaCas");
CHECK_INTERFACE(IMediaExtractor, data, reply);
- sp<IBinder> casBinder;
- status_t err = data.readNullableStrongBinder(&casBinder);
+ HInterfaceToken casToken;
+ status_t err = data.readByteVector(&casToken);
if (err != NO_ERROR) {
- ALOGE("Error reading cas from parcel");
+ ALOGE("Error reading casToken from parcel");
return err;
}
- sp<ICas> cas = interface_cast<ICas>(casBinder);
- reply->writeInt32(setMediaCas(cas));
+ reply->writeInt32(setMediaCas(casToken));
return OK;
}
default:
diff --git a/media/libmedia/include/media/IMediaExtractor.h b/media/libmedia/include/media/IMediaExtractor.h
index ab40f53..1e13b65 100644
--- a/media/libmedia/include/media/IMediaExtractor.h
+++ b/media/libmedia/include/media/IMediaExtractor.h
@@ -20,14 +20,12 @@
#include <media/IMediaSource.h>
#include <media/stagefright/DataSource.h>
+#include <vector>
namespace android {
class MetaData;
-namespace media {
-class ICas;
-};
-using namespace media;
+typedef std::vector<uint8_t> HInterfaceToken;
class IMediaExtractor : public IInterface {
public:
@@ -65,7 +63,7 @@
// for DRM
virtual char* getDrmTrackInfo(size_t trackID, int *len) = 0;
- virtual status_t setMediaCas(const sp<ICas> &cas) = 0;
+ virtual status_t setMediaCas(const HInterfaceToken &casToken) = 0;
virtual void setUID(uid_t uid) = 0;
diff --git a/media/libstagefright/ACodecBufferChannel.cpp b/media/libstagefright/ACodecBufferChannel.cpp
index 0d9696f..3c7ae3e 100644
--- a/media/libstagefright/ACodecBufferChannel.cpp
+++ b/media/libstagefright/ACodecBufferChannel.cpp
@@ -20,7 +20,7 @@
#include <numeric>
-#include <android/media/IDescrambler.h>
+#include <android/hardware/cas/native/1.0/IDescrambler.h>
#include <binder/MemoryDealer.h>
#include <media/openmax/OMX_Core.h>
#include <media/stagefright/foundation/AMessage.h>
@@ -34,8 +34,11 @@
#include "include/SharedMemoryBuffer.h"
namespace android {
-using binder::Status;
-using MediaDescrambler::DescrambleInfo;
+using hardware::hidl_handle;
+using hardware::hidl_string;
+using hardware::hidl_vec;
+using namespace hardware::cas::V1_0;
+using namespace hardware::cas::native::V1_0;
using BufferInfo = ACodecBufferChannel::BufferInfo;
using BufferInfoIterator = std::vector<const BufferInfo>::const_iterator;
@@ -114,74 +117,97 @@
return -ENOENT;
}
- ICrypto::DestinationBuffer destination;
+ native_handle_t *secureHandle = NULL;
if (secure) {
sp<SecureBuffer> secureData =
static_cast<SecureBuffer *>(it->mCodecBuffer.get());
- destination.mType = secureData->getDestinationType();
- if (destination.mType != ICrypto::kDestinationTypeNativeHandle) {
+ if (secureData->getDestinationType() != ICrypto::kDestinationTypeNativeHandle) {
return BAD_VALUE;
}
- destination.mHandle =
- static_cast<native_handle_t *>(secureData->getDestinationPointer());
- } else {
- destination.mType = ICrypto::kDestinationTypeSharedMemory;
- destination.mSharedMemory = mDecryptDestination;
+ secureHandle = static_cast<native_handle_t *>(secureData->getDestinationPointer());
}
-
- ICrypto::SourceBuffer source;
- source.mSharedMemory = it->mSharedEncryptedBuffer;
- source.mHeapSeqNum = mHeapSeqNum;
-
ssize_t result = -1;
if (mCrypto != NULL) {
+ ICrypto::DestinationBuffer destination;
+ if (secure) {
+ destination.mType = ICrypto::kDestinationTypeNativeHandle;
+ destination.mHandle = secureHandle;
+ } else {
+ destination.mType = ICrypto::kDestinationTypeSharedMemory;
+ destination.mSharedMemory = mDecryptDestination;
+ }
+
+ ICrypto::SourceBuffer source;
+ source.mSharedMemory = it->mSharedEncryptedBuffer;
+ source.mHeapSeqNum = mHeapSeqNum;
+
result = mCrypto->decrypt(key, iv, mode, pattern,
source, it->mClientBuffer->offset(),
subSamples, numSubSamples, destination, errorDetailMsg);
- } else {
- DescrambleInfo descrambleInfo;
- descrambleInfo.dstType = destination.mType ==
- ICrypto::kDestinationTypeSharedMemory ?
- DescrambleInfo::kDestinationTypeVmPointer :
- DescrambleInfo::kDestinationTypeNativeHandle;
- descrambleInfo.scramblingControl = key != NULL ?
- (DescramblerPlugin::ScramblingControl)key[0] :
- DescramblerPlugin::kScrambling_Unscrambled;
- descrambleInfo.numSubSamples = numSubSamples;
- descrambleInfo.subSamples = (DescramblerPlugin::SubSample *)subSamples;
- descrambleInfo.srcMem = it->mSharedEncryptedBuffer;
- descrambleInfo.srcOffset = 0;
- descrambleInfo.dstPtr = NULL;
- descrambleInfo.dstOffset = 0;
-
- int32_t descrambleResult = -1;
- Status status = mDescrambler->descramble(descrambleInfo, &descrambleResult);
-
- if (status.isOk()) {
- result = descrambleResult;
- }
if (result < 0) {
- ALOGE("descramble failed, exceptionCode=%d, err=%d, result=%zd",
- status.exceptionCode(), status.transactionError(), result);
- } else {
- ALOGV("descramble succeeded, result=%zd", result);
+ return result;
}
- if (result > 0 && destination.mType == ICrypto::kDestinationTypeSharedMemory) {
- memcpy(destination.mSharedMemory->pointer(),
+ if (destination.mType == ICrypto::kDestinationTypeSharedMemory) {
+ memcpy(it->mCodecBuffer->base(), destination.mSharedMemory->pointer(), result);
+ }
+ } else {
+ // Here we cast CryptoPlugin::SubSample to hardware::cas::native::V1_0::SubSample
+ // directly, the structure definitions should match as checked in DescramblerImpl.cpp.
+ hidl_vec<SubSample> hidlSubSamples;
+ hidlSubSamples.setToExternal((SubSample *)subSamples, numSubSamples, false /*own*/);
+
+ ssize_t offset;
+ size_t size;
+ it->mSharedEncryptedBuffer->getMemory(&offset, &size);
+ hardware::cas::native::V1_0::SharedBuffer srcBuffer = {
+ .heapBase = mHidlMemory,
+ .offset = (uint64_t) offset,
+ .size = size
+ };
+
+ DestinationBuffer dstBuffer;
+ if (secure) {
+ dstBuffer.type = BufferType::NATIVE_HANDLE;
+ dstBuffer.secureMemory = hidl_handle(secureHandle);
+ } else {
+ dstBuffer.type = BufferType::SHARED_MEMORY;
+ dstBuffer.nonsecureMemory = srcBuffer;
+ }
+
+ Status status = Status::OK;
+ hidl_string detailedError;
+
+ auto returnVoid = mDescrambler->descramble(
+ key != NULL ? (ScramblingControl)key[0] : ScramblingControl::UNSCRAMBLED,
+ hidlSubSamples,
+ srcBuffer,
+ 0,
+ dstBuffer,
+ 0,
+ [&status, &result, &detailedError] (
+ Status _status, uint32_t _bytesWritten,
+ const hidl_string& _detailedError) {
+ status = _status;
+ result = (ssize_t)_bytesWritten;
+ detailedError = _detailedError;
+ });
+
+ if (!returnVoid.isOk() || status != Status::OK || result < 0) {
+ ALOGE("descramble failed, trans=%s, status=%d, result=%zd",
+ returnVoid.description().c_str(), status, result);
+ return UNKNOWN_ERROR;
+ }
+
+ ALOGV("descramble succeeded, %zd bytes", result);
+
+ if (dstBuffer.type == BufferType::SHARED_MEMORY) {
+ memcpy(it->mCodecBuffer->base(),
(uint8_t*)it->mSharedEncryptedBuffer->pointer(), result);
}
}
- if (result < 0) {
- return result;
- }
-
- if (destination.mType == ICrypto::kDestinationTypeSharedMemory) {
- memcpy(it->mCodecBuffer->base(), destination.mSharedMemory->pointer(), result);
- }
-
it->mCodecBuffer->setRange(0, result);
// Copy metadata from client to codec buffer.
@@ -275,10 +301,21 @@
int32_t seqNum = mCrypto->setHeap(dealer->getMemoryHeap());
if (seqNum >= 0) {
mHeapSeqNum = seqNum;
- ALOGD("setHeap returned mHeapSeqNum=%d", mHeapSeqNum);
+ ALOGV("setHeap returned mHeapSeqNum=%d", mHeapSeqNum);
} else {
mHeapSeqNum = -1;
- ALOGD("setHeap failed, setting mHeapSeqNum=-1");
+ ALOGE("setHeap failed, setting mHeapSeqNum=-1");
+ }
+ } else if (mDescrambler != nullptr) {
+ sp<IMemoryHeap> heap = dealer->getMemoryHeap();
+ native_handle_t* nativeHandle = native_handle_create(1, 0);
+ if (nativeHandle != nullptr) {
+ int fd = heap->getHeapID();
+ nativeHandle->data[0] = fd;
+ mHidlMemory = hidl_memory("ashmem", hidl_handle(nativeHandle), heap->getSize());
+ ALOGV("created hidl_memory for descrambler");
+ } else {
+ ALOGE("failed to create hidl_memory for descrambler");
}
}
return dealer;
diff --git a/media/libstagefright/Android.bp b/media/libstagefright/Android.bp
index 5fcb1fe..45a8d94 100644
--- a/media/libstagefright/Android.bp
+++ b/media/libstagefright/Android.bp
@@ -17,6 +17,7 @@
"AudioPlayer.cpp",
"AudioSource.cpp",
"BufferImpl.cpp",
+ "CodecBase.cpp",
"CallbackDataSource.cpp",
"CameraSource.cpp",
"CameraSourceTimeLapse.cpp",
@@ -105,6 +106,9 @@
"libhidlmemory",
"android.hidl.allocator@1.0",
"android.hidl.memory@1.0",
+ "android.hidl.token@1.0-utils",
+ "android.hardware.cas@1.0",
+ "android.hardware.cas.native@1.0",
"android.hardware.media.omx@1.0",
"libstagefright_xmlparser@1.0",
],
diff --git a/media/libstagefright/CodecBase.cpp b/media/libstagefright/CodecBase.cpp
new file mode 100644
index 0000000..d0610b2
--- /dev/null
+++ b/media/libstagefright/CodecBase.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "CodecBase"
+
+#include <android/hardware/cas/native/1.0/IDescrambler.h>
+#include <media/ICrypto.h>
+#include <media/stagefright/CodecBase.h>
+#include <utils/Log.h>
+
+namespace android {
+
+void BufferChannelBase::setCrypto(const sp<ICrypto> &crypto) {
+ mCrypto = crypto;
+}
+
+void BufferChannelBase::setDescrambler(const sp<IDescrambler> &descrambler) {
+ mDescrambler = descrambler;
+}
+
+} // namespace android
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index bd71632..98d101a 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -23,7 +23,8 @@
#include "include/SharedMemoryBuffer.h"
#include "include/SoftwareRenderer.h"
-#include <android/media/IDescrambler.h>
+#include <android/hardware/cas/native/1.0/IDescrambler.h>
+
#include <binder/IMemory.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
diff --git a/media/libstagefright/NuMediaExtractor.cpp b/media/libstagefright/NuMediaExtractor.cpp
index 51f1ba3..640cb82 100644
--- a/media/libstagefright/NuMediaExtractor.cpp
+++ b/media/libstagefright/NuMediaExtractor.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-//#define LOG_NDEBUG 0
+#define LOG_NDEBUG 0
#define LOG_TAG "NuMediaExtractor"
#include <utils/Log.h>
@@ -35,7 +35,6 @@
#include <media/stagefright/MediaSource.h>
#include <media/stagefright/MetaData.h>
#include <media/stagefright/Utils.h>
-#include <android/media/ICas.h>
namespace android {
@@ -83,8 +82,8 @@
return ERROR_UNSUPPORTED;
}
- if (mCas != NULL) {
- mImpl->setMediaCas(mCas);
+ if (!mCasToken.empty()) {
+ mImpl->setMediaCas(mCasToken);
}
status_t err = updateDurationAndBitrate();
@@ -119,8 +118,8 @@
return ERROR_UNSUPPORTED;
}
- if (mCas != NULL) {
- mImpl->setMediaCas(mCas);
+ if (!mCasToken.empty()) {
+ mImpl->setMediaCas(mCasToken);
}
err = updateDurationAndBitrate();
@@ -149,8 +148,8 @@
return ERROR_UNSUPPORTED;
}
- if (mCas != NULL) {
- mImpl->setMediaCas(mCas);
+ if (!mCasToken.empty()) {
+ mImpl->setMediaCas(mCasToken);
}
err = updateDurationAndBitrate();
@@ -161,24 +160,36 @@
return err;
}
-status_t NuMediaExtractor::setMediaCas(const sp<ICas> &cas) {
- ALOGV("setMediaCas: cas=%p", cas.get());
+static String8 arrayToString(const std::vector<uint8_t> &array) {
+ String8 result;
+ for (size_t i = 0; i < array.size(); i++) {
+ result.appendFormat("%02x ", array[i]);
+ }
+ if (result.isEmpty()) {
+ result.append("(null)");
+ }
+ return result;
+}
+
+status_t NuMediaExtractor::setMediaCas(const HInterfaceToken &casToken) {
+ ALOGV("setMediaCas: casToken={%s}", arrayToString(casToken).c_str());
Mutex::Autolock autoLock(mLock);
- if (cas == NULL) {
+ if (casToken.empty()) {
return BAD_VALUE;
}
+ mCasToken = casToken;
+
if (mImpl != NULL) {
- mImpl->setMediaCas(cas);
+ mImpl->setMediaCas(casToken);
status_t err = updateDurationAndBitrate();
if (err != OK) {
return err;
}
}
- mCas = cas;
return OK;
}
diff --git a/media/libstagefright/include/ACodecBufferChannel.h b/media/libstagefright/include/ACodecBufferChannel.h
index 0da2e81..f253a52 100644
--- a/media/libstagefright/include/ACodecBufferChannel.h
+++ b/media/libstagefright/include/ACodecBufferChannel.h
@@ -30,6 +30,8 @@
namespace android {
+using hardware::hidl_memory;
+
/**
* BufferChannelBase implementation for ACodec.
*/
@@ -117,6 +119,7 @@
sp<MemoryDealer> mDealer;
sp<IMemory> mDecryptDestination;
int32_t mHeapSeqNum;
+ hidl_memory mHidlMemory;
// These should only be accessed via std::atomic_* functions.
//
diff --git a/media/libstagefright/include/MPEG2TSExtractor.h b/media/libstagefright/include/MPEG2TSExtractor.h
index 2a75298f..ac93b5e 100644
--- a/media/libstagefright/include/MPEG2TSExtractor.h
+++ b/media/libstagefright/include/MPEG2TSExtractor.h
@@ -45,7 +45,7 @@
virtual sp<MetaData> getMetaData();
- virtual status_t setMediaCas(const sp<ICas> &cas) override;
+ virtual status_t setMediaCas(const HInterfaceToken &casToken) override;
virtual uint32_t flags() const;
virtual const char * name() { return "MPEG2TSExtractor"; }
diff --git a/media/libstagefright/include/media/stagefright/CodecBase.h b/media/libstagefright/include/media/stagefright/CodecBase.h
index 0dd77ba..6245ccb 100644
--- a/media/libstagefright/include/media/stagefright/CodecBase.h
+++ b/media/libstagefright/include/media/stagefright/CodecBase.h
@@ -24,27 +24,31 @@
#define STRINGIFY_ENUMS
-#include <media/ICrypto.h>
+#include <media/hardware/CryptoAPI.h>
+#include <media/hardware/HardwareAPI.h>
#include <media/IOMX.h>
#include <media/MediaCodecInfo.h>
-#include <media/stagefright/MediaErrors.h>
#include <media/stagefright/foundation/AHandler.h>
#include <media/stagefright/foundation/ColorUtils.h>
-#include <media/hardware/HardwareAPI.h>
-
+#include <media/stagefright/MediaErrors.h>
+#include <system/graphics.h>
#include <utils/NativeHandle.h>
-#include <system/graphics.h>
-#include <android/media/IDescrambler.h>
-
namespace android {
-using namespace media;
class BufferChannelBase;
struct BufferProducerWrapper;
class MediaCodecBuffer;
struct PersistentSurface;
struct RenderedFrameInfo;
class Surface;
+struct ICrypto;
+namespace hardware {
+namespace cas {
+namespace native {
+namespace V1_0 {
+struct IDescrambler;
+}}}}
+using hardware::cas::native::V1_0::IDescrambler;
struct CodecBase : public AHandler, /* static */ ColorUtils {
/**
@@ -256,13 +260,9 @@
mCallback = std::move(callback);
}
- inline void setCrypto(const sp<ICrypto> &crypto) {
- mCrypto = crypto;
- }
+ void setCrypto(const sp<ICrypto> &crypto);
- inline void setDescrambler(const sp<IDescrambler> &descrambler) {
- mDescrambler = descrambler;
- }
+ void setDescrambler(const sp<IDescrambler> &descrambler);
/**
* Queue an input buffer into the buffer channel.
diff --git a/media/libstagefright/include/media/stagefright/MediaCodec.h b/media/libstagefright/include/media/stagefright/MediaCodec.h
index 4140266..209fe12 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodec.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodec.h
@@ -47,10 +47,13 @@
struct PersistentSurface;
class SoftwareRenderer;
class Surface;
-namespace media {
-class IDescrambler;
-};
-using namespace media;
+namespace hardware {
+namespace cas {
+namespace native {
+namespace V1_0 {
+struct IDescrambler;
+}}}}
+using hardware::cas::native::V1_0::IDescrambler;
struct MediaCodec : public AHandler {
enum ConfigureFlags {
diff --git a/media/libstagefright/include/media/stagefright/MediaErrors.h b/media/libstagefright/include/media/stagefright/MediaErrors.h
index 2e663ec..6a5c6b6 100644
--- a/media/libstagefright/include/media/stagefright/MediaErrors.h
+++ b/media/libstagefright/include/media/stagefright/MediaErrors.h
@@ -79,6 +79,26 @@
HEARTBEAT_ERROR_BASE = -3000,
ERROR_HEARTBEAT_TERMINATE_REQUESTED = HEARTBEAT_ERROR_BASE,
+ // CAS-related error codes
+ CAS_ERROR_BASE = -4000,
+
+ ERROR_CAS_UNKNOWN = CAS_ERROR_BASE,
+ ERROR_CAS_NO_LICENSE = CAS_ERROR_BASE - 1,
+ ERROR_CAS_LICENSE_EXPIRED = CAS_ERROR_BASE - 2,
+ ERROR_CAS_SESSION_NOT_OPENED = CAS_ERROR_BASE - 3,
+ ERROR_CAS_DECRYPT_UNIT_NOT_INITIALIZED = CAS_ERROR_BASE - 4,
+ ERROR_CAS_DECRYPT = CAS_ERROR_BASE - 5,
+ ERROR_CAS_CANNOT_HANDLE = CAS_ERROR_BASE - 6,
+ ERROR_CAS_TAMPER_DETECTED = CAS_ERROR_BASE - 7,
+ ERROR_CAS_NOT_PROVISIONED = CAS_ERROR_BASE - 8,
+ ERROR_CAS_DEVICE_REVOKED = CAS_ERROR_BASE - 9,
+ ERROR_CAS_RESOURCE_BUSY = CAS_ERROR_BASE - 10,
+ ERROR_CAS_INSUFFICIENT_OUTPUT_PROTECTION = CAS_ERROR_BASE - 11,
+ ERROR_CAS_LAST_USED_ERRORCODE = CAS_ERROR_BASE - 11,
+
+ ERROR_CAS_VENDOR_MAX = CAS_ERROR_BASE - 500,
+ ERROR_CAS_VENDOR_MIN = CAS_ERROR_BASE - 999,
+
// NDK Error codes
// frameworks/av/include/ndk/NdkMediaError.h
// from -10000 (0xFFFFD8F0 - 0xFFFFD8EC)
diff --git a/media/libstagefright/include/media/stagefright/MediaExtractor.h b/media/libstagefright/include/media/stagefright/MediaExtractor.h
index a856b2b..f12160b 100644
--- a/media/libstagefright/include/media/stagefright/MediaExtractor.h
+++ b/media/libstagefright/include/media/stagefright/MediaExtractor.h
@@ -23,10 +23,6 @@
#include <media/MediaAnalyticsItem.h>
namespace android {
-namespace media {
-class ICas;
-};
-using namespace media;
class DataSource;
struct MediaSource;
class MetaData;
@@ -70,7 +66,7 @@
}
virtual void setUID(uid_t /*uid*/) {
}
- virtual status_t setMediaCas(const sp<ICas>& /*cas*/) override {
+ virtual status_t setMediaCas(const HInterfaceToken &/*casToken*/) override {
return INVALID_OPERATION;
}
diff --git a/media/libstagefright/include/media/stagefright/NuMediaExtractor.h b/media/libstagefright/include/media/stagefright/NuMediaExtractor.h
index 3e3cc17..6a93bd5 100644
--- a/media/libstagefright/include/media/stagefright/NuMediaExtractor.h
+++ b/media/libstagefright/include/media/stagefright/NuMediaExtractor.h
@@ -28,10 +28,6 @@
#include <utils/Vector.h>
namespace android {
-namespace media {
-class ICas;
-}
-using namespace media;
struct ABuffer;
struct AMessage;
@@ -64,7 +60,7 @@
status_t setDataSource(const sp<DataSource> &datasource);
- status_t setMediaCas(const sp<ICas> &cas);
+ status_t setMediaCas(const HInterfaceToken &casToken);
size_t countTracks() const;
status_t getTrackFormat(size_t index, sp<AMessage> *format, uint32_t flags = 0) const;
@@ -115,7 +111,7 @@
sp<DataSource> mDataSource;
sp<IMediaExtractor> mImpl;
- sp<ICas> mCas;
+ HInterfaceToken mCasToken;
Vector<TrackInfo> mSelectedTracks;
int64_t mTotalBitrate; // in bits/sec
diff --git a/media/libstagefright/mpeg2ts/ATSParser.cpp b/media/libstagefright/mpeg2ts/ATSParser.cpp
index 31edb21..a256a4d 100644
--- a/media/libstagefright/mpeg2ts/ATSParser.cpp
+++ b/media/libstagefright/mpeg2ts/ATSParser.cpp
@@ -23,8 +23,8 @@
#include "ESQueue.h"
#include "include/avc_utils.h"
-#include <android/media/IDescrambler.h>
-#include <binder/MemoryDealer.h>
+#include <android/hardware/cas/native/1.0/IDescrambler.h>
+#include <cutils/native_handle.h>
#include <media/stagefright/foundation/ABitReader.h>
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h>
@@ -41,8 +41,12 @@
#include <inttypes.h>
namespace android {
-using binder::Status;
-using MediaDescrambler::DescrambleInfo;
+using hardware::hidl_handle;
+using hardware::hidl_memory;
+using hardware::hidl_string;
+using hardware::hidl_vec;
+using namespace hardware::cas::V1_0;
+using namespace hardware::cas::native::V1_0;
// I want the expression "y" evaluated even if verbose logging is off.
#define MY_LOGV(x, y) \
@@ -203,6 +207,7 @@
sp<AMessage> mSampleAesKeyItem;
sp<IMemory> mMem;
sp<MemoryDealer> mDealer;
+ hardware::cas::native::V1_0::SharedBuffer mDescramblerSrcBuffer;
sp<ABuffer> mDescrambledBuffer;
List<SubSampleInfo> mSubSamples;
sp<IDescrambler> mDescrambler;
@@ -235,7 +240,7 @@
// Ensure internal buffers can hold specified size, and will re-allocate
// as needed.
- void ensureBufferCapacity(size_t size);
+ bool ensureBufferCapacity(size_t size);
DISALLOW_EVIL_CONSTRUCTORS(Stream);
};
@@ -807,9 +812,9 @@
mQueue = NULL;
}
-void ATSParser::Stream::ensureBufferCapacity(size_t neededSize) {
+bool ATSParser::Stream::ensureBufferCapacity(size_t neededSize) {
if (mBuffer != NULL && mBuffer->capacity() >= neededSize) {
- return;
+ return true;
}
ALOGV("ensureBufferCapacity: current size %zu, new size %zu, scrambled %d",
@@ -837,6 +842,26 @@
mMem = newMem;
mDealer = newDealer;
mDescrambledBuffer = newScrambledBuffer;
+
+ ssize_t offset;
+ size_t size;
+ sp<IMemoryHeap> heap = newMem->getMemory(&offset, &size);
+ if (heap == NULL) {
+ return false;
+ }
+ native_handle_t* nativeHandle = native_handle_create(1, 0);
+ if (!nativeHandle) {
+ ALOGE("[stream %d] failed to create native handle", mElementaryPID);
+ return false;
+ }
+ nativeHandle->data[0] = heap->getHeapID();
+ mDescramblerSrcBuffer.heapBase = hidl_memory("ashmem",
+ hidl_handle(nativeHandle), heap->getSize());
+ mDescramblerSrcBuffer.offset = (uint64_t) offset;
+ mDescramblerSrcBuffer.size = (uint64_t) size;
+
+ ALOGD("[stream %d] created shared buffer for descrambling, offset %zd, size %zu",
+ mElementaryPID, offset, size);
} else {
// Align to multiples of 64K.
neededSize = (neededSize + 65535) & ~65535;
@@ -850,6 +875,7 @@
newBuffer->setRange(0, 0);
}
mBuffer = newBuffer;
+ return true;
}
status_t ATSParser::Stream::parse(
@@ -923,7 +949,9 @@
}
size_t neededSize = mBuffer->size() + payloadSizeBits / 8;
- ensureBufferCapacity(neededSize);
+ if (!ensureBufferCapacity(neededSize)) {
+ return NO_MEMORY;
+ }
memcpy(mBuffer->data() + mBuffer->size(), br->data(), payloadSizeBits / 8);
mBuffer->setRange(0, mBuffer->size() + payloadSizeBits / 8);
@@ -1365,47 +1393,59 @@
memcpy(mDescrambledBuffer->data(), mBuffer->data(), descrambleBytes);
mDescrambledBuffer->setRange(0, descrambleBytes);
- sp<ABuffer> subSamples = new ABuffer(
- sizeof(DescramblerPlugin::SubSample) * descrambleSubSamples);
-
- DescrambleInfo info;
- info.dstType = DescrambleInfo::kDestinationTypeVmPointer;
- info.scramblingControl = (DescramblerPlugin::ScramblingControl)sctrl;
- info.numSubSamples = descrambleSubSamples;
- info.subSamples = (DescramblerPlugin::SubSample *)subSamples->data();
- info.srcMem = mMem;
- info.srcOffset = 0;
- info.dstPtr = NULL; // in-place descrambling into srcMem
- info.dstOffset = 0;
+ hidl_vec<SubSample> subSamples;
+ subSamples.resize(descrambleSubSamples);
int32_t i = 0;
for (auto it = mSubSamples.begin();
it != mSubSamples.end() && i < descrambleSubSamples; it++, i++) {
if (it->transport_scrambling_mode != 0 || pesScramblingControl != 0) {
- info.subSamples[i].mNumBytesOfClearData = 0;
- info.subSamples[i].mNumBytesOfEncryptedData = it->subSampleSize;
+ subSamples[i].numBytesOfClearData = 0;
+ subSamples[i].numBytesOfEncryptedData = it->subSampleSize;
} else {
- info.subSamples[i].mNumBytesOfClearData = it->subSampleSize;
- info.subSamples[i].mNumBytesOfEncryptedData = 0;
+ subSamples[i].numBytesOfClearData = it->subSampleSize;
+ subSamples[i].numBytesOfEncryptedData = 0;
}
}
+
+ uint64_t srcOffset = 0, dstOffset = 0;
// If scrambled at PES-level, PES header should be skipped
if (pesScramblingControl != 0) {
- info.srcOffset = info.dstOffset = pesOffset;
- info.subSamples[0].mNumBytesOfEncryptedData -= pesOffset;
+ srcOffset = dstOffset = pesOffset;
+ subSamples[0].numBytesOfEncryptedData -= pesOffset;
}
- int32_t result;
- Status status = mDescrambler->descramble(info, &result);
+ Status status = Status::OK;
+ uint32_t bytesWritten = 0;
+ hidl_string detailedError;
- if (!status.isOk()) {
- ALOGE("[stream %d] descramble failed, exceptionCode=%d",
- mElementaryPID, status.exceptionCode());
+ DestinationBuffer dstBuffer;
+ dstBuffer.type = BufferType::SHARED_MEMORY;
+ dstBuffer.nonsecureMemory = mDescramblerSrcBuffer;
+
+ auto returnVoid = mDescrambler->descramble(
+ (ScramblingControl) sctrl,
+ subSamples,
+ mDescramblerSrcBuffer,
+ srcOffset,
+ dstBuffer,
+ dstOffset,
+ [&status, &bytesWritten, &detailedError] (
+ Status _status, uint32_t _bytesWritten,
+ const hidl_string& _detailedError) {
+ status = _status;
+ bytesWritten = _bytesWritten;
+ detailedError = _detailedError;
+ });
+
+ if (!returnVoid.isOk()) {
+ ALOGE("[stream %d] descramble failed, trans=%s",
+ mElementaryPID, returnVoid.description().c_str());
return UNKNOWN_ERROR;
}
ALOGV("[stream %d] descramble succeeded, %d bytes",
- mElementaryPID, result);
+ mElementaryPID, bytesWritten);
memcpy(mBuffer->data(), mDescrambledBuffer->data(), descrambleBytes);
}
diff --git a/media/libstagefright/mpeg2ts/ATSParser.h b/media/libstagefright/mpeg2ts/ATSParser.h
index 374e011..41c19cd 100644
--- a/media/libstagefright/mpeg2ts/ATSParser.h
+++ b/media/libstagefright/mpeg2ts/ATSParser.h
@@ -29,11 +29,13 @@
#include <vector>
namespace android {
-namespace media {
-class ICas;
-class IDescrambler;
-};
-using namespace media;
+namespace hardware {
+namespace cas {
+namespace V1_0 {
+struct ICas;
+}}}
+using hardware::cas::V1_0::ICas;
+
class ABitReader;
struct ABuffer;
struct AnotherPacketSource;
diff --git a/media/libstagefright/mpeg2ts/Android.bp b/media/libstagefright/mpeg2ts/Android.bp
index 96eb5bf..21259c4 100644
--- a/media/libstagefright/mpeg2ts/Android.bp
+++ b/media/libstagefright/mpeg2ts/Android.bp
@@ -35,5 +35,8 @@
shared_libs: [
"libcrypto",
"libmedia",
+ "libhidlmemory",
+ "android.hardware.cas.native@1.0",
+ "android.hidl.memory@1.0",
],
}
diff --git a/media/libstagefright/mpeg2ts/CasManager.cpp b/media/libstagefright/mpeg2ts/CasManager.cpp
index 047b1b3..9ff4521 100644
--- a/media/libstagefright/mpeg2ts/CasManager.cpp
+++ b/media/libstagefright/mpeg2ts/CasManager.cpp
@@ -18,15 +18,19 @@
#define LOG_TAG "CasManager"
#include "CasManager.h"
-#include <android/media/ICas.h>
-#include <android/media/IDescrambler.h>
-#include <android/media/IMediaCasService.h>
-#include <binder/IServiceManager.h>
+#include <android/hardware/cas/1.0/ICas.h>
+#include <android/hardware/cas/1.0/IMediaCasService.h>
+#include <android/hardware/cas/native/1.0/IDescrambler.h>
+#include <hidl/HidlSupport.h>
#include <media/stagefright/foundation/ABitReader.h>
#include <utils/Log.h>
namespace android {
-using binder::Status;
+
+using hardware::hidl_vec;
+using hardware::Return;
+using namespace hardware::cas::V1_0;
+using namespace hardware::cas::native::V1_0;
struct ATSParser::CasManager::ProgramCasManager : public RefBase {
ProgramCasManager(unsigned programNumber, const CADescriptor &descriptor);
@@ -125,45 +129,60 @@
const sp<ICas>& cas,
PidToSessionMap &sessionMap,
CasSession *session) {
- sp<IServiceManager> sm = defaultServiceManager();
- sp<IBinder> casServiceBinder = sm->getService(String16("media.cas"));
- sp<IMediaCasService> casService =
- interface_cast<IMediaCasService>(casServiceBinder);
-
+ sp<IMediaCasService> casService = IMediaCasService::getService("default");
if (casService == NULL) {
ALOGE("Cannot obtain IMediaCasService");
return NO_INIT;
}
+ Status status;
sp<IDescrambler> descrambler;
+ sp<IDescramblerBase> descramblerBase;
+ Return<Status> returnStatus(Status::OK);
+ Return<sp<IDescramblerBase> > returnDescrambler(NULL);
std::vector<uint8_t> sessionId;
const CADescriptor &descriptor = session->mCADescriptor;
- Status status = cas->openSession(&sessionId);
- if (!status.isOk()) {
- ALOGE("Failed to open session: exception=%d, error=%d",
- status.exceptionCode(), status.serviceSpecificErrorCode());
+ auto returnVoid = cas->openSession(
+ [&status, &sessionId] (Status _status, const hidl_vec<uint8_t>& _sessionId) {
+ status = _status;
+ sessionId = _sessionId;
+ });
+ if (!returnVoid.isOk() || status != Status::OK) {
+ ALOGE("Failed to open session: trans=%s, status=%d",
+ returnVoid.description().c_str(), status);
goto l_fail;
}
- cas->setSessionPrivateData(sessionId, descriptor.mPrivateData);
- if (!status.isOk()) {
- ALOGE("Failed to set private data: exception=%d, error=%d",
- status.exceptionCode(), status.serviceSpecificErrorCode());
+ returnStatus = cas->setSessionPrivateData(sessionId, descriptor.mPrivateData);
+ if (!returnStatus.isOk() || returnStatus != Status::OK) {
+ ALOGE("Failed to set private data: trans=%s, status=%d",
+ returnStatus.description().c_str(), (Status)returnStatus);
goto l_fail;
}
- status = casService->createDescrambler(descriptor.mSystemID, &descrambler);
- if (!status.isOk() || descrambler == NULL) {
- ALOGE("Failed to create descrambler: : exception=%d, error=%d",
- status.exceptionCode(), status.serviceSpecificErrorCode());
+ returnDescrambler = casService->createDescrambler(descriptor.mSystemID);
+ if (!returnDescrambler.isOk()) {
+ ALOGE("Failed to create descrambler: trans=%s",
+ returnDescrambler.description().c_str());
+ goto l_fail;
+ }
+ descramblerBase = (sp<IDescramblerBase>) returnDescrambler;
+ if (descramblerBase == NULL) {
+ ALOGE("Failed to create descrambler: null ptr");
goto l_fail;
}
- status = descrambler->setMediaCasSession(sessionId);
- if (!status.isOk()) {
- ALOGE("Failed to init descrambler: : exception=%d, error=%d",
- status.exceptionCode(), status.serviceSpecificErrorCode());
+ returnStatus = descramblerBase->setMediaCasSession(sessionId);
+ if (!returnStatus.isOk() || (Status) returnStatus != Status::OK) {
+ ALOGE("Failed to init descrambler: : trans=%s, status=%d",
+ returnStatus.description().c_str(), (Status) returnStatus);
+ goto l_fail;
+ }
+
+ descrambler = IDescrambler::castFrom(descramblerBase);
+ if (descrambler == NULL) {
+ ALOGE("Failed to cast from IDescramblerBase to IDescrambler");
goto l_fail;
}
@@ -177,8 +196,8 @@
if (!sessionId.empty()) {
cas->closeSession(sessionId);
}
- if (descrambler != NULL) {
- descrambler->release();
+ if (descramblerBase != NULL) {
+ descramblerBase->release();
}
return NO_INIT;
}
@@ -316,11 +335,12 @@
if (index < 0) {
return false;
}
- MediaCas::ParcelableCasData ecm(br->data(), br->numBitsLeft() / 8);
- Status status = mICas->processEcm(mCAPidToSessionIdMap[index], ecm);
- if (!status.isOk()) {
- ALOGE("Failed to process ECM: exception=%d, error=%d",
- status.exceptionCode(), status.serviceSpecificErrorCode());
+ hidl_vec<uint8_t> ecm;
+ ecm.setToExternal((uint8_t*)br->data(), br->numBitsLeft() / 8);
+ auto returnStatus = mICas->processEcm(mCAPidToSessionIdMap[index], ecm);
+ if (!returnStatus.isOk() || (Status) returnStatus != Status::OK) {
+ ALOGE("Failed to process ECM: trans=%s, status=%d",
+ returnStatus.description().c_str(), (Status) returnStatus);
}
return true; // handled
}
diff --git a/media/libstagefright/mpeg2ts/CasManager.h b/media/libstagefright/mpeg2ts/CasManager.h
index 8088dec..81f6546 100644
--- a/media/libstagefright/mpeg2ts/CasManager.h
+++ b/media/libstagefright/mpeg2ts/CasManager.h
@@ -21,10 +21,13 @@
#include <set>
namespace android {
-namespace media {
-class ICas;
-class IDescrambler;
-}
+namespace hardware {
+namespace cas {
+namespace native {
+namespace V1_0 {
+struct IDescrambler;
+}}}}
+using hardware::cas::native::V1_0::IDescrambler;
struct ATSParser::CasManager : public RefBase {
CasManager();
diff --git a/media/libstagefright/mpeg2ts/MPEG2TSExtractor.cpp b/media/libstagefright/mpeg2ts/MPEG2TSExtractor.cpp
index c3f1274..9d684e0 100644
--- a/media/libstagefright/mpeg2ts/MPEG2TSExtractor.cpp
+++ b/media/libstagefright/mpeg2ts/MPEG2TSExtractor.cpp
@@ -38,8 +38,13 @@
#include "AnotherPacketSource.h"
#include "ATSParser.h"
+#include <hidl/HybridInterface.h>
+#include <android/hardware/cas/1.0/ICas.h>
+
namespace android {
+using hardware::cas::V1_0::ICas;
+
static const size_t kTSPacketSize = 188;
static const int kMaxDurationReadSize = 250000LL;
static const int kMaxDurationRetry = 6;
@@ -156,7 +161,10 @@
|| !strcasecmp(MEDIA_MIMETYPE_AUDIO_SCRAMBLED, mime));
}
-status_t MPEG2TSExtractor::setMediaCas(const sp<ICas> &cas) {
+status_t MPEG2TSExtractor::setMediaCas(const HInterfaceToken &casToken) {
+ HalToken halToken;
+ halToken.setToExternal((uint8_t*)casToken.data(), casToken.size());
+ sp<ICas> cas = ICas::castFrom(retrieveHalInterface(halToken));
ALOGD("setMediaCas: %p", cas.get());
status_t err = mParser->setMediaCas(cas);