Merge "Adding hasProfile."
diff --git a/cmds/stagefright/record.cpp b/cmds/stagefright/record.cpp
index 5a87f4c..c424281 100644
--- a/cmds/stagefright/record.cpp
+++ b/cmds/stagefright/record.cpp
@@ -32,9 +32,15 @@
using namespace android;
+static const int32_t kFramerate = 24; // fps
+static const int32_t kIFramesIntervalSec = 1;
+static const int32_t kVideoBitRate = 512 * 1024;
+static const int32_t kAudioBitRate = 12200;
+static const int32_t kColorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
+static const int64_t kDurationUs = 10000000LL; // 10 seconds
+
#if 1
class DummySource : public MediaSource {
- static const int32_t kFramerate = 24; // fps
public:
DummySource(int width, int height)
@@ -176,6 +182,12 @@
enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
enc_meta->setInt32(kKeyWidth, width);
enc_meta->setInt32(kKeyHeight, height);
+ enc_meta->setInt32(kKeySampleRate, kFramerate);
+ enc_meta->setInt32(kKeyBitRate, kVideoBitRate);
+ enc_meta->setInt32(kKeyStride, width);
+ enc_meta->setInt32(kKeySliceHeight, height);
+ enc_meta->setInt32(kKeyIFramesInterval, kIFramesIntervalSec);
+ enc_meta->setInt32(kKeyColorFormat, kColorFormat);
sp<MediaSource> encoder =
OMXCodec::Create(
@@ -184,8 +196,10 @@
#if 1
sp<MPEG4Writer> writer = new MPEG4Writer("/sdcard/output.mp4");
writer->addSource(encoder);
+ writer->setMaxFileDuration(kDurationUs);
writer->start();
while (!writer->reachedEOS()) {
+ fprintf(stderr, ".");
usleep(100000);
}
writer->stop();
@@ -194,6 +208,8 @@
MediaBuffer *buffer;
while (encoder->read(&buffer) == OK) {
+ printf(".");
+ fflush(stdout);
int32_t isSync;
if (!buffer->meta_data()->findInt32(kKeyIsSyncFrame, &isSync)) {
isSync = false;
@@ -209,6 +225,7 @@
encoder->stop();
#endif
+ printf("$\n");
client.disconnect();
#endif
@@ -267,6 +284,7 @@
encMeta->setInt32(kKeySampleRate, kSampleRate);
encMeta->setInt32(kKeyChannelCount, kNumChannels);
encMeta->setInt32(kKeyMaxInputSize, 8192);
+ encMeta->setInt32(kKeyBitRate, kAudioBitRate);
sp<MediaSource> encoder =
OMXCodec::Create(client.interface(), encMeta, true, audioSource);
diff --git a/drm/common/Android.mk b/drm/common/Android.mk
new file mode 100644
index 0000000..249fe8e
--- /dev/null
+++ b/drm/common/Android.mk
@@ -0,0 +1,41 @@
+#
+# Copyright (C) 2010 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.
+#
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ DrmConstraints.cpp \
+ DrmConvertedStatus.cpp \
+ DrmEngineBase.cpp \
+ DrmInfo.cpp \
+ DrmInfoRequest.cpp \
+ DrmInfoStatus.cpp \
+ DrmRights.cpp \
+ DrmSupportInfo.cpp \
+ IDrmIOService.cpp \
+ IDrmManagerService.cpp \
+ IDrmServiceListener.cpp \
+ DrmInfoEvent.cpp \
+ ReadWriteUtils.cpp
+
+LOCAL_C_INCLUDES := \
+ $(TOP)/frameworks/base/include \
+ $(TOP)/frameworks/base/drm/libdrmframework/include \
+ $(TOP)/frameworks/base/drm/libdrmframework/plugins/common/include
+
+LOCAL_MODULE:= libdrmframeworkcommon
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/drm/common/DrmConstraints.cpp b/drm/common/DrmConstraints.cpp
new file mode 100644
index 0000000..11ce410
--- /dev/null
+++ b/drm/common/DrmConstraints.cpp
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#include <drm/DrmConstraints.h>
+
+using namespace android;
+
+const String8 DrmConstraints::MAX_REPEAT_COUNT("max_repeat_count");
+const String8 DrmConstraints::REMAINING_REPEAT_COUNT("remaining_repeat_count");
+const String8 DrmConstraints::LICENSE_START_TIME("license_start_time");
+const String8 DrmConstraints::LICENSE_EXPIRY_TIME("license_expiry_time");
+const String8 DrmConstraints::LICENSE_AVAILABLE_TIME("license_available_time");
+const String8 DrmConstraints::EXTENDED_METADATA("extended_metadata");
+
+int DrmConstraints::getCount(void) const {
+ return mConstraintMap.size();
+}
+
+status_t DrmConstraints::put(const String8* key, const char* value) {
+ int length = strlen(value);
+ char* charValue = new char[length + 1];
+ if (NULL != charValue) {
+ strncpy(charValue, value, length);
+ charValue[length] = '\0';
+ mConstraintMap.add(*key, charValue);
+ }
+ return DRM_NO_ERROR;
+}
+
+String8 DrmConstraints::get(const String8& key) const {
+ if (NULL != getValue(&key)) {
+ return String8(getValue(&key));
+ }
+ return String8("");
+}
+
+const char* DrmConstraints::getValue(const String8* key) const {
+ if (NAME_NOT_FOUND != mConstraintMap.indexOfKey(*key)) {
+ return mConstraintMap.valueFor(*key);
+ }
+ return NULL;
+}
+
+const char* DrmConstraints::getAsByteArray(const String8* key) const {
+ return getValue(key);
+}
+
+bool DrmConstraints::KeyIterator::hasNext() {
+ return mIndex < mDrmConstraints->mConstraintMap.size();
+}
+
+const String8& DrmConstraints::KeyIterator::next() {
+ const String8& key = mDrmConstraints->mConstraintMap.keyAt(mIndex);
+ mIndex++;
+ return key;
+}
+
+DrmConstraints::KeyIterator DrmConstraints::keyIterator() {
+ return KeyIterator(this);
+}
+
+DrmConstraints::KeyIterator::KeyIterator(const DrmConstraints::KeyIterator& keyIterator)
+ : mDrmConstraints(keyIterator.mDrmConstraints),
+ mIndex(keyIterator.mIndex) {
+ LOGV("DrmConstraints::KeyIterator::KeyIterator");
+}
+
+DrmConstraints::KeyIterator& DrmConstraints::KeyIterator::operator=(
+ const DrmConstraints::KeyIterator& keyIterator) {
+ LOGV("DrmConstraints::KeyIterator::operator=");
+ mDrmConstraints = keyIterator.mDrmConstraints;
+ mIndex = keyIterator.mIndex;
+ return *this;
+}
+
+
+DrmConstraints::Iterator DrmConstraints::iterator() {
+ return Iterator(this);
+}
+
+DrmConstraints::Iterator::Iterator(const DrmConstraints::Iterator& iterator) :
+ mDrmConstraints(iterator.mDrmConstraints),
+ mIndex(iterator.mIndex) {
+ LOGV("DrmConstraints::Iterator::Iterator");
+}
+
+DrmConstraints::Iterator& DrmConstraints::Iterator::operator=(
+ const DrmConstraints::Iterator& iterator) {
+ LOGV("DrmConstraints::Iterator::operator=");
+ mDrmConstraints = iterator.mDrmConstraints;
+ mIndex = iterator.mIndex;
+ return *this;
+}
+
+bool DrmConstraints::Iterator::hasNext() {
+ return mIndex < mDrmConstraints->mConstraintMap.size();
+}
+
+String8 DrmConstraints::Iterator::next() {
+ String8 value = String8(mDrmConstraints->mConstraintMap.editValueAt(mIndex));
+ mIndex++;
+ return value;
+}
+
diff --git a/drm/common/DrmConvertedStatus.cpp b/drm/common/DrmConvertedStatus.cpp
new file mode 100644
index 0000000..5d035f5
--- /dev/null
+++ b/drm/common/DrmConvertedStatus.cpp
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#include <drm/DrmConvertedStatus.h>
+
+using namespace android;
+
+DrmConvertedStatus::DrmConvertedStatus(
+ int _statusCode, const DrmBuffer* _convertedData, int _offset) :
+ statusCode(_statusCode),
+ convertedData(_convertedData),
+ offset(_offset) {
+
+}
+
diff --git a/drm/common/DrmEngineBase.cpp b/drm/common/DrmEngineBase.cpp
new file mode 100644
index 0000000..70398e8
--- /dev/null
+++ b/drm/common/DrmEngineBase.cpp
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#include "DrmEngineBase.h"
+
+using namespace android;
+
+DrmEngineBase::DrmEngineBase() {
+
+}
+
+DrmEngineBase::~DrmEngineBase() {
+
+}
+
+DrmConstraints* DrmEngineBase::getConstraints(
+ int uniqueId, const String8* path, int action) {
+ return onGetConstraints(uniqueId, path, action);
+}
+
+status_t DrmEngineBase::initialize(int uniqueId) {
+ return onInitialize(uniqueId);
+}
+
+status_t DrmEngineBase::setOnInfoListener(
+ int uniqueId, const IDrmEngine::OnInfoListener* infoListener) {
+ return onSetOnInfoListener(uniqueId, infoListener);
+}
+
+status_t DrmEngineBase::terminate(int uniqueId) {
+ return onTerminate(uniqueId);
+}
+
+bool DrmEngineBase::canHandle(int uniqueId, const String8& path) {
+ return onCanHandle(uniqueId, path);
+}
+
+DrmInfoStatus* DrmEngineBase::processDrmInfo(int uniqueId, const DrmInfo* drmInfo) {
+ return onProcessDrmInfo(uniqueId, drmInfo);
+}
+
+void DrmEngineBase::saveRights(
+ int uniqueId, const DrmRights& drmRights,
+ const String8& rightsPath, const String8& contentPath) {
+ return onSaveRights(uniqueId, drmRights, rightsPath, contentPath);
+}
+
+DrmInfo* DrmEngineBase::acquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInfoRequest) {
+ return onAcquireDrmInfo(uniqueId, drmInfoRequest);
+}
+
+String8 DrmEngineBase::getOriginalMimeType(int uniqueId, const String8& path) {
+ return onGetOriginalMimeType(uniqueId, path);
+}
+
+int DrmEngineBase::getDrmObjectType(int uniqueId, const String8& path, const String8& mimeType) {
+ return onGetDrmObjectType(uniqueId, path, mimeType);
+}
+
+int DrmEngineBase::checkRightsStatus(int uniqueId, const String8& path, int action) {
+ return onCheckRightsStatus(uniqueId, path, action);
+}
+
+void DrmEngineBase::consumeRights(
+ int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve) {
+ onConsumeRights(uniqueId, decryptHandle, action, reserve);
+}
+
+void DrmEngineBase::setPlaybackStatus(
+ int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int position) {
+ onSetPlaybackStatus(uniqueId, decryptHandle, playbackStatus, position);
+}
+
+bool DrmEngineBase::validateAction(
+ int uniqueId, const String8& path,
+ int action, const ActionDescription& description) {
+ return onValidateAction(uniqueId, path, action, description);
+}
+
+void DrmEngineBase::removeRights(int uniqueId, const String8& path) {
+ onRemoveRights(uniqueId, path);
+}
+
+void DrmEngineBase::removeAllRights(int uniqueId) {
+ onRemoveAllRights(uniqueId);
+}
+
+void DrmEngineBase::openConvertSession(int uniqueId, int convertId) {
+ onOpenConvertSession(uniqueId, convertId);
+}
+
+DrmConvertedStatus* DrmEngineBase::convertData(
+ int uniqueId, int convertId, const DrmBuffer* inputData) {
+ return onConvertData(uniqueId, convertId, inputData);
+}
+
+DrmConvertedStatus* DrmEngineBase::closeConvertSession(int uniqueId, int convertId) {
+ return onCloseConvertSession(uniqueId, convertId);
+}
+
+DrmSupportInfo* DrmEngineBase::getSupportInfo(int uniqueId) {
+ return onGetSupportInfo(uniqueId);
+}
+
+status_t DrmEngineBase::openDecryptSession(
+ int uniqueId, DecryptHandle* decryptHandle, int fd, int offset, int length) {
+ return onOpenDecryptSession(uniqueId, decryptHandle, fd, offset, length);
+}
+
+void DrmEngineBase::closeDecryptSession(int uniqueId, DecryptHandle* decryptHandle) {
+ onCloseDecryptSession(uniqueId, decryptHandle);
+}
+
+void DrmEngineBase::initializeDecryptUnit(
+ int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId, const DrmBuffer* headerInfo) {
+ onInitializeDecryptUnit(uniqueId, decryptHandle, decryptUnitId, headerInfo);
+}
+
+status_t DrmEngineBase::decrypt(
+ int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId,
+ const DrmBuffer* encBuffer, DrmBuffer** decBuffer) {
+ return onDecrypt(uniqueId, decryptHandle, decryptUnitId, encBuffer, decBuffer);
+}
+
+void DrmEngineBase::finalizeDecryptUnit(
+ int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId) {
+ onFinalizeDecryptUnit(uniqueId, decryptHandle, decryptUnitId);
+}
+
+ssize_t DrmEngineBase::pread(
+ int uniqueId, DecryptHandle* decryptHandle, void* buffer, ssize_t numBytes, off_t offset) {
+ return onPread(uniqueId, decryptHandle, buffer, numBytes, offset);
+}
+
diff --git a/drm/common/DrmInfo.cpp b/drm/common/DrmInfo.cpp
new file mode 100644
index 0000000..ddcab33
--- /dev/null
+++ b/drm/common/DrmInfo.cpp
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#include <drm/DrmInfo.h>
+
+using namespace android;
+
+DrmInfo::DrmInfo(int infoType, const DrmBuffer& drmBuffer, const String8& mimeType) :
+ mInfoType(infoType),
+ mData(drmBuffer),
+ mMimeType(mimeType) {
+
+}
+
+int DrmInfo::getInfoType(void) const {
+ return mInfoType;
+}
+
+String8 DrmInfo::getMimeType(void) const {
+ return mMimeType;
+}
+
+const DrmBuffer& DrmInfo::getData(void) const {
+ return mData;
+}
+
+int DrmInfo::getCount(void) const {
+ return mAttributes.size();
+}
+
+status_t DrmInfo::put(const String8& key, const String8& value) {
+ mAttributes.add(key, value);
+ return DRM_NO_ERROR;
+}
+
+String8 DrmInfo::get(const String8& key) const {
+ if (NAME_NOT_FOUND != mAttributes.indexOfKey(key)) {
+ return mAttributes.valueFor(key);
+ }
+ return String8("");
+}
+
+int DrmInfo::indexOfKey(const String8& key) const {
+ return mAttributes.indexOfKey(key);
+}
+
+DrmInfo::KeyIterator DrmInfo::keyIterator() const {
+ return KeyIterator(this);
+}
+
+DrmInfo::Iterator DrmInfo::iterator() const {
+ return Iterator(this);
+}
+
+// KeyIterator implementation
+DrmInfo::KeyIterator::KeyIterator(const DrmInfo::KeyIterator& keyIterator) :
+ mDrmInfo(keyIterator.mDrmInfo), mIndex(keyIterator.mIndex) {
+
+}
+
+bool DrmInfo::KeyIterator::hasNext() {
+ return (mIndex < mDrmInfo->mAttributes.size());
+}
+
+const String8& DrmInfo::KeyIterator::next() {
+ const String8& key = mDrmInfo->mAttributes.keyAt(mIndex);
+ mIndex++;
+ return key;
+}
+
+DrmInfo::KeyIterator& DrmInfo::KeyIterator::operator=(const DrmInfo::KeyIterator& keyIterator) {
+ mDrmInfo = keyIterator.mDrmInfo;
+ mIndex = keyIterator.mIndex;
+ return *this;
+}
+
+// Iterator implementation
+DrmInfo::Iterator::Iterator(const DrmInfo::Iterator& iterator)
+ : mDrmInfo(iterator.mDrmInfo), mIndex(iterator.mIndex) {
+
+}
+
+DrmInfo::Iterator& DrmInfo::Iterator::operator=(const DrmInfo::Iterator& iterator) {
+ mDrmInfo = iterator.mDrmInfo;
+ mIndex = iterator.mIndex;
+ return *this;
+}
+
+bool DrmInfo::Iterator::hasNext() {
+ return mIndex < mDrmInfo->mAttributes.size();
+}
+
+String8& DrmInfo::Iterator::next() {
+ String8& value = mDrmInfo->mAttributes.editValueAt(mIndex);
+ mIndex++;
+ return value;
+}
+
diff --git a/drm/common/DrmInfoEvent.cpp b/drm/common/DrmInfoEvent.cpp
new file mode 100644
index 0000000..eb58129
--- /dev/null
+++ b/drm/common/DrmInfoEvent.cpp
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2010 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 "DrmInfoEvent"
+#include "utils/Log.h"
+
+#include <utils/String8.h>
+#include <drm/DrmInfoEvent.h>
+
+using namespace android;
+
+DrmInfoEvent::DrmInfoEvent(int uniqueId, int infoType, const String8& message)
+ : mUniqueId(uniqueId),
+ mInfoType(infoType),
+ mMessage(message) {
+
+}
+
+int DrmInfoEvent::getUniqueId() const {
+ return mUniqueId;
+}
+
+int DrmInfoEvent::getType() const {
+ return mInfoType;
+}
+
+const String8& DrmInfoEvent::getMessage() const {
+ return mMessage;
+}
+
diff --git a/drm/common/DrmInfoRequest.cpp b/drm/common/DrmInfoRequest.cpp
new file mode 100644
index 0000000..a646859
--- /dev/null
+++ b/drm/common/DrmInfoRequest.cpp
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#include <drm/DrmInfoRequest.h>
+
+using namespace android;
+
+const String8 DrmInfoRequest::ACCOUNT_ID("account_id");
+const String8 DrmInfoRequest::SUBSCRIPTION_ID("subscription_id");
+
+DrmInfoRequest::DrmInfoRequest(int infoType, const String8& mimeType) :
+ mInfoType(infoType), mMimeType(mimeType) {
+
+}
+
+String8 DrmInfoRequest::getMimeType(void) const {
+ return mMimeType;
+}
+
+int DrmInfoRequest::getInfoType(void) const {
+ return mInfoType;
+}
+
+int DrmInfoRequest::getCount(void) const {
+ return mRequestInformationMap.size();
+}
+
+status_t DrmInfoRequest::put(const String8& key, const String8& value) {
+ mRequestInformationMap.add(key, value);
+ return DRM_NO_ERROR;
+}
+
+String8 DrmInfoRequest::get(const String8& key) const {
+ if (NAME_NOT_FOUND != mRequestInformationMap.indexOfKey(key)) {
+ return mRequestInformationMap.valueFor(key);
+ }
+ return String8("");
+}
+
+DrmInfoRequest::KeyIterator DrmInfoRequest::keyIterator() const {
+ return KeyIterator(this);
+}
+
+DrmInfoRequest::Iterator DrmInfoRequest::iterator() const {
+ return Iterator(this);
+}
+
+// KeyIterator implementation
+DrmInfoRequest::KeyIterator::KeyIterator(const DrmInfoRequest::KeyIterator& keyIterator)
+ : mDrmInfoRequest(keyIterator.mDrmInfoRequest),
+ mIndex(keyIterator.mIndex) {
+
+}
+
+bool DrmInfoRequest::KeyIterator::hasNext() {
+ return (mIndex < mDrmInfoRequest->mRequestInformationMap.size());
+}
+
+const String8& DrmInfoRequest::KeyIterator::next() {
+ const String8& key = mDrmInfoRequest->mRequestInformationMap.keyAt(mIndex);
+ mIndex++;
+ return key;
+}
+
+DrmInfoRequest::KeyIterator& DrmInfoRequest::KeyIterator::operator=(
+ const DrmInfoRequest::KeyIterator& keyIterator) {
+ mDrmInfoRequest = keyIterator.mDrmInfoRequest;
+ mIndex = keyIterator.mIndex;
+ return *this;
+}
+
+// Iterator implementation
+DrmInfoRequest::Iterator::Iterator(const DrmInfoRequest::Iterator& iterator) :
+ mDrmInfoRequest(iterator.mDrmInfoRequest), mIndex(iterator.mIndex) {
+}
+
+DrmInfoRequest::Iterator& DrmInfoRequest::Iterator::operator=(
+ const DrmInfoRequest::Iterator& iterator) {
+ mDrmInfoRequest = iterator.mDrmInfoRequest;
+ mIndex = iterator.mIndex;
+ return *this;
+}
+
+bool DrmInfoRequest::Iterator::hasNext() {
+ return mIndex < mDrmInfoRequest->mRequestInformationMap.size();
+}
+
+String8& DrmInfoRequest::Iterator::next() {
+ String8& value = mDrmInfoRequest->mRequestInformationMap.editValueAt(mIndex);
+ mIndex++;
+ return value;
+}
+
diff --git a/drm/common/DrmInfoStatus.cpp b/drm/common/DrmInfoStatus.cpp
new file mode 100644
index 0000000..f3a1516
--- /dev/null
+++ b/drm/common/DrmInfoStatus.cpp
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#include <drm/DrmInfoStatus.h>
+
+using namespace android;
+
+DrmInfoStatus::DrmInfoStatus(
+ int _statusCode, const DrmBuffer* _drmBuffer, const String8& _mimeType) :
+ statusCode(_statusCode),
+ drmBuffer(_drmBuffer),
+ mimeType(_mimeType) {
+
+}
+
diff --git a/drm/common/DrmRights.cpp b/drm/common/DrmRights.cpp
new file mode 100644
index 0000000..dc1e6c5
--- /dev/null
+++ b/drm/common/DrmRights.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#include <drm/DrmRights.h>
+
+using namespace android;
+
+DrmRights::DrmRights(const String8& rightsFilePath, const String8& mimeType,
+ const String8& accountId, const String8& subscriptionId) {
+ /**
+ * TODO Read DrmRights from rights file
+ */
+}
+
+DrmRights::DrmRights(const DrmBuffer& rightsData, const String8& mimeType,
+ const String8& accountId, const String8& subscriptionId) :
+ mData(rightsData),
+ mMimeType(mimeType),
+ mAccountId(accountId),
+ mSubscriptionId(subscriptionId) {
+}
+
+const DrmBuffer& DrmRights::getData(void) const {
+ return mData;
+}
+
+String8 DrmRights::getMimeType(void) const {
+ return mMimeType;
+}
+
+String8 DrmRights::getAccountId(void) const {
+ return mAccountId;
+}
+
+String8 DrmRights::getSubscriptionId(void) const {
+ return mSubscriptionId;
+}
+
diff --git a/drm/common/DrmSupportInfo.cpp b/drm/common/DrmSupportInfo.cpp
new file mode 100644
index 0000000..35e83fc
--- /dev/null
+++ b/drm/common/DrmSupportInfo.cpp
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#include <drm/DrmSupportInfo.h>
+
+using namespace android;
+
+DrmSupportInfo::DrmSupportInfo() {
+
+}
+
+DrmSupportInfo::DrmSupportInfo(const DrmSupportInfo& drmSupportInfo):
+ mMimeTypeVector(drmSupportInfo.mMimeTypeVector),
+ mFileSuffixVector(drmSupportInfo.mFileSuffixVector),
+ mDescription(drmSupportInfo.mDescription) {
+
+}
+
+bool DrmSupportInfo::operator<(const DrmSupportInfo& drmSupportInfo) const {
+ // Do we need to check mMimeTypeVector & mFileSuffixVector ?
+ // Note Vector doesn't overrides "<" operator
+ return mDescription < drmSupportInfo.mDescription;
+}
+
+bool DrmSupportInfo::operator==(const DrmSupportInfo& drmSupportInfo) const {
+ // Do we need to check mMimeTypeVector & mFileSuffixVector ?
+ // Note Vector doesn't overrides "==" operator
+ return (mDescription == drmSupportInfo.mDescription);
+}
+
+bool DrmSupportInfo::isSupportedMimeType(const String8& mimeType) const {
+ for (int i = 0; i < mMimeTypeVector.size(); i++) {
+ const String8 item = mMimeTypeVector.itemAt(i);
+
+ if (String8("") != mimeType && item.find(mimeType) != -1) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool DrmSupportInfo::isSupportedFileSuffix(const String8& fileType) const {
+ for (int i = 0; i < mFileSuffixVector.size(); i++) {
+ const String8 item = mFileSuffixVector.itemAt(i);
+
+ if (String8("") != fileType && item.find(fileType) != -1) {
+ return true;
+ }
+ }
+ return false;
+}
+
+DrmSupportInfo& DrmSupportInfo::operator=(const DrmSupportInfo& drmSupportInfo) {
+ mMimeTypeVector = drmSupportInfo.mMimeTypeVector;
+ mFileSuffixVector = drmSupportInfo.mFileSuffixVector;
+ mDescription = drmSupportInfo.mDescription;
+ return *this;
+}
+
+int DrmSupportInfo::getMimeTypeCount(void) const {
+ return mMimeTypeVector.size();
+}
+
+int DrmSupportInfo::getFileSuffixCount(void) const {
+ return mFileSuffixVector.size();
+}
+
+status_t DrmSupportInfo::addMimeType(const String8& mimeType) {
+ mMimeTypeVector.push(mimeType);
+ return DRM_NO_ERROR;
+}
+
+status_t DrmSupportInfo::addFileSuffix(const String8& fileSuffix) {
+ mFileSuffixVector.push(fileSuffix);
+ return DRM_NO_ERROR;
+}
+
+status_t DrmSupportInfo::setDescription(const String8& description) {
+ mDescription = description;
+ return DRM_NO_ERROR;
+}
+
+String8 DrmSupportInfo::getDescription() const {
+ return mDescription;
+}
+
+DrmSupportInfo::FileSuffixIterator DrmSupportInfo::getFileSuffixIterator() {
+ return FileSuffixIterator(this);
+}
+
+DrmSupportInfo::MimeTypeIterator DrmSupportInfo::getMimeTypeIterator() {
+ return MimeTypeIterator(this);
+}
+
+DrmSupportInfo::FileSuffixIterator::FileSuffixIterator(
+ const DrmSupportInfo::FileSuffixIterator& iterator) :
+ mDrmSupportInfo(iterator.mDrmSupportInfo),
+ mIndex(iterator.mIndex) {
+
+}
+
+DrmSupportInfo::FileSuffixIterator& DrmSupportInfo::FileSuffixIterator::operator=(
+ const DrmSupportInfo::FileSuffixIterator& iterator) {
+ mDrmSupportInfo = iterator.mDrmSupportInfo;
+ mIndex = iterator.mIndex;
+ return *this;
+}
+
+bool DrmSupportInfo::FileSuffixIterator::hasNext() {
+ return mIndex < mDrmSupportInfo->mFileSuffixVector.size();
+}
+
+String8& DrmSupportInfo::FileSuffixIterator::next() {
+ String8& value = mDrmSupportInfo->mFileSuffixVector.editItemAt(mIndex);
+ mIndex++;
+ return value;
+}
+
+DrmSupportInfo::MimeTypeIterator::MimeTypeIterator(
+ const DrmSupportInfo::MimeTypeIterator& iterator) :
+ mDrmSupportInfo(iterator.mDrmSupportInfo),
+ mIndex(iterator.mIndex) {
+
+}
+
+DrmSupportInfo::MimeTypeIterator& DrmSupportInfo::MimeTypeIterator::operator=(
+ const DrmSupportInfo::MimeTypeIterator& iterator) {
+ mDrmSupportInfo = iterator.mDrmSupportInfo;
+ mIndex = iterator.mIndex;
+ return *this;
+}
+
+bool DrmSupportInfo::MimeTypeIterator::hasNext() {
+ return mIndex < mDrmSupportInfo->mMimeTypeVector.size();
+}
+
+String8& DrmSupportInfo::MimeTypeIterator::next() {
+ String8& value = mDrmSupportInfo->mMimeTypeVector.editItemAt(mIndex);
+ mIndex++;
+ return value;
+}
+
diff --git a/drm/common/IDrmIOService.cpp b/drm/common/IDrmIOService.cpp
new file mode 100644
index 0000000..7ce45e7
--- /dev/null
+++ b/drm/common/IDrmIOService.cpp
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2010 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 "IDrmIOService"
+#include <utils/Log.h>
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <binder/Parcel.h>
+#include <binder/IPCThreadState.h>
+#include <drm/drm_framework_common.h>
+#include "IDrmIOService.h"
+
+using namespace android;
+
+void BpDrmIOService::writeToFile(const String8& filePath, const String8& dataBuffer) {
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmIOService::getInterfaceDescriptor());
+ data.writeString8(filePath);
+ data.writeString8(dataBuffer);
+
+ remote()->transact(WRITE_TO_FILE, data, &reply);
+}
+
+String8 BpDrmIOService::readFromFile(const String8& filePath) {
+
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmIOService::getInterfaceDescriptor());
+ data.writeString8(filePath);
+
+ remote()->transact(READ_FROM_FILE, data, &reply);
+ return reply.readString8();
+}
+
+IMPLEMENT_META_INTERFACE(DrmIOService, "drm.IDrmIOService");
+
+status_t BnDrmIOService::onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
+
+ switch (code) {
+ case WRITE_TO_FILE:
+ {
+ CHECK_INTERFACE(IDrmIOService, data, reply);
+
+ writeToFile(data.readString8(), data.readString8());
+ return DRM_NO_ERROR;
+ }
+
+ case READ_FROM_FILE:
+ {
+ CHECK_INTERFACE(IDrmIOService, data, reply);
+
+ String8 dataBuffer = readFromFile(data.readString8());
+ reply->writeString8(dataBuffer);
+ return DRM_NO_ERROR;
+ }
+
+ default:
+ return BBinder::onTransact(code, data, reply, flags);
+ }
+}
+
diff --git a/drm/common/IDrmManagerService.cpp b/drm/common/IDrmManagerService.cpp
new file mode 100644
index 0000000..4fc828a
--- /dev/null
+++ b/drm/common/IDrmManagerService.cpp
@@ -0,0 +1,1358 @@
+/*
+ * Copyright (C) 2010 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 "IDrmManagerService(Native)"
+#include <utils/Log.h>
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <binder/IPCThreadState.h>
+
+#include <drm/DrmInfo.h>
+#include <drm/DrmConstraints.h>
+#include <drm/DrmRights.h>
+#include <drm/DrmInfoStatus.h>
+#include <drm/DrmConvertedStatus.h>
+#include <drm/DrmInfoRequest.h>
+#include <drm/DrmSupportInfo.h>
+
+#include "IDrmManagerService.h"
+
+#define INVALID_BUFFER_LENGTH -1
+
+using namespace android;
+
+status_t BpDrmManagerService::loadPlugIns(int uniqueId) {
+ LOGV("load plugins");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+
+ remote()->transact(LOAD_PLUGINS, data, &reply);
+ return reply.readInt32();
+}
+
+status_t BpDrmManagerService::loadPlugIns(int uniqueId, const String8& plugInDirPath) {
+ LOGV("load plugins from path");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+ data.writeString8(plugInDirPath);
+
+ remote()->transact(LOAD_PLUGINS_FROM_PATH, data, &reply);
+ return reply.readInt32();
+}
+
+status_t BpDrmManagerService::setDrmServiceListener(
+ int uniqueId, const sp<IDrmServiceListener>& drmServiceListener) {
+ LOGV("setDrmServiceListener");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+ data.writeStrongBinder(drmServiceListener->asBinder());
+ remote()->transact(SET_DRM_SERVICE_LISTENER, data, &reply);
+ return reply.readInt32();
+}
+
+status_t BpDrmManagerService::unloadPlugIns(int uniqueId) {
+ LOGV("unload plugins");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+
+ remote()->transact(UNLOAD_PLUGINS, data, &reply);
+ return reply.readInt32();
+}
+
+status_t BpDrmManagerService::installDrmEngine(int uniqueId, const String8& drmEngineFile) {
+ LOGV("Install DRM Engine");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+ data.writeString8(drmEngineFile);
+
+ remote()->transact(INSTALL_DRM_ENGINE, data, &reply);
+ return reply.readInt32();
+}
+
+DrmConstraints* BpDrmManagerService::getConstraints(
+ int uniqueId, const String8* path, const int action) {
+ LOGV("Get Constraints");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+ data.writeString8(*path);
+ data.writeInt32(action);
+
+ remote()->transact(GET_CONSTRAINTS_FROM_CONTENT, data, &reply);
+
+ DrmConstraints* drmConstraints = NULL;
+ if (0 != reply.dataAvail()) {
+ //Filling Drm Constraints
+ drmConstraints = new DrmConstraints();
+
+ const int size = reply.readInt32();
+ for (int index = 0; index < size; ++index) {
+ const String8 key(reply.readString8());
+ const int bufferSize = reply.readInt32();
+ char* data = NULL;
+ if (0 < bufferSize) {
+ data = new char[bufferSize];
+ reply.read(data, bufferSize);
+ }
+ drmConstraints->put(&key, data);
+ }
+ }
+ return drmConstraints;
+}
+
+bool BpDrmManagerService::canHandle(int uniqueId, const String8& path, const String8& mimeType) {
+ LOGV("Can Handle");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+
+ data.writeString8(path);
+ data.writeString8(mimeType);
+
+ remote()->transact(CAN_HANDLE, data, &reply);
+
+ return static_cast<bool>(reply.readInt32());
+}
+
+DrmInfoStatus* BpDrmManagerService::processDrmInfo(int uniqueId, const DrmInfo* drmInfo) {
+ LOGV("Process DRM Info");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+
+ //Filling DRM info
+ data.writeInt32(drmInfo->getInfoType());
+ const DrmBuffer dataBuffer = drmInfo->getData();
+ const int dataBufferSize = dataBuffer.length;
+ data.writeInt32(dataBufferSize);
+ if (0 < dataBufferSize) {
+ data.write(dataBuffer.data, dataBufferSize);
+ }
+ data.writeString8(drmInfo->getMimeType());
+
+ data.writeInt32(drmInfo->getCount());
+ DrmInfo::KeyIterator keyIt = drmInfo->keyIterator();
+
+ while (keyIt.hasNext()) {
+ const String8 key = keyIt.next();
+ data.writeString8(key);
+ const String8 value = drmInfo->get(key);
+ data.writeString8((value == String8("")) ? String8("NULL") : value);
+ }
+
+ remote()->transact(PROCESS_DRM_INFO, data, &reply);
+
+ DrmInfoStatus* drmInfoStatus = NULL;
+ if (0 != reply.dataAvail()) {
+ //Filling DRM Info Status
+ const int statusCode = reply.readInt32();
+ const String8 mimeType = reply.readString8();
+
+ DrmBuffer* drmBuffer = NULL;
+ if (0 != reply.dataAvail()) {
+ const int bufferSize = reply.readInt32();
+ char* data = NULL;
+ if (0 < bufferSize) {
+ data = new char[bufferSize];
+ reply.read(data, bufferSize);
+ }
+ drmBuffer = new DrmBuffer(data, bufferSize);
+ }
+ drmInfoStatus = new DrmInfoStatus(statusCode, drmBuffer, mimeType);
+ }
+ return drmInfoStatus;
+}
+
+DrmInfo* BpDrmManagerService::acquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInforequest) {
+ LOGV("Acquire DRM Info");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+
+ //Filling DRM Info Request
+ data.writeInt32(drmInforequest->getInfoType());
+ data.writeString8(drmInforequest->getMimeType());
+
+ data.writeInt32(drmInforequest->getCount());
+ DrmInfoRequest::KeyIterator keyIt = drmInforequest->keyIterator();
+
+ while (keyIt.hasNext()) {
+ const String8 key = keyIt.next();
+ data.writeString8(key);
+ const String8 value = drmInforequest->get(key);
+ data.writeString8((value == String8("")) ? String8("NULL") : value);
+ }
+
+ remote()->transact(ACQUIRE_DRM_INFO, data, &reply);
+
+ DrmInfo* drmInfo = NULL;
+ if (0 != reply.dataAvail()) {
+ //Filling DRM Info
+ const int infoType = reply.readInt32();
+ const int bufferSize = reply.readInt32();
+ char* data = NULL;
+
+ if (0 < bufferSize) {
+ data = new char[bufferSize];
+ reply.read(data, bufferSize);
+ }
+ drmInfo = new DrmInfo(infoType, DrmBuffer(data, bufferSize), reply.readString8());
+
+ const int size = reply.readInt32();
+ for (int index = 0; index < size; ++index) {
+ const String8 key(reply.readString8());
+ const String8 value(reply.readString8());
+ drmInfo->put(key, (value == String8("NULL")) ? String8("") : value);
+ }
+ }
+ return drmInfo;
+}
+
+void BpDrmManagerService::saveRights(
+ int uniqueId, const DrmRights& drmRights,
+ const String8& rightsPath, const String8& contentPath) {
+ LOGV("Save Rights");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+
+ //Filling Drm Rights
+ const DrmBuffer dataBuffer = drmRights.getData();
+ data.writeInt32(dataBuffer.length);
+ data.write(dataBuffer.data, dataBuffer.length);
+
+ const String8 mimeType = drmRights.getMimeType();
+ data.writeString8((mimeType == String8("")) ? String8("NULL") : mimeType);
+
+ const String8 accountId = drmRights.getAccountId();
+ data.writeString8((accountId == String8("")) ? String8("NULL") : accountId);
+
+ const String8 subscriptionId = drmRights.getSubscriptionId();
+ data.writeString8((subscriptionId == String8("")) ? String8("NULL") : subscriptionId);
+
+ data.writeString8((rightsPath == String8("")) ? String8("NULL") : rightsPath);
+ data.writeString8((contentPath == String8("")) ? String8("NULL") : contentPath);
+
+ remote()->transact(SAVE_RIGHTS, data, &reply);
+}
+
+String8 BpDrmManagerService::getOriginalMimeType(int uniqueId, const String8& path) {
+ LOGV("Get Original MimeType");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+ data.writeString8(path);
+
+ remote()->transact(GET_ORIGINAL_MIMETYPE, data, &reply);
+ return reply.readString8();
+}
+
+int BpDrmManagerService::getDrmObjectType(
+ int uniqueId, const String8& path, const String8& mimeType) {
+ LOGV("Get Drm object type");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+ data.writeString8(path);
+ data.writeString8(mimeType);
+
+ remote()->transact(GET_DRM_OBJECT_TYPE, data, &reply);
+
+ return reply.readInt32();
+}
+
+int BpDrmManagerService::checkRightsStatus(int uniqueId, const String8& path, int action) {
+ LOGV("checkRightsStatus");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+ data.writeString8(path);
+ data.writeInt32(action);
+
+ remote()->transact(CHECK_RIGHTS_STATUS, data, &reply);
+
+ return reply.readInt32();
+}
+
+void BpDrmManagerService::consumeRights(
+ int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve) {
+ LOGV("consumeRights");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+
+ data.writeInt32(decryptHandle->decryptId);
+ data.writeString8(decryptHandle->mimeType);
+ data.writeInt32(decryptHandle->decryptApiType);
+ data.writeInt32(decryptHandle->status);
+
+ if (NULL != decryptHandle->decryptInfo) {
+ data.writeInt32(decryptHandle->decryptInfo->decryptBufferLength);
+ } else {
+ data.writeInt32(INVALID_BUFFER_LENGTH);
+ }
+
+ data.writeInt32(action);
+ data.writeInt32(static_cast< int>(reserve));
+
+ remote()->transact(CONSUME_RIGHTS, data, &reply);
+}
+
+void BpDrmManagerService::setPlaybackStatus(
+ int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int position) {
+ LOGV("setPlaybackStatus");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+
+ data.writeInt32(decryptHandle->decryptId);
+ data.writeString8(decryptHandle->mimeType);
+ data.writeInt32(decryptHandle->decryptApiType);
+ data.writeInt32(decryptHandle->status);
+
+ if (NULL != decryptHandle->decryptInfo) {
+ data.writeInt32(decryptHandle->decryptInfo->decryptBufferLength);
+ } else {
+ data.writeInt32(INVALID_BUFFER_LENGTH);
+ }
+
+ data.writeInt32(playbackStatus);
+ data.writeInt32(position);
+
+ remote()->transact(SET_PLAYBACK_STATUS, data, &reply);
+}
+
+bool BpDrmManagerService::validateAction(
+ int uniqueId, const String8& path,
+ int action, const ActionDescription& description) {
+ LOGV("validateAction");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+ data.writeString8(path);
+ data.writeInt32(action);
+ data.writeInt32(description.outputType);
+ data.writeInt32(description.configuration);
+
+ remote()->transact(VALIDATE_ACTION, data, &reply);
+
+ return static_cast<bool>(reply.readInt32());
+}
+
+void BpDrmManagerService::removeRights(int uniqueId, const String8& path) {
+ LOGV("removeRights");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+ data.writeString8(path);
+
+ remote()->transact(REMOVE_RIGHTS, data, &reply);
+}
+
+void BpDrmManagerService::removeAllRights(int uniqueId) {
+ LOGV("removeAllRights");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+
+ remote()->transact(REMOVE_ALL_RIGHTS, data, &reply);
+}
+
+int BpDrmManagerService::openConvertSession(int uniqueId, const String8& mimeType) {
+ LOGV("openConvertSession");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+ data.writeString8(mimeType);
+
+ remote()->transact(OPEN_CONVERT_SESSION, data, &reply);
+ return reply.readInt32();
+}
+
+DrmConvertedStatus* BpDrmManagerService::convertData(
+ int uniqueId, int convertId, const DrmBuffer* inputData) {
+ LOGV("convertData");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+ data.writeInt32(convertId);
+ data.writeInt32(inputData->length);
+ data.write(inputData->data, inputData->length);
+
+ remote()->transact(CONVERT_DATA, data, &reply);
+
+ DrmConvertedStatus* drmConvertedStatus = NULL;
+
+ if (0 != reply.dataAvail()) {
+ //Filling DRM Converted Status
+ const int statusCode = reply.readInt32();
+ const int offset = reply.readInt32();
+
+ DrmBuffer* convertedData = NULL;
+ if (0 != reply.dataAvail()) {
+ const int bufferSize = reply.readInt32();
+ char* data = NULL;
+ if (0 < bufferSize) {
+ data = new char[bufferSize];
+ reply.read(data, bufferSize);
+ }
+ convertedData = new DrmBuffer(data, bufferSize);
+ }
+ drmConvertedStatus = new DrmConvertedStatus(statusCode, convertedData, offset);
+ }
+ return drmConvertedStatus;
+}
+
+DrmConvertedStatus* BpDrmManagerService::closeConvertSession(int uniqueId, int convertId) {
+ LOGV("closeConvertSession");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+ data.writeInt32(convertId);
+
+ remote()->transact(CLOSE_CONVERT_SESSION, data, &reply);
+
+ DrmConvertedStatus* drmConvertedStatus = NULL;
+
+ if (0 != reply.dataAvail()) {
+ //Filling DRM Converted Status
+ const int statusCode = reply.readInt32();
+ const int offset = reply.readInt32();
+
+ DrmBuffer* convertedData = NULL;
+ if (0 != reply.dataAvail()) {
+ const int bufferSize = reply.readInt32();
+ char* data = NULL;
+ if (0 < bufferSize) {
+ data = new char[bufferSize];
+ reply.read(data, bufferSize);
+ }
+ convertedData = new DrmBuffer(data, bufferSize);
+ }
+ drmConvertedStatus = new DrmConvertedStatus(statusCode, convertedData, offset);
+ }
+ return drmConvertedStatus;
+}
+
+status_t BpDrmManagerService::getAllSupportInfo(
+ int uniqueId, int* length, DrmSupportInfo** drmSupportInfoArray) {
+ LOGV("Get All Support Info");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+
+ remote()->transact(GET_ALL_SUPPORT_INFO, data, &reply);
+
+ //Filling DRM Support Info
+ const int arraySize = reply.readInt32();
+ if (0 < arraySize) {
+ *drmSupportInfoArray = new DrmSupportInfo[arraySize];
+
+ for (int index = 0; index < arraySize; ++index) {
+ DrmSupportInfo drmSupportInfo;
+
+ const int fileSuffixVectorSize = reply.readInt32();
+ for (int i = 0; i < fileSuffixVectorSize; ++i) {
+ drmSupportInfo.addFileSuffix(reply.readString8());
+ }
+
+ const int mimeTypeVectorSize = reply.readInt32();
+ for (int i = 0; i < mimeTypeVectorSize; ++i) {
+ drmSupportInfo.addMimeType(reply.readString8());
+ }
+
+ drmSupportInfo.setDescription(reply.readString8());
+ (*drmSupportInfoArray)[index] = drmSupportInfo;
+ }
+ }
+ *length = arraySize;
+ return reply.readInt32();
+}
+
+DecryptHandle* BpDrmManagerService::openDecryptSession(
+ int uniqueId, int fd, int offset, int length) {
+ LOGV("Entering BpDrmManagerService::openDecryptSession");
+ Parcel data, reply;
+
+ const String16 interfaceDescriptor = IDrmManagerService::getInterfaceDescriptor();
+ LOGV("BpDrmManagerService::openDecryptSession: InterfaceDescriptor name is %s",
+ interfaceDescriptor.string());
+ data.writeInterfaceToken(interfaceDescriptor);
+ data.writeInt32(uniqueId);
+ data.writeFileDescriptor(fd);
+ data.writeInt32(offset);
+ data.writeInt32(length);
+
+ LOGV("try to invoke remote onTransact() with code OPEN_DECRYPT_SESSION");
+ remote()->transact(OPEN_DECRYPT_SESSION, data, &reply);
+
+ DecryptHandle* handle = NULL;
+ if (0 != reply.dataAvail()) {
+ handle = new DecryptHandle();
+ handle->decryptId = reply.readInt32();
+ handle->mimeType = reply.readString8();
+ handle->decryptApiType = reply.readInt32();
+ handle->status = reply.readInt32();
+ handle->decryptInfo = NULL;
+ if (0 != reply.dataAvail()) {
+ handle->decryptInfo = new DecryptInfo();
+ handle->decryptInfo->decryptBufferLength = reply.readInt32();
+ }
+ } else {
+ LOGE("no decryptHandle is generated in service side");
+ }
+ return handle;
+}
+
+void BpDrmManagerService::closeDecryptSession(int uniqueId, DecryptHandle* decryptHandle) {
+ LOGV("closeDecryptSession");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+
+ data.writeInt32(decryptHandle->decryptId);
+ data.writeString8(decryptHandle->mimeType);
+ data.writeInt32(decryptHandle->decryptApiType);
+ data.writeInt32(decryptHandle->status);
+
+ if (NULL != decryptHandle->decryptInfo) {
+ data.writeInt32(decryptHandle->decryptInfo->decryptBufferLength);
+ } else {
+ data.writeInt32(INVALID_BUFFER_LENGTH);
+ }
+
+ remote()->transact(CLOSE_DECRYPT_SESSION, data, &reply);
+
+ if (NULL != decryptHandle->decryptInfo) {
+ LOGV("deleting decryptInfo");
+ delete decryptHandle->decryptInfo; decryptHandle->decryptInfo = NULL;
+ }
+ delete decryptHandle; decryptHandle = NULL;
+}
+
+void BpDrmManagerService::initializeDecryptUnit(
+ int uniqueId, DecryptHandle* decryptHandle,
+ int decryptUnitId, const DrmBuffer* headerInfo) {
+ LOGV("initializeDecryptUnit");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+
+ data.writeInt32(decryptHandle->decryptId);
+ data.writeString8(decryptHandle->mimeType);
+ data.writeInt32(decryptHandle->decryptApiType);
+ data.writeInt32(decryptHandle->status);
+
+ if (NULL != decryptHandle->decryptInfo) {
+ data.writeInt32(decryptHandle->decryptInfo->decryptBufferLength);
+ } else {
+ data.writeInt32(INVALID_BUFFER_LENGTH);
+ }
+ data.writeInt32(decryptUnitId);
+
+ data.writeInt32(headerInfo->length);
+ data.write(headerInfo->data, headerInfo->length);
+
+ remote()->transact(INITIALIZE_DECRYPT_UNIT, data, &reply);
+}
+
+status_t BpDrmManagerService::decrypt(
+ int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId,
+ const DrmBuffer* encBuffer, DrmBuffer** decBuffer) {
+ LOGV("decrypt");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+
+ data.writeInt32(decryptHandle->decryptId);
+ data.writeString8(decryptHandle->mimeType);
+ data.writeInt32(decryptHandle->decryptApiType);
+ data.writeInt32(decryptHandle->status);
+
+ if (NULL != decryptHandle->decryptInfo) {
+ data.writeInt32(decryptHandle->decryptInfo->decryptBufferLength);
+ } else {
+ data.writeInt32(INVALID_BUFFER_LENGTH);
+ }
+
+ data.writeInt32(decryptUnitId);
+ data.writeInt32((*decBuffer)->length);
+
+ data.writeInt32(encBuffer->length);
+ data.write(encBuffer->data, encBuffer->length);
+
+ remote()->transact(DECRYPT, data, &reply);
+
+ const status_t status = reply.readInt32();
+ LOGV("Return value of decrypt() is %d", status);
+
+ const int size = reply.readInt32();
+ (*decBuffer)->length = size;
+ reply.read((void *)(*decBuffer)->data, size);
+
+ return status;
+}
+
+void BpDrmManagerService::finalizeDecryptUnit(
+ int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId) {
+ LOGV("finalizeDecryptUnit");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+
+ data.writeInt32(decryptHandle->decryptId);
+ data.writeString8(decryptHandle->mimeType);
+ data.writeInt32(decryptHandle->decryptApiType);
+ data.writeInt32(decryptHandle->status);
+
+ if (NULL != decryptHandle->decryptInfo) {
+ data.writeInt32(decryptHandle->decryptInfo->decryptBufferLength);
+ } else {
+ data.writeInt32(INVALID_BUFFER_LENGTH);
+ }
+
+ data.writeInt32(decryptUnitId);
+
+ remote()->transact(FINALIZE_DECRYPT_UNIT, data, &reply);
+}
+
+ssize_t BpDrmManagerService::pread(
+ int uniqueId, DecryptHandle* decryptHandle, void* buffer,
+ ssize_t numBytes, off_t offset) {
+ LOGV("read");
+ Parcel data, reply;
+ int result;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+
+ data.writeInt32(decryptHandle->decryptId);
+ data.writeString8(decryptHandle->mimeType);
+ data.writeInt32(decryptHandle->decryptApiType);
+ data.writeInt32(decryptHandle->status);
+
+ if (NULL != decryptHandle->decryptInfo) {
+ data.writeInt32(decryptHandle->decryptInfo->decryptBufferLength);
+ } else {
+ data.writeInt32(INVALID_BUFFER_LENGTH);
+ }
+
+ data.writeInt32(numBytes);
+ data.writeInt32(offset);
+
+ remote()->transact(PREAD, data, &reply);
+ result = reply.readInt32();
+ if (0 < result) {
+ reply.read(buffer, result);
+ }
+ return result;
+}
+
+IMPLEMENT_META_INTERFACE(DrmManagerService, "drm.IDrmManagerService");
+
+status_t BnDrmManagerService::onTransact(
+ uint32_t code, const Parcel& data,
+ Parcel* reply, uint32_t flags) {
+ LOGV("Entering BnDrmManagerService::onTransact with code %d", code);
+
+ switch (code) {
+ case LOAD_PLUGINS:
+ {
+ LOGV("BnDrmManagerService::onTransact :LOAD_PLUGINS");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ status_t status = loadPlugIns(data.readInt32());
+
+ reply->writeInt32(status);
+ return DRM_NO_ERROR;
+
+ }
+
+ case LOAD_PLUGINS_FROM_PATH:
+ {
+ LOGV("BnDrmManagerService::onTransact :LOAD_PLUGINS_FROM_PATH");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ status_t status = loadPlugIns(data.readInt32(), data.readString8());
+
+ reply->writeInt32(status);
+ return DRM_NO_ERROR;
+ }
+
+ case SET_DRM_SERVICE_LISTENER:
+ {
+ LOGV("BnDrmManagerService::onTransact :SET_DRM_SERVICE_LISTENER");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ const int uniqueId = data.readInt32();
+ const sp<IDrmServiceListener> drmServiceListener
+ = interface_cast<IDrmServiceListener> (data.readStrongBinder());
+
+ status_t status = setDrmServiceListener(uniqueId, drmServiceListener);
+
+ reply->writeInt32(status);
+ return DRM_NO_ERROR;
+ }
+
+ case UNLOAD_PLUGINS:
+ {
+ LOGV("BnDrmManagerService::onTransact :UNLOAD_PLUGINS");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ status_t status = unloadPlugIns(data.readInt32());
+
+ reply->writeInt32(status);
+ return DRM_NO_ERROR;
+ }
+
+ case INSTALL_DRM_ENGINE:
+ {
+ LOGV("BnDrmManagerService::onTransact :INSTALL_DRM_ENGINE");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ status_t status = installDrmEngine(data.readInt32(), data.readString8());
+
+ reply->writeInt32(status);
+ return DRM_NO_ERROR;
+ }
+
+ case GET_CONSTRAINTS_FROM_CONTENT:
+ {
+ LOGV("BnDrmManagerService::onTransact :GET_CONSTRAINTS_FROM_CONTENT");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ const int uniqueId = data.readInt32();
+ const String8 path = data.readString8();
+
+ DrmConstraints* drmConstraints = getConstraints(uniqueId, &path, data.readInt32());
+
+ if (NULL != drmConstraints) {
+ //Filling DRM Constraints contents
+ reply->writeInt32(drmConstraints->getCount());
+
+ DrmConstraints::KeyIterator keyIt = drmConstraints->keyIterator();
+ while (keyIt.hasNext()) {
+ const String8 key = keyIt.next();
+ reply->writeString8(key);
+ const char* value = drmConstraints->getAsByteArray(&key);
+ int bufferSize = 0;
+ if (NULL != value) {
+ bufferSize = strlen(value);
+ }
+ reply->writeInt32(bufferSize + 1);
+ reply->write(value, bufferSize + 1);
+ }
+ }
+ delete drmConstraints; drmConstraints = NULL;
+ return DRM_NO_ERROR;
+ }
+
+ case CAN_HANDLE:
+ {
+ LOGV("BnDrmManagerService::onTransact :CAN_HANDLE");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ const int uniqueId = data.readInt32();
+ const String8 path = data.readString8();
+ const String8 mimeType = data.readString8();
+
+ bool result = canHandle(uniqueId, path, mimeType);
+
+ reply->writeInt32(result);
+ return DRM_NO_ERROR;
+ }
+
+ case PROCESS_DRM_INFO:
+ {
+ LOGV("BnDrmManagerService::onTransact :PROCESS_DRM_INFO");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ const int uniqueId = data.readInt32();
+
+ //Filling DRM info
+ const int infoType = data.readInt32();
+ const int bufferSize = data.readInt32();
+ char* buffer = NULL;
+ if (0 < bufferSize) {
+ buffer = (char *)data.readInplace(bufferSize);
+ }
+ const DrmBuffer drmBuffer(buffer, bufferSize);
+ DrmInfo* drmInfo = new DrmInfo(infoType, drmBuffer, data.readString8());
+
+ const int size = data.readInt32();
+ for (int index = 0; index < size; ++index) {
+ const String8 key(data.readString8());
+ const String8 value(data.readString8());
+ drmInfo->put(key, (value == String8("NULL")) ? String8("") : value);
+ }
+
+ DrmInfoStatus* drmInfoStatus = processDrmInfo(uniqueId, drmInfo);
+
+ if (NULL != drmInfoStatus) {
+ //Filling DRM Info Status contents
+ reply->writeInt32(drmInfoStatus->statusCode);
+ reply->writeString8(drmInfoStatus->mimeType);
+
+ if (NULL != drmInfoStatus->drmBuffer) {
+ const DrmBuffer* drmBuffer = drmInfoStatus->drmBuffer;
+ const int bufferSize = drmBuffer->length;
+ reply->writeInt32(bufferSize);
+ if (0 < bufferSize) {
+ reply->write(drmBuffer->data, bufferSize);
+ }
+ delete [] drmBuffer->data;
+ delete drmBuffer; drmBuffer = NULL;
+ }
+ }
+ delete drmInfo; drmInfo = NULL;
+ delete drmInfoStatus; drmInfoStatus = NULL;
+ return DRM_NO_ERROR;
+ }
+
+ case ACQUIRE_DRM_INFO:
+ {
+ LOGV("BnDrmManagerService::onTransact :ACQUIRE_DRM_INFO");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ const int uniqueId = data.readInt32();
+
+ //Filling DRM info Request
+ DrmInfoRequest* drmInfoRequest = new DrmInfoRequest(data.readInt32(), data.readString8());
+
+ const int size = data.readInt32();
+ for (int index = 0; index < size; ++index) {
+ const String8 key(data.readString8());
+ const String8 value(data.readString8());
+ drmInfoRequest->put(key, (value == String8("NULL")) ? String8("") : value);
+ }
+
+ DrmInfo* drmInfo = acquireDrmInfo(uniqueId, drmInfoRequest);
+
+ if (NULL != drmInfo) {
+ //Filling DRM Info
+ const DrmBuffer drmBuffer = drmInfo->getData();
+ reply->writeInt32(drmInfo->getInfoType());
+
+ const int bufferSize = drmBuffer.length;
+ reply->writeInt32(bufferSize);
+ if (0 < bufferSize) {
+ reply->write(drmBuffer.data, bufferSize);
+ }
+ reply->writeString8(drmInfo->getMimeType());
+ reply->writeInt32(drmInfo->getCount());
+
+ DrmInfo::KeyIterator keyIt = drmInfo->keyIterator();
+ while (keyIt.hasNext()) {
+ const String8 key = keyIt.next();
+ reply->writeString8(key);
+ const String8 value = drmInfo->get(key);
+ reply->writeString8((value == String8("")) ? String8("NULL") : value);
+ }
+ delete [] drmBuffer.data;
+ }
+ delete drmInfoRequest; drmInfoRequest = NULL;
+ delete drmInfo; drmInfo = NULL;
+ return DRM_NO_ERROR;
+ }
+
+ case SAVE_RIGHTS:
+ {
+ LOGV("BnDrmManagerService::onTransact :SAVE_RIGHTS");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ const int uniqueId = data.readInt32();
+
+ //Filling DRM Rights
+ const int bufferSize = data.readInt32();
+ const DrmBuffer drmBuffer((char *)data.readInplace(bufferSize), bufferSize);
+
+ const String8 mimeType(data.readString8());
+ const String8 accountId(data.readString8());
+ const String8 subscriptionId(data.readString8());
+ const String8 rightsPath(data.readString8());
+ const String8 contentPath(data.readString8());
+
+ DrmRights drmRights(drmBuffer,
+ ((mimeType == String8("NULL")) ? String8("") : mimeType),
+ ((accountId == String8("NULL")) ? String8("") : accountId),
+ ((subscriptionId == String8("NULL")) ? String8("") : subscriptionId));
+
+ saveRights(uniqueId, drmRights,
+ ((rightsPath == String8("NULL")) ? String8("") : rightsPath),
+ ((contentPath == String8("NULL")) ? String8("") : contentPath));
+
+ return DRM_NO_ERROR;
+ }
+
+ case GET_ORIGINAL_MIMETYPE:
+ {
+ LOGV("BnDrmManagerService::onTransact :GET_ORIGINAL_MIMETYPE");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ const String8 originalMimeType = getOriginalMimeType(data.readInt32(), data.readString8());
+
+ reply->writeString8(originalMimeType);
+ return DRM_NO_ERROR;
+ }
+
+ case GET_DRM_OBJECT_TYPE:
+ {
+ LOGV("BnDrmManagerService::onTransact :GET_DRM_OBJECT_TYPE");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ const int drmObjectType
+ = getDrmObjectType(data.readInt32(), data.readString8(), data.readString8());
+
+ reply->writeInt32(drmObjectType);
+ return DRM_NO_ERROR;
+ }
+
+ case CHECK_RIGHTS_STATUS:
+ {
+ LOGV("BnDrmManagerService::onTransact :CHECK_RIGHTS_STATUS");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ const int result
+ = checkRightsStatus(data.readInt32(), data.readString8(), data.readInt32());
+
+ reply->writeInt32(result);
+ return DRM_NO_ERROR;
+ }
+
+ case CONSUME_RIGHTS:
+ {
+ LOGV("BnDrmManagerService::onTransact :CONSUME_RIGHTS");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ const int uniqueId = data.readInt32();
+
+ DecryptHandle handle;
+ handle.decryptId = data.readInt32();
+ handle.mimeType = data.readString8();
+ handle.decryptApiType = data.readInt32();
+ handle.status = data.readInt32();
+ handle.decryptInfo = NULL;
+
+ const int bufferLength = data.readInt32();
+ if (INVALID_BUFFER_LENGTH != bufferLength) {
+ handle.decryptInfo = new DecryptInfo();
+ handle.decryptInfo->decryptBufferLength = bufferLength;
+ }
+
+ consumeRights(uniqueId, &handle, data.readInt32(), static_cast<bool>(data.readInt32()));
+
+ delete handle.decryptInfo; handle.decryptInfo = NULL;
+ return DRM_NO_ERROR;
+ }
+
+ case SET_PLAYBACK_STATUS:
+ {
+ LOGV("BnDrmManagerService::onTransact :SET_PLAYBACK_STATUS");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ const int uniqueId = data.readInt32();
+
+ DecryptHandle handle;
+ handle.decryptId = data.readInt32();
+ handle.mimeType = data.readString8();
+ handle.decryptApiType = data.readInt32();
+ handle.status = data.readInt32();
+ handle.decryptInfo = NULL;
+
+ const int bufferLength = data.readInt32();
+ if (INVALID_BUFFER_LENGTH != bufferLength) {
+ handle.decryptInfo = new DecryptInfo();
+ handle.decryptInfo->decryptBufferLength = bufferLength;
+ }
+
+ setPlaybackStatus(uniqueId, &handle, data.readInt32(), data.readInt32());
+
+ delete handle.decryptInfo; handle.decryptInfo = NULL;
+ return DRM_NO_ERROR;
+ }
+
+ case VALIDATE_ACTION:
+ {
+ LOGV("BnDrmManagerService::onTransact :VALIDATE_ACTION");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ bool result = validateAction(
+ data.readInt32(),
+ data.readString8(),
+ data.readInt32(),
+ ActionDescription(data.readInt32(), data.readInt32()));
+
+ reply->writeInt32(result);
+ return DRM_NO_ERROR;
+ }
+
+ case REMOVE_RIGHTS:
+ {
+ LOGV("BnDrmManagerService::onTransact :REMOVE_RIGHTS");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ removeRights(data.readInt32(), data.readString8());
+
+ return DRM_NO_ERROR;
+ }
+
+ case REMOVE_ALL_RIGHTS:
+ {
+ LOGV("BnDrmManagerService::onTransact :REMOVE_ALL_RIGHTS");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ removeAllRights(data.readInt32());
+
+ return DRM_NO_ERROR;
+ }
+
+ case OPEN_CONVERT_SESSION:
+ {
+ LOGV("BnDrmManagerService::onTransact :OPEN_CONVERT_SESSION");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ const int convertId = openConvertSession(data.readInt32(), data.readString8());
+
+ reply->writeInt32(convertId);
+ return DRM_NO_ERROR;
+ }
+
+ case CONVERT_DATA:
+ {
+ LOGV("BnDrmManagerService::onTransact :CONVERT_DATA");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ const int uniqueId = data.readInt32();
+ const int convertId = data.readInt32();
+
+ //Filling input data
+ const int bufferSize = data.readInt32();
+ DrmBuffer* inputData = new DrmBuffer((char *)data.readInplace(bufferSize), bufferSize);
+
+ DrmConvertedStatus* drmConvertedStatus = convertData(uniqueId, convertId, inputData);
+
+ if (NULL != drmConvertedStatus) {
+ //Filling Drm Converted Ststus
+ reply->writeInt32(drmConvertedStatus->statusCode);
+ reply->writeInt32(drmConvertedStatus->offset);
+
+ if (NULL != drmConvertedStatus->convertedData) {
+ const DrmBuffer* convertedData = drmConvertedStatus->convertedData;
+ const int bufferSize = convertedData->length;
+ reply->writeInt32(bufferSize);
+ if (0 < bufferSize) {
+ reply->write(convertedData->data, bufferSize);
+ }
+ delete [] convertedData->data;
+ delete convertedData; convertedData = NULL;
+ }
+ }
+ delete inputData; inputData = NULL;
+ delete drmConvertedStatus; drmConvertedStatus = NULL;
+ return DRM_NO_ERROR;
+ }
+
+ case CLOSE_CONVERT_SESSION:
+ {
+ LOGV("BnDrmManagerService::onTransact :CLOSE_CONVERT_SESSION");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ DrmConvertedStatus* drmConvertedStatus
+ = closeConvertSession(data.readInt32(), data.readInt32());
+
+ if (NULL != drmConvertedStatus) {
+ //Filling Drm Converted Ststus
+ reply->writeInt32(drmConvertedStatus->statusCode);
+ reply->writeInt32(drmConvertedStatus->offset);
+
+ if (NULL != drmConvertedStatus->convertedData) {
+ const DrmBuffer* convertedData = drmConvertedStatus->convertedData;
+ const int bufferSize = convertedData->length;
+ reply->writeInt32(bufferSize);
+ if (0 < bufferSize) {
+ reply->write(convertedData->data, bufferSize);
+ }
+ delete [] convertedData->data;
+ delete convertedData; convertedData = NULL;
+ }
+ }
+ delete drmConvertedStatus; drmConvertedStatus = NULL;
+ return DRM_NO_ERROR;
+ }
+
+ case GET_ALL_SUPPORT_INFO:
+ {
+ LOGV("BnDrmManagerService::onTransact :GET_ALL_SUPPORT_INFO");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ const int uniqueId = data.readInt32();
+ int length = 0;
+ DrmSupportInfo* drmSupportInfoArray = NULL;
+
+ status_t status = getAllSupportInfo(uniqueId, &length, &drmSupportInfoArray);
+
+ reply->writeInt32(length);
+ for (int i = 0; i < length; ++i) {
+ DrmSupportInfo drmSupportInfo = drmSupportInfoArray[i];
+
+ reply->writeInt32(drmSupportInfo.getFileSuffixCount());
+ DrmSupportInfo::FileSuffixIterator fileSuffixIt
+ = drmSupportInfo.getFileSuffixIterator();
+ while (fileSuffixIt.hasNext()) {
+ reply->writeString8(fileSuffixIt.next());
+ }
+
+ reply->writeInt32(drmSupportInfo.getMimeTypeCount());
+ DrmSupportInfo::MimeTypeIterator mimeTypeIt = drmSupportInfo.getMimeTypeIterator();
+ while (mimeTypeIt.hasNext()) {
+ reply->writeString8(mimeTypeIt.next());
+ }
+ reply->writeString8(drmSupportInfo.getDescription());
+ }
+ delete [] drmSupportInfoArray; drmSupportInfoArray = NULL;
+ reply->writeInt32(status);
+ return DRM_NO_ERROR;
+ }
+
+ case OPEN_DECRYPT_SESSION:
+ {
+ LOGV("BnDrmManagerService::onTransact :OPEN_DECRYPT_SESSION");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ const int uniqueId = data.readInt32();
+ const int fd = data.readFileDescriptor();
+
+ DecryptHandle* handle
+ = openDecryptSession(uniqueId, fd, data.readInt32(), data.readInt32());
+
+ if (NULL != handle) {
+ reply->writeInt32(handle->decryptId);
+ reply->writeString8(handle->mimeType);
+ reply->writeInt32(handle->decryptApiType);
+ reply->writeInt32(handle->status);
+ if (NULL != handle->decryptInfo) {
+ reply->writeInt32(handle->decryptInfo->decryptBufferLength);
+ delete handle->decryptInfo; handle->decryptInfo = NULL;
+ }
+ } else {
+ LOGE("NULL decryptHandle is returned");
+ }
+ delete handle; handle = NULL;
+ return DRM_NO_ERROR;
+ }
+
+ case CLOSE_DECRYPT_SESSION:
+ {
+ LOGV("BnDrmManagerService::onTransact :CLOSE_DECRYPT_SESSION");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ const int uniqueId = data.readInt32();
+
+ DecryptHandle* handle = new DecryptHandle();
+ handle->decryptId = data.readInt32();
+ handle->mimeType = data.readString8();
+ handle->decryptApiType = data.readInt32();
+ handle->status = data.readInt32();
+ handle->decryptInfo = NULL;
+
+ const int bufferLength = data.readInt32();
+ if (INVALID_BUFFER_LENGTH != bufferLength) {
+ handle->decryptInfo = new DecryptInfo();
+ handle->decryptInfo->decryptBufferLength = bufferLength;
+ }
+
+ closeDecryptSession(uniqueId, handle);
+ return DRM_NO_ERROR;
+ }
+
+ case INITIALIZE_DECRYPT_UNIT:
+ {
+ LOGV("BnDrmManagerService::onTransact :INITIALIZE_DECRYPT_UNIT");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ const int uniqueId = data.readInt32();
+
+ DecryptHandle handle;
+ handle.decryptId = data.readInt32();
+ handle.mimeType = data.readString8();
+ handle.decryptApiType = data.readInt32();
+ handle.status = data.readInt32();
+ handle.decryptInfo = NULL;
+
+ const int bufferLength = data.readInt32();
+ if (INVALID_BUFFER_LENGTH != bufferLength) {
+ handle.decryptInfo = new DecryptInfo();
+ handle.decryptInfo->decryptBufferLength = bufferLength;
+ }
+ const int decryptUnitId = data.readInt32();
+
+ //Filling Header info
+ const int bufferSize = data.readInt32();
+ DrmBuffer* headerInfo = NULL;
+ headerInfo = new DrmBuffer((char *)data.readInplace(bufferSize), bufferSize);
+
+ initializeDecryptUnit(uniqueId, &handle, decryptUnitId, headerInfo);
+
+ delete handle.decryptInfo; handle.decryptInfo = NULL;
+ delete headerInfo; headerInfo = NULL;
+ return DRM_NO_ERROR;
+ }
+
+ case DECRYPT:
+ {
+ LOGV("BnDrmManagerService::onTransact :DECRYPT");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ const int uniqueId = data.readInt32();
+
+ DecryptHandle handle;
+ handle.decryptId = data.readInt32();
+ handle.mimeType = data.readString8();
+ handle.decryptApiType = data.readInt32();
+ handle.status = data.readInt32();
+ handle.decryptInfo = NULL;
+
+ const int bufferLength = data.readInt32();
+ if (INVALID_BUFFER_LENGTH != bufferLength) {
+ handle.decryptInfo = new DecryptInfo();
+ handle.decryptInfo->decryptBufferLength = bufferLength;
+ }
+ const int decryptUnitId = data.readInt32();
+ const int decBufferSize = data.readInt32();
+
+ const int encBufferSize = data.readInt32();
+ DrmBuffer* encBuffer
+ = new DrmBuffer((char *)data.readInplace(encBufferSize), encBufferSize);
+
+ char* buffer = NULL;
+ buffer = new char[decBufferSize];
+ DrmBuffer* decBuffer = new DrmBuffer(buffer, decBufferSize);
+
+ const status_t status = decrypt(uniqueId, &handle, decryptUnitId, encBuffer, &decBuffer);
+
+ reply->writeInt32(status);
+
+ const int size = decBuffer->length;
+ reply->writeInt32(size);
+ reply->write(decBuffer->data, size);
+
+ delete handle.decryptInfo; handle.decryptInfo = NULL;
+ delete encBuffer; encBuffer = NULL;
+ delete decBuffer; decBuffer = NULL;
+ delete [] buffer; buffer = NULL;
+ return DRM_NO_ERROR;
+ }
+
+ case FINALIZE_DECRYPT_UNIT:
+ {
+ LOGV("BnDrmManagerService::onTransact :FINALIZE_DECRYPT_UNIT");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ const int uniqueId = data.readInt32();
+
+ DecryptHandle handle;
+ handle.decryptId = data.readInt32();
+ handle.mimeType = data.readString8();
+ handle.decryptApiType = data.readInt32();
+ handle.status = data.readInt32();
+ handle.decryptInfo = NULL;
+
+ const int bufferLength = data.readInt32();
+ if (INVALID_BUFFER_LENGTH != bufferLength) {
+ handle.decryptInfo = new DecryptInfo();
+ handle.decryptInfo->decryptBufferLength = bufferLength;
+ }
+
+ finalizeDecryptUnit(uniqueId, &handle, data.readInt32());
+
+ delete handle.decryptInfo; handle.decryptInfo = NULL;
+ return DRM_NO_ERROR;
+ }
+
+ case PREAD:
+ {
+ LOGV("BnDrmManagerService::onTransact :READ");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ const int uniqueId = data.readInt32();
+
+ DecryptHandle handle;
+ handle.decryptId = data.readInt32();
+ handle.mimeType = data.readString8();
+ handle.decryptApiType = data.readInt32();
+ handle.status = data.readInt32();
+ handle.decryptInfo = NULL;
+
+ const int bufferLength = data.readInt32();
+ if (INVALID_BUFFER_LENGTH != bufferLength) {
+ handle.decryptInfo = new DecryptInfo();
+ handle.decryptInfo->decryptBufferLength = bufferLength;
+ }
+
+ const int numBytes = data.readInt32();
+ char* buffer = new char[numBytes];
+
+ const off_t offset = data.readInt32();
+
+ ssize_t result = pread(uniqueId, &handle, buffer, numBytes, offset);
+ reply->writeInt32(result);
+ if (0 < result) {
+ reply->write(buffer, result);
+ }
+
+ delete handle.decryptInfo; handle.decryptInfo = NULL;
+ delete [] buffer, buffer = NULL;
+ return DRM_NO_ERROR;
+ }
+
+ default:
+ return BBinder::onTransact(code, data, reply, flags);
+ }
+}
+
diff --git a/drm/common/IDrmServiceListener.cpp b/drm/common/IDrmServiceListener.cpp
new file mode 100644
index 0000000..0a69115
--- /dev/null
+++ b/drm/common/IDrmServiceListener.cpp
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2010 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 "IDrmServiceListener"
+#include <utils/Log.h>
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <binder/Parcel.h>
+#include <binder/IPCThreadState.h>
+#include <drm/drm_framework_common.h>
+#include <drm/DrmInfoEvent.h>
+#include "IDrmServiceListener.h"
+
+using namespace android;
+
+status_t BpDrmServiceListener::notify(const DrmInfoEvent& event) {
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmServiceListener::getInterfaceDescriptor());
+ data.writeInt32(event.getUniqueId());
+ data.writeInt32(event.getType());
+ data.writeString8(event.getMessage());
+
+ remote()->transact(NOTIFY, data, &reply);
+ return reply.readInt32();
+}
+
+IMPLEMENT_META_INTERFACE(DrmServiceListener, "drm.IDrmServiceListener");
+
+status_t BnDrmServiceListener::onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
+
+ switch (code) {
+ case NOTIFY:
+ {
+ CHECK_INTERFACE(IDrmServiceListener, data, reply);
+ int uniqueId = data.readInt32();
+ int type = data.readInt32();
+ const String8& message = data.readString8();
+
+ status_t status = notify(DrmInfoEvent(uniqueId, type, message));
+ reply->writeInt32(status);
+
+ return DRM_NO_ERROR;
+ }
+ default:
+ return BBinder::onTransact(code, data, reply, flags);
+ }
+}
+
diff --git a/drm/common/ReadWriteUtils.cpp b/drm/common/ReadWriteUtils.cpp
new file mode 100644
index 0000000..4319c1c
--- /dev/null
+++ b/drm/common/ReadWriteUtils.cpp
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#include <ReadWriteUtils.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <utils/FileMap.h>
+#include <utils/String8.h>
+
+using namespace android;
+
+#define FAILURE -1
+
+String8 ReadWriteUtils::readBytes(const String8& filePath) {
+ FILE* file = NULL;
+ file = fopen(filePath.string(), "r");
+
+ String8 string("");
+ if (NULL != file) {
+ int fd = fileno(file);
+ struct stat sb;
+
+ if (fstat(fd, &sb) == 0 && sb.st_size > 0) {
+ FileMap* fileMap = new FileMap();
+ if (fileMap->create(filePath.string(), fd, 0, sb.st_size, true)) {
+ char* addr = (char*)fileMap->getDataPtr();
+ string.append(addr, sb.st_size);
+ fileMap->release();
+ }
+ }
+ fclose(file);
+ }
+ return string;
+}
+
+void ReadWriteUtils::writeToFile(const String8& filePath, const String8& data) {
+ FILE* file = NULL;
+ file = fopen(filePath.string(), "w+");
+
+ if (NULL != file) {
+ int fd = fileno(file);
+
+ int size = data.size();
+ if (FAILURE != ftruncate(fd, size)) {
+ FileMap* fileMap = NULL;
+ fileMap = new FileMap();
+ if (fileMap->create(filePath.string(), fd, 0, size, false)) {
+ char* addr = (char*)fileMap->getDataPtr();
+ memcpy(addr, data.string(), size);
+ fileMap->release();
+ }
+ }
+ fclose(file);
+ }
+}
+
+void ReadWriteUtils::appendToFile(const String8& filePath, const String8& data) {
+ FILE* file = NULL;
+ file = fopen(filePath.string(), "a+");
+
+ if (NULL != file) {
+ int fd = fileno(file);
+
+ int offset = lseek(fd, 0, SEEK_END);
+ if (FAILURE != offset) {
+ int newEntrySize = data.size();
+ int fileSize = offset + newEntrySize;
+
+ if (FAILURE != ftruncate(fd, fileSize)) {
+ FileMap* fileMap = NULL;
+ fileMap = new FileMap();
+ if (fileMap->create(filePath.string(), fd, offset, fileSize, false)) {
+ char* addr = (char*)fileMap->getDataPtr();
+ memcpy(addr, data.string(), data.size());
+ fileMap->release();
+ }
+ }
+ }
+ fclose(file);
+ }
+}
+
diff --git a/drm/drmserver/Android.mk b/drm/drmserver/Android.mk
new file mode 100644
index 0000000..d2ebe8e
--- /dev/null
+++ b/drm/drmserver/Android.mk
@@ -0,0 +1,39 @@
+#
+# Copyright (C) 2010 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.
+#
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ main_drmserver.cpp \
+ DrmManager.cpp \
+ DrmManagerService.cpp \
+ StringTokenizer.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+ libutils \
+ libbinder \
+ libdl
+
+LOCAL_STATIC_LIBRARIES := libdrmframeworkcommon
+
+LOCAL_C_INCLUDES := \
+ $(TOP)/frameworks/base/include \
+ $(TOP)/frameworks/base/drm/libdrmframework/include \
+ $(TOP)/frameworks/base/drm/libdrmframework/plugins/common/include
+
+LOCAL_MODULE:= drmserver
+
+include $(BUILD_EXECUTABLE)
diff --git a/drm/drmserver/DrmManager.cpp b/drm/drmserver/DrmManager.cpp
new file mode 100644
index 0000000..44886f9
--- /dev/null
+++ b/drm/drmserver/DrmManager.cpp
@@ -0,0 +1,473 @@
+/*
+ * Copyright (C) 2010 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 "DrmManager(Native)"
+#include "utils/Log.h"
+
+#include <utils/String8.h>
+#include <drm/DrmInfo.h>
+#include <drm/DrmInfoEvent.h>
+#include <drm/DrmRights.h>
+#include <drm/DrmConstraints.h>
+#include <drm/DrmInfoStatus.h>
+#include <drm/DrmInfoRequest.h>
+#include <drm/DrmSupportInfo.h>
+#include <drm/DrmConvertedStatus.h>
+#include <IDrmEngine.h>
+
+#include "DrmManager.h"
+#include "ReadWriteUtils.h"
+
+#define DECRYPT_FILE_ERROR -1
+
+using namespace android;
+
+const String8 DrmManager::EMPTY_STRING("");
+
+DrmManager::DrmManager() :
+ mDecryptSessionId(0),
+ mConvertId(0) {
+
+}
+
+DrmManager::~DrmManager() {
+
+}
+
+status_t DrmManager::loadPlugIns(int uniqueId) {
+ String8 pluginDirPath("/system/lib/drm/plugins/native");
+ return loadPlugIns(uniqueId, pluginDirPath);
+}
+
+status_t DrmManager::loadPlugIns(int uniqueId, const String8& plugInDirPath) {
+ if (mSupportInfoToPlugInIdMap.isEmpty()) {
+ mPlugInManager.loadPlugIns(plugInDirPath);
+
+ initializePlugIns(uniqueId);
+
+ populate(uniqueId);
+ } else {
+ initializePlugIns(uniqueId);
+ }
+
+ return DRM_NO_ERROR;
+}
+
+status_t DrmManager::setDrmServiceListener(
+ int uniqueId, const sp<IDrmServiceListener>& drmServiceListener) {
+ Mutex::Autolock _l(mLock);
+ mServiceListeners.add(uniqueId, drmServiceListener);
+ return DRM_NO_ERROR;
+}
+
+status_t DrmManager::unloadPlugIns(int uniqueId) {
+ Vector<String8> plugInIdList = mPlugInManager.getPlugInIdList();
+
+ for (unsigned int index = 0; index < plugInIdList.size(); index++) {
+ IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInIdList.itemAt(index));
+ rDrmEngine.terminate(uniqueId);
+ }
+
+ mConvertSessionMap.clear();
+ mDecryptSessionMap.clear();
+ mSupportInfoToPlugInIdMap.clear();
+ mPlugInManager.unloadPlugIns();
+ return DRM_NO_ERROR;
+}
+
+DrmConstraints* DrmManager::getConstraints(int uniqueId, const String8* path, const int action) {
+ const String8 plugInId = getSupportedPlugInIdFromPath(uniqueId, *path);
+ if (EMPTY_STRING != plugInId) {
+ IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
+ return rDrmEngine.getConstraints(uniqueId, path, action);
+ }
+ return NULL;
+}
+
+status_t DrmManager::installDrmEngine(int uniqueId, const String8& absolutePath) {
+ mPlugInManager.loadPlugIn(absolutePath);
+
+ IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(absolutePath);
+ rDrmEngine.initialize(uniqueId);
+ rDrmEngine.setOnInfoListener(uniqueId, this);
+
+ DrmSupportInfo* info = rDrmEngine.getSupportInfo(uniqueId);
+ mSupportInfoToPlugInIdMap.add(*info, absolutePath);
+
+ return DRM_NO_ERROR;
+}
+
+bool DrmManager::canHandle(int uniqueId, const String8& path, const String8& mimeType) {
+ const String8 plugInId = getSupportedPlugInId(mimeType);
+ bool result = (EMPTY_STRING != plugInId) ? true : false;
+
+ if (NULL != path) {
+ if (result) {
+ IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
+ result = rDrmEngine.canHandle(uniqueId, path);
+ } else {
+ result = canHandle(uniqueId, path);
+ }
+ }
+ return result;
+}
+
+DrmInfoStatus* DrmManager::processDrmInfo(int uniqueId, const DrmInfo* drmInfo) {
+ const String8 plugInId = getSupportedPlugInId(drmInfo->getMimeType());
+ if (EMPTY_STRING != plugInId) {
+ IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
+ return rDrmEngine.processDrmInfo(uniqueId, drmInfo);
+ }
+ return NULL;
+}
+
+bool DrmManager::canHandle(int uniqueId, const String8& path) {
+ bool result = false;
+ Vector<String8> plugInPathList = mPlugInManager.getPlugInIdList();
+
+ for (unsigned int i = 0; i < plugInPathList.size(); ++i) {
+ IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInPathList[i]);
+ result = rDrmEngine.canHandle(uniqueId, path);
+
+ if (result) {
+ break;
+ }
+ }
+ return result;
+}
+
+DrmInfo* DrmManager::acquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInfoRequest) {
+ const String8 plugInId = getSupportedPlugInId(drmInfoRequest->getMimeType());
+ if (EMPTY_STRING != plugInId) {
+ IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
+ return rDrmEngine.acquireDrmInfo(uniqueId, drmInfoRequest);
+ }
+ return NULL;
+}
+
+void DrmManager::saveRights(int uniqueId, const DrmRights& drmRights,
+ const String8& rightsPath, const String8& contentPath) {
+ const String8 plugInId = getSupportedPlugInId(drmRights.getMimeType());
+ if (EMPTY_STRING != plugInId) {
+ IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
+ rDrmEngine.saveRights(uniqueId, drmRights, rightsPath, contentPath);
+ }
+}
+
+String8 DrmManager::getOriginalMimeType(int uniqueId, const String8& path) {
+ const String8 plugInId = getSupportedPlugInIdFromPath(uniqueId, path);
+ if (EMPTY_STRING != plugInId) {
+ IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
+ return rDrmEngine.getOriginalMimeType(uniqueId, path);
+ }
+ return EMPTY_STRING;
+}
+
+int DrmManager::getDrmObjectType(int uniqueId, const String8& path, const String8& mimeType) {
+ const String8 plugInId = getSupportedPlugInId(uniqueId, path, mimeType);
+ if (EMPTY_STRING != plugInId) {
+ IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
+ return rDrmEngine.getDrmObjectType(uniqueId, path, mimeType);
+ }
+ return DrmObjectType::UNKNOWN;
+}
+
+int DrmManager::checkRightsStatus(int uniqueId, const String8& path, int action) {
+ const String8 plugInId = getSupportedPlugInIdFromPath(uniqueId, path);
+ if (EMPTY_STRING != plugInId) {
+ IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
+ return rDrmEngine.checkRightsStatus(uniqueId, path, action);
+ }
+ return RightsStatus::RIGHTS_INVALID;
+}
+
+void DrmManager::consumeRights(
+ int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve) {
+ if (mDecryptSessionMap.indexOfKey(decryptHandle->decryptId) != NAME_NOT_FOUND) {
+ IDrmEngine* drmEngine = mDecryptSessionMap.valueFor(decryptHandle->decryptId);
+ drmEngine->consumeRights(uniqueId, decryptHandle, action, reserve);
+ }
+}
+
+void DrmManager::setPlaybackStatus(
+ int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int position) {
+
+ if (mDecryptSessionMap.indexOfKey(decryptHandle->decryptId) != NAME_NOT_FOUND) {
+ IDrmEngine* drmEngine = mDecryptSessionMap.valueFor(decryptHandle->decryptId);
+ drmEngine->setPlaybackStatus(uniqueId, decryptHandle, playbackStatus, position);
+ }
+}
+
+bool DrmManager::validateAction(
+ int uniqueId, const String8& path, int action, const ActionDescription& description) {
+ const String8 plugInId = getSupportedPlugInIdFromPath(uniqueId, path);
+ if (EMPTY_STRING != plugInId) {
+ IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
+ return rDrmEngine.validateAction(uniqueId, path, action, description);
+ }
+ return false;
+}
+
+void DrmManager::removeRights(int uniqueId, const String8& path) {
+ const String8 plugInId = getSupportedPlugInIdFromPath(uniqueId, path);
+ if (EMPTY_STRING != plugInId) {
+ IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
+ rDrmEngine.removeRights(uniqueId, path);
+ }
+}
+
+void DrmManager::removeAllRights(int uniqueId) {
+ Vector<String8> plugInIdList = mPlugInManager.getPlugInIdList();
+
+ for (unsigned int index = 0; index < plugInIdList.size(); index++) {
+ IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInIdList.itemAt(index));
+ rDrmEngine.removeAllRights(uniqueId);
+ }
+}
+
+int DrmManager::openConvertSession(int uniqueId, const String8& mimeType) {
+ int convertId = -1;
+
+ const String8 plugInId = getSupportedPlugInId(mimeType);
+ if (EMPTY_STRING != plugInId) {
+ IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
+
+ Mutex::Autolock _l(mConvertLock);
+ ++mConvertId;
+ convertId = mConvertId;
+ mConvertSessionMap.add(mConvertId, &rDrmEngine);
+
+ rDrmEngine.openConvertSession(uniqueId, mConvertId);
+ }
+ return convertId;
+}
+
+DrmConvertedStatus* DrmManager::convertData(
+ int uniqueId, int convertId, const DrmBuffer* inputData) {
+ DrmConvertedStatus *drmConvertedStatus = NULL;
+
+ if (mConvertSessionMap.indexOfKey(convertId) != NAME_NOT_FOUND) {
+ IDrmEngine* drmEngine = mConvertSessionMap.valueFor(convertId);
+ drmConvertedStatus = drmEngine->convertData(uniqueId, convertId, inputData);
+ }
+ return drmConvertedStatus;
+}
+
+DrmConvertedStatus* DrmManager::closeConvertSession(int uniqueId, int convertId) {
+ DrmConvertedStatus *drmConvertedStatus = NULL;
+
+ if (mConvertSessionMap.indexOfKey(convertId) != NAME_NOT_FOUND) {
+ IDrmEngine* drmEngine = mConvertSessionMap.valueFor(convertId);
+ drmConvertedStatus = drmEngine->closeConvertSession(uniqueId, convertId);
+ mConvertSessionMap.removeItem(convertId);
+ }
+ return drmConvertedStatus;
+}
+
+status_t DrmManager::getAllSupportInfo(
+ int uniqueId, int* length, DrmSupportInfo** drmSupportInfoArray) {
+ Vector<String8> plugInPathList = mPlugInManager.getPlugInIdList();
+ int size = plugInPathList.size();
+ int validPlugins = 0;
+
+ if (0 < size) {
+ Vector<DrmSupportInfo> drmSupportInfoList;
+
+ for (int i = 0; i < size; ++i) {
+ String8 plugInPath = plugInPathList[i];
+ DrmSupportInfo* drmSupportInfo
+ = mPlugInManager.getPlugIn(plugInPath).getSupportInfo(uniqueId);
+ if (NULL != drmSupportInfo) {
+ drmSupportInfoList.add(*drmSupportInfo);
+ delete drmSupportInfo; drmSupportInfo = NULL;
+ }
+ }
+
+ validPlugins = drmSupportInfoList.size();
+ if (0 < validPlugins) {
+ *drmSupportInfoArray = new DrmSupportInfo[validPlugins];
+ for (int i = 0; i < validPlugins; ++i) {
+ (*drmSupportInfoArray)[i] = drmSupportInfoList[i];
+ }
+ }
+ }
+ *length = validPlugins;
+ return DRM_NO_ERROR;
+}
+
+DecryptHandle* DrmManager::openDecryptSession(int uniqueId, int fd, int offset, int length) {
+ LOGV("Entering DrmManager::openDecryptSession");
+ status_t result = DRM_ERROR_CANNOT_HANDLE;
+ Vector<String8> plugInIdList = mPlugInManager.getPlugInIdList();
+
+ DecryptHandle* handle = new DecryptHandle();
+ if (NULL != handle) {
+ Mutex::Autolock _l(mDecryptLock);
+ handle->decryptId = mDecryptSessionId + 1;
+
+ for (unsigned int index = 0; index < plugInIdList.size(); index++) {
+ String8 plugInId = plugInIdList.itemAt(index);
+ IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
+ result = rDrmEngine.openDecryptSession(uniqueId, handle, fd, offset, length);
+
+ LOGV("plug-in %s return value = %d", plugInId.string(), result);
+
+ if (DRM_NO_ERROR == result) {
+ ++mDecryptSessionId;
+ mDecryptSessionMap.add(mDecryptSessionId, &rDrmEngine);
+ LOGV("plug-in %s is selected", plugInId.string());
+ break;
+ }
+ }
+ }
+
+ if (DRM_ERROR_CANNOT_HANDLE == result) {
+ delete handle; handle = NULL;
+ LOGE("DrmManager::openDecryptSession: no capable plug-in found");
+ }
+
+ return handle;
+}
+
+void DrmManager::closeDecryptSession(int uniqueId, DecryptHandle* decryptHandle) {
+ if (mDecryptSessionMap.indexOfKey(decryptHandle->decryptId) != NAME_NOT_FOUND) {
+ IDrmEngine* drmEngine = mDecryptSessionMap.valueFor(decryptHandle->decryptId);
+ drmEngine->closeDecryptSession(uniqueId, decryptHandle);
+
+ mDecryptSessionMap.removeItem(decryptHandle->decryptId);
+ }
+}
+
+void DrmManager::initializeDecryptUnit(
+ int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId, const DrmBuffer* headerInfo) {
+ if (mDecryptSessionMap.indexOfKey(decryptHandle->decryptId) != NAME_NOT_FOUND) {
+ IDrmEngine* drmEngine = mDecryptSessionMap.valueFor(decryptHandle->decryptId);
+ drmEngine->initializeDecryptUnit(uniqueId, decryptHandle, decryptUnitId, headerInfo);
+ }
+}
+
+status_t DrmManager::decrypt(int uniqueId, DecryptHandle* decryptHandle,
+ int decryptUnitId, const DrmBuffer* encBuffer, DrmBuffer** decBuffer) {
+ status_t status = DRM_ERROR_UNKNOWN;
+ if (mDecryptSessionMap.indexOfKey(decryptHandle->decryptId) != NAME_NOT_FOUND) {
+ IDrmEngine* drmEngine = mDecryptSessionMap.valueFor(decryptHandle->decryptId);
+ status = drmEngine->decrypt(uniqueId, decryptHandle, decryptUnitId, encBuffer, decBuffer);
+ }
+ return status;
+}
+
+void DrmManager::finalizeDecryptUnit(
+ int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId) {
+ if (mDecryptSessionMap.indexOfKey(decryptHandle->decryptId) != NAME_NOT_FOUND) {
+ IDrmEngine* drmEngine = mDecryptSessionMap.valueFor(decryptHandle->decryptId);
+ drmEngine->finalizeDecryptUnit(uniqueId, decryptHandle, decryptUnitId);
+ }
+}
+
+ssize_t DrmManager::pread(int uniqueId, DecryptHandle* decryptHandle,
+ void* buffer, ssize_t numBytes, off_t offset) {
+ ssize_t result = DECRYPT_FILE_ERROR;
+
+ if (mDecryptSessionMap.indexOfKey(decryptHandle->decryptId) != NAME_NOT_FOUND) {
+ IDrmEngine* drmEngine = mDecryptSessionMap.valueFor(decryptHandle->decryptId);
+ result = drmEngine->pread(uniqueId, decryptHandle, buffer, numBytes, offset);
+ }
+ return result;
+}
+
+void DrmManager::initializePlugIns(int uniqueId) {
+ Vector<String8> plugInIdList = mPlugInManager.getPlugInIdList();
+
+ for (unsigned int index = 0; index < plugInIdList.size(); index++) {
+ IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInIdList.itemAt(index));
+ rDrmEngine.initialize(uniqueId);
+ rDrmEngine.setOnInfoListener(uniqueId, this);
+ }
+}
+
+void DrmManager::populate(int uniqueId) {
+ Vector<String8> plugInPathList = mPlugInManager.getPlugInIdList();
+
+ for (unsigned int i = 0; i < plugInPathList.size(); ++i) {
+ String8 plugInPath = plugInPathList[i];
+ DrmSupportInfo* info = mPlugInManager.getPlugIn(plugInPath).getSupportInfo(uniqueId);
+ if (NULL != info) {
+ mSupportInfoToPlugInIdMap.add(*info, plugInPath);
+ }
+ }
+}
+
+String8 DrmManager::getSupportedPlugInId(
+ int uniqueId, const String8& path, const String8& mimeType) {
+ String8 plugInId("");
+
+ if (EMPTY_STRING != mimeType) {
+ plugInId = getSupportedPlugInId(mimeType);
+ } else {
+ plugInId = getSupportedPlugInIdFromPath(uniqueId, path);
+ }
+ return plugInId;
+}
+
+String8 DrmManager::getSupportedPlugInId(const String8& mimeType) {
+ String8 plugInId("");
+
+ if (EMPTY_STRING != mimeType) {
+ for (unsigned int index = 0; index < mSupportInfoToPlugInIdMap.size(); index++) {
+ const DrmSupportInfo& drmSupportInfo = mSupportInfoToPlugInIdMap.keyAt(index);
+
+ if (drmSupportInfo.isSupportedMimeType(mimeType)) {
+ plugInId = mSupportInfoToPlugInIdMap.valueFor(drmSupportInfo);
+ break;
+ }
+ }
+ }
+ return plugInId;
+}
+
+String8 DrmManager::getSupportedPlugInIdFromPath(int uniqueId, const String8& path) {
+ String8 plugInId("");
+ const String8 fileSuffix = path.getPathExtension();
+
+ for (unsigned int index = 0; index < mSupportInfoToPlugInIdMap.size(); index++) {
+ const DrmSupportInfo& drmSupportInfo = mSupportInfoToPlugInIdMap.keyAt(index);
+
+ if (drmSupportInfo.isSupportedFileSuffix(fileSuffix)) {
+ String8 key = mSupportInfoToPlugInIdMap.valueFor(drmSupportInfo);
+ IDrmEngine& drmEngine = mPlugInManager.getPlugIn(key);
+
+ if (drmEngine.canHandle(uniqueId, path)) {
+ plugInId = key;
+ break;
+ }
+ }
+ }
+ return plugInId;
+}
+
+void DrmManager::onInfo(const DrmInfoEvent& event) {
+ Mutex::Autolock _l(mLock);
+ for (unsigned int index = 0; index < mServiceListeners.size(); index++) {
+ int uniqueId = mServiceListeners.keyAt(index);
+
+ if (uniqueId == event.getUniqueId()) {
+ sp<IDrmServiceListener> serviceListener = mServiceListeners.valueFor(uniqueId);
+ serviceListener->notify(event);
+ }
+ }
+}
+
diff --git a/drm/drmserver/DrmManagerService.cpp b/drm/drmserver/DrmManagerService.cpp
new file mode 100644
index 0000000..9d000e9
--- /dev/null
+++ b/drm/drmserver/DrmManagerService.cpp
@@ -0,0 +1,218 @@
+/*
+ * Copyright (C) 2010 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 "DrmManagerService(Native)"
+#include <utils/Log.h>
+
+#include <errno.h>
+#include <utils/threads.h>
+#include <binder/IServiceManager.h>
+#include <sys/stat.h>
+#include "DrmManagerService.h"
+#include "DrmManager.h"
+
+using namespace android;
+
+#define SUCCESS 0
+#define DRM_DIRECTORY_PERMISSION 0700
+
+void DrmManagerService::instantiate() {
+ LOGV("instantiate");
+
+ int res = mkdir("/data/drm/plugins", DRM_DIRECTORY_PERMISSION);
+ if (SUCCESS == res || EEXIST == errno) {
+ res = mkdir("/data/drm/plugins/native", DRM_DIRECTORY_PERMISSION);
+ if (SUCCESS == res || EEXIST == errno) {
+ res = mkdir("/data/drm/plugins/native/databases", DRM_DIRECTORY_PERMISSION);
+ if (SUCCESS == res || EEXIST == errno) {
+ defaultServiceManager()
+ ->addService(String16("drm.drmManager"), new DrmManagerService());
+ }
+ }
+ }
+}
+
+DrmManagerService::DrmManagerService() {
+ LOGV("created");
+ mDrmManager = NULL;
+ mDrmManager = new DrmManager();
+}
+
+DrmManagerService::~DrmManagerService() {
+ LOGV("Destroyed");
+ delete mDrmManager; mDrmManager = NULL;
+}
+
+status_t DrmManagerService::loadPlugIns(int uniqueId) {
+ LOGV("Entering load plugins");
+ return mDrmManager->loadPlugIns(uniqueId);
+}
+
+status_t DrmManagerService::loadPlugIns(int uniqueId, const String8& plugInDirPath) {
+ LOGV("Entering load plugins from path");
+ return mDrmManager->loadPlugIns(uniqueId, plugInDirPath);
+}
+
+status_t DrmManagerService::setDrmServiceListener(
+ int uniqueId, const sp<IDrmServiceListener>& drmServiceListener) {
+ LOGV("Entering setDrmServiceListener");
+ mDrmManager->setDrmServiceListener(uniqueId, drmServiceListener);
+ return DRM_NO_ERROR;
+}
+
+status_t DrmManagerService::unloadPlugIns(int uniqueId) {
+ LOGV("Entering unload plugins");
+ return mDrmManager->unloadPlugIns(uniqueId);
+}
+
+status_t DrmManagerService::installDrmEngine(int uniqueId, const String8& drmEngineFile) {
+ LOGV("Entering installDrmEngine");
+ return mDrmManager->installDrmEngine(uniqueId, drmEngineFile);
+}
+
+DrmConstraints* DrmManagerService::getConstraints(
+ int uniqueId, const String8* path, const int action) {
+ LOGV("Entering getConstraints from content");
+ return mDrmManager->getConstraints(uniqueId, path, action);
+}
+
+bool DrmManagerService::canHandle(int uniqueId, const String8& path, const String8& mimeType) {
+ LOGV("Entering canHandle");
+ return mDrmManager->canHandle(uniqueId, path, mimeType);
+}
+
+DrmInfoStatus* DrmManagerService::processDrmInfo(int uniqueId, const DrmInfo* drmInfo) {
+ LOGV("Entering processDrmInfo");
+ return mDrmManager->processDrmInfo(uniqueId, drmInfo);
+}
+
+DrmInfo* DrmManagerService::acquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInfoRequest) {
+ LOGV("Entering acquireDrmInfo");
+ return mDrmManager->acquireDrmInfo(uniqueId, drmInfoRequest);
+}
+
+void DrmManagerService::saveRights(
+ int uniqueId, const DrmRights& drmRights,
+ const String8& rightsPath, const String8& contentPath) {
+ LOGV("Entering saveRights");
+ return mDrmManager->saveRights(uniqueId, drmRights, rightsPath, contentPath);
+}
+
+String8 DrmManagerService::getOriginalMimeType(int uniqueId, const String8& path) {
+ LOGV("Entering getOriginalMimeType");
+ return mDrmManager->getOriginalMimeType(uniqueId, path);
+}
+
+int DrmManagerService::getDrmObjectType(
+ int uniqueId, const String8& path, const String8& mimeType) {
+ LOGV("Entering getDrmObjectType");
+ return mDrmManager->getDrmObjectType(uniqueId, path, mimeType);
+}
+
+int DrmManagerService::checkRightsStatus(
+ int uniqueId, const String8& path, int action) {
+ LOGV("Entering checkRightsStatus");
+ return mDrmManager->checkRightsStatus(uniqueId, path, action);
+}
+
+void DrmManagerService::consumeRights(
+ int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve) {
+ LOGV("Entering consumeRights");
+ mDrmManager->consumeRights(uniqueId, decryptHandle, action, reserve);
+}
+
+void DrmManagerService::setPlaybackStatus(
+ int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int position) {
+ LOGV("Entering setPlaybackStatus");
+ mDrmManager->setPlaybackStatus(uniqueId, decryptHandle, playbackStatus, position);
+}
+
+bool DrmManagerService::validateAction(
+ int uniqueId, const String8& path,
+ int action, const ActionDescription& description) {
+ LOGV("Entering validateAction");
+ return mDrmManager->validateAction(uniqueId, path, action, description);
+}
+
+void DrmManagerService::removeRights(int uniqueId, const String8& path) {
+ LOGV("Entering removeRights");
+ mDrmManager->removeRights(uniqueId, path);
+}
+
+void DrmManagerService::removeAllRights(int uniqueId) {
+ LOGV("Entering removeAllRights");
+ mDrmManager->removeAllRights(uniqueId);
+}
+
+int DrmManagerService::openConvertSession(int uniqueId, const String8& mimeType) {
+ LOGV("Entering openConvertSession");
+ return mDrmManager->openConvertSession(uniqueId, mimeType);
+}
+
+DrmConvertedStatus* DrmManagerService::convertData(
+ int uniqueId, int convertId, const DrmBuffer* inputData) {
+ LOGV("Entering convertData");
+ return mDrmManager->convertData(uniqueId, convertId, inputData);
+}
+
+DrmConvertedStatus* DrmManagerService::closeConvertSession(int uniqueId, int convertId) {
+ LOGV("Entering closeConvertSession");
+ return mDrmManager->closeConvertSession(uniqueId, convertId);
+}
+
+status_t DrmManagerService::getAllSupportInfo(
+ int uniqueId, int* length, DrmSupportInfo** drmSupportInfoArray) {
+ LOGV("Entering getAllSupportInfo");
+ return mDrmManager->getAllSupportInfo(uniqueId, length, drmSupportInfoArray);
+}
+
+DecryptHandle* DrmManagerService::openDecryptSession(
+ int uniqueId, int fd, int offset, int length) {
+ LOGV("Entering DrmManagerService::openDecryptSession");
+ return mDrmManager->openDecryptSession(uniqueId, fd, offset, length);
+}
+
+void DrmManagerService::closeDecryptSession(int uniqueId, DecryptHandle* decryptHandle) {
+ LOGV("Entering closeDecryptSession");
+ mDrmManager->closeDecryptSession(uniqueId, decryptHandle);
+}
+
+void DrmManagerService::initializeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle,
+ int decryptUnitId, const DrmBuffer* headerInfo) {
+ LOGV("Entering initializeDecryptUnit");
+ mDrmManager->initializeDecryptUnit(uniqueId,decryptHandle, decryptUnitId, headerInfo);
+}
+
+status_t DrmManagerService::decrypt(
+ int uniqueId, DecryptHandle* decryptHandle,
+ int decryptUnitId, const DrmBuffer* encBuffer, DrmBuffer** decBuffer) {
+ LOGV("Entering decrypt");
+ return mDrmManager->decrypt(uniqueId, decryptHandle, decryptUnitId, encBuffer, decBuffer);
+}
+
+void DrmManagerService::finalizeDecryptUnit(
+ int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId) {
+ LOGV("Entering finalizeDecryptUnit");
+ mDrmManager->finalizeDecryptUnit(uniqueId, decryptHandle, decryptUnitId);
+}
+
+ssize_t DrmManagerService::pread(int uniqueId, DecryptHandle* decryptHandle,
+ void* buffer, ssize_t numBytes, off_t offset) {
+ LOGV("Entering pread");
+ return mDrmManager->pread(uniqueId, decryptHandle, buffer, numBytes, offset);
+}
+
diff --git a/drm/drmserver/StringTokenizer.cpp b/drm/drmserver/StringTokenizer.cpp
new file mode 100644
index 0000000..367c9bd
--- /dev/null
+++ b/drm/drmserver/StringTokenizer.cpp
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#include "StringTokenizer.h"
+
+using namespace android;
+
+StringTokenizer::StringTokenizer(const String8& string, const String8& delimiter) {
+ splitString(string, delimiter);
+}
+
+void StringTokenizer::splitString(const String8& string, const String8& delimiter) {
+ for (unsigned int i = 0; i < string.length(); i++) {
+ unsigned int position = string.find(delimiter.string(), i);
+ if (string.length() != position) {
+ String8 token(string.string()+i, position-i);
+ if (token.length()) {
+ mStringTokenizerVector.push(token);
+ i = position + delimiter.length() - 1;
+ }
+ } else {
+ mStringTokenizerVector.push(String8(string.string()+i, string.length()-i));
+ break;
+ }
+ }
+}
+
+StringTokenizer::Iterator StringTokenizer::iterator() {
+ return Iterator(this);
+}
+
+StringTokenizer::Iterator::Iterator(const StringTokenizer::Iterator& iterator) :
+ mStringTokenizer(iterator.mStringTokenizer),
+ mIndex(iterator.mIndex) {
+ LOGV("StringTokenizer::Iterator::Iterator");
+}
+
+StringTokenizer::Iterator& StringTokenizer::Iterator::operator=(
+ const StringTokenizer::Iterator& iterator) {
+ LOGV("StringTokenizer::Iterator::operator=");
+ mStringTokenizer = iterator.mStringTokenizer;
+ mIndex = iterator.mIndex;
+ return *this;
+}
+
+bool StringTokenizer::Iterator::hasNext() {
+ return mIndex < mStringTokenizer->mStringTokenizerVector.size();
+}
+
+String8& StringTokenizer::Iterator::next() {
+ String8& value = mStringTokenizer->mStringTokenizerVector.editItemAt(mIndex);
+ mIndex++;
+ return value;
+}
+
diff --git a/drm/drmserver/main_drmserver.cpp b/drm/drmserver/main_drmserver.cpp
new file mode 100644
index 0000000..6d10646
--- /dev/null
+++ b/drm/drmserver/main_drmserver.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <grp.h>
+
+#include <binder/IPCThreadState.h>
+#include <binder/ProcessState.h>
+#include <binder/IServiceManager.h>
+#include <utils/Log.h>
+#include <private/android_filesystem_config.h>
+
+#include <DrmManagerService.h>
+
+using namespace android;
+
+int main(int argc, char** argv)
+{
+ sp<ProcessState> proc(ProcessState::self());
+ sp<IServiceManager> sm = defaultServiceManager();
+ LOGI("ServiceManager: %p", sm.get());
+ DrmManagerService::instantiate();
+ ProcessState::self()->startThreadPool();
+ IPCThreadState::self()->joinThreadPool();
+}
+
diff --git a/drm/libdrmframework/Android.mk b/drm/libdrmframework/Android.mk
new file mode 100644
index 0000000..c25d79b
--- /dev/null
+++ b/drm/libdrmframework/Android.mk
@@ -0,0 +1,42 @@
+#
+# Copyright (C) 2010 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.
+#
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ DrmManagerClientImpl.cpp \
+ DrmManagerClient.cpp
+
+LOCAL_MODULE:= libdrmframework
+
+LOCAL_SHARED_LIBRARIES := \
+ libutils \
+ libbinder \
+ libdl
+
+LOCAL_STATIC_LIBRARIES := \
+ libdrmframeworkcommon
+
+LOCAL_C_INCLUDES += \
+ $(TOP)/frameworks/base/drm/libdrmframework/include \
+ $(TOP)/frameworks/base/include
+
+LOCAL_PRELINK_MODULE := false
+
+include $(BUILD_SHARED_LIBRARY)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/drm/libdrmframework/DrmManagerClient.cpp b/drm/libdrmframework/DrmManagerClient.cpp
new file mode 100644
index 0000000..06c7c50
--- /dev/null
+++ b/drm/libdrmframework/DrmManagerClient.cpp
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2010 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 "DrmManagerClient(Native)"
+#include <utils/Log.h>
+
+#include <utils/String8.h>
+#include <binder/IServiceManager.h>
+#include <drm/DrmManagerClient.h>
+
+#include "DrmManagerClientImpl.h"
+
+using namespace android;
+
+DrmManagerClient::DrmManagerClient() {
+ int uniqueId = 0;
+ mDrmManagerClientImpl = NULL;
+
+ mDrmManagerClientImpl = DrmManagerClientImpl::create(&uniqueId);
+ mUniqueId = uniqueId;
+
+ loadPlugIns();
+}
+
+DrmManagerClient::~DrmManagerClient() {
+ unloadPlugIns();
+ DrmManagerClientImpl::remove(mUniqueId);
+
+ delete mDrmManagerClientImpl; mDrmManagerClientImpl = NULL;
+}
+
+status_t DrmManagerClient::loadPlugIns() {
+ return mDrmManagerClientImpl->loadPlugIns(mUniqueId);
+}
+
+status_t DrmManagerClient::setOnInfoListener(
+ const sp<DrmManagerClient::OnInfoListener>& infoListener) {
+ return mDrmManagerClientImpl->setOnInfoListener(mUniqueId, infoListener);
+}
+
+status_t DrmManagerClient::unloadPlugIns() {
+ return mDrmManagerClientImpl->unloadPlugIns(mUniqueId);
+}
+
+DrmConstraints* DrmManagerClient::getConstraints(const String8* path, const int action) {
+ return mDrmManagerClientImpl->getConstraints(mUniqueId, path, action);
+}
+
+bool DrmManagerClient::canHandle(const String8& path, const String8& mimeType) {
+ return mDrmManagerClientImpl->canHandle(mUniqueId, path, mimeType);
+}
+
+DrmInfoStatus* DrmManagerClient::processDrmInfo(const DrmInfo* drmInfo) {
+ return mDrmManagerClientImpl->processDrmInfo(mUniqueId, drmInfo);
+}
+
+DrmInfo* DrmManagerClient::acquireDrmInfo(const DrmInfoRequest* drmInfoRequest) {
+ return mDrmManagerClientImpl->acquireDrmInfo(mUniqueId, drmInfoRequest);
+}
+
+void DrmManagerClient::saveRights(
+ const DrmRights& drmRights, const String8& rightsPath, const String8& contentPath) {
+ return mDrmManagerClientImpl->saveRights(mUniqueId, drmRights, rightsPath, contentPath);
+}
+
+String8 DrmManagerClient::getOriginalMimeType(const String8& path) {
+ return mDrmManagerClientImpl->getOriginalMimeType(mUniqueId, path);
+}
+
+int DrmManagerClient::getDrmObjectType(const String8& path, const String8& mimeType) {
+ return mDrmManagerClientImpl->getDrmObjectType( mUniqueId, path, mimeType);
+}
+
+int DrmManagerClient::checkRightsStatus(const String8& path, int action) {
+ return mDrmManagerClientImpl->checkRightsStatus(mUniqueId, path, action);
+}
+
+void DrmManagerClient::consumeRights(DecryptHandle* decryptHandle, int action, bool reserve) {
+ mDrmManagerClientImpl->consumeRights(mUniqueId, decryptHandle, action, reserve);
+}
+
+void DrmManagerClient::setPlaybackStatus(
+ DecryptHandle* decryptHandle, int playbackStatus, int position) {
+ mDrmManagerClientImpl->setPlaybackStatus(mUniqueId, decryptHandle, playbackStatus, position);
+}
+
+bool DrmManagerClient::validateAction(
+ const String8& path, int action, const ActionDescription& description) {
+ return mDrmManagerClientImpl->validateAction(mUniqueId, path, action, description);
+}
+
+void DrmManagerClient::removeRights(const String8& path) {
+ mDrmManagerClientImpl->removeRights(mUniqueId, path);
+}
+
+void DrmManagerClient::removeAllRights() {
+ mDrmManagerClientImpl->removeAllRights(mUniqueId);
+}
+
+int DrmManagerClient::openConvertSession(const String8& mimeType) {
+ return mDrmManagerClientImpl->openConvertSession(mUniqueId, mimeType);
+}
+
+DrmConvertedStatus* DrmManagerClient::convertData(int convertId, const DrmBuffer* inputData) {
+ return mDrmManagerClientImpl->convertData(mUniqueId, convertId, inputData);
+}
+
+DrmConvertedStatus* DrmManagerClient::closeConvertSession(int convertId) {
+ return mDrmManagerClientImpl->closeConvertSession(mUniqueId, convertId);
+}
+
+status_t DrmManagerClient::getAllSupportInfo(int* length, DrmSupportInfo** drmSupportInfoArray) {
+ return mDrmManagerClientImpl->getAllSupportInfo(mUniqueId, length, drmSupportInfoArray);
+}
+
+DecryptHandle* DrmManagerClient::openDecryptSession(int fd, int offset, int length) {
+ return mDrmManagerClientImpl->openDecryptSession(mUniqueId, fd, offset, length);
+}
+
+void DrmManagerClient::closeDecryptSession(DecryptHandle* decryptHandle) {
+ mDrmManagerClientImpl->closeDecryptSession(mUniqueId, decryptHandle);
+}
+
+void DrmManagerClient::initializeDecryptUnit(
+ DecryptHandle* decryptHandle, int decryptUnitId, const DrmBuffer* headerInfo) {
+ mDrmManagerClientImpl->initializeDecryptUnit(
+ mUniqueId, decryptHandle, decryptUnitId, headerInfo);
+}
+
+status_t DrmManagerClient::decrypt(
+ DecryptHandle* decryptHandle, int decryptUnitId,
+ const DrmBuffer* encBuffer, DrmBuffer** decBuffer) {
+ return mDrmManagerClientImpl->decrypt(
+ mUniqueId, decryptHandle, decryptUnitId, encBuffer, decBuffer);
+}
+
+void DrmManagerClient::finalizeDecryptUnit(DecryptHandle* decryptHandle, int decryptUnitId) {
+ mDrmManagerClientImpl->finalizeDecryptUnit(mUniqueId, decryptHandle, decryptUnitId);
+}
+
+ssize_t DrmManagerClient::pread(
+ DecryptHandle* decryptHandle, void* buffer, ssize_t numBytes, off_t offset) {
+ return mDrmManagerClientImpl->pread(mUniqueId, decryptHandle, buffer, numBytes, offset);
+}
+
diff --git a/drm/libdrmframework/DrmManagerClientImpl.cpp b/drm/libdrmframework/DrmManagerClientImpl.cpp
new file mode 100644
index 0000000..7274b49
--- /dev/null
+++ b/drm/libdrmframework/DrmManagerClientImpl.cpp
@@ -0,0 +1,319 @@
+/*
+ * Copyright (C) 2010 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 "DrmManagerClientImpl(Native)"
+#include <utils/Log.h>
+
+#include <utils/String8.h>
+#include <utils/Vector.h>
+#include <binder/IServiceManager.h>
+
+#include "DrmManagerClientImpl.h"
+
+using namespace android;
+
+#define INVALID_VALUE -1
+
+Mutex DrmManagerClientImpl::mMutex;
+Vector<int> DrmManagerClientImpl::mUniqueIdVector;
+sp<IDrmManagerService> DrmManagerClientImpl::mDrmManagerService;
+const String8 DrmManagerClientImpl::EMPTY_STRING("");
+
+DrmManagerClientImpl* DrmManagerClientImpl::create(int* pUniqueId) {
+ if (0 == *pUniqueId) {
+ int uniqueId = 0;
+ bool foundUniqueId = false;
+ srand(time(NULL));
+
+ while (!foundUniqueId) {
+ const int size = mUniqueIdVector.size();
+ uniqueId = rand() % 100;
+
+ int index = 0;
+ for (; index < size; ++index) {
+ if (mUniqueIdVector.itemAt(index) == uniqueId) {
+ foundUniqueId = false;
+ break;
+ }
+ }
+ if (index == size) {
+ foundUniqueId = true;
+ }
+ }
+ *pUniqueId = uniqueId;
+ }
+ mUniqueIdVector.push(*pUniqueId);
+ return new DrmManagerClientImpl();
+}
+
+void DrmManagerClientImpl::remove(int uniqueId) {
+ for (int i = 0; i < mUniqueIdVector.size(); i++) {
+ if (uniqueId == mUniqueIdVector.itemAt(i)) {
+ mUniqueIdVector.removeAt(i);
+ break;
+ }
+ }
+}
+
+DrmManagerClientImpl::DrmManagerClientImpl() {
+
+}
+
+DrmManagerClientImpl::~DrmManagerClientImpl() {
+
+}
+
+const sp<IDrmManagerService>& DrmManagerClientImpl::getDrmManagerService() {
+ mMutex.lock();
+ if (NULL == mDrmManagerService.get()) {
+ sp<IServiceManager> sm = defaultServiceManager();
+ sp<IBinder> binder;
+ do {
+ binder = sm->getService(String16("drm.drmManager"));
+ if (binder != 0) {
+ break;
+ }
+ LOGW("DrmManagerService not published, waiting...");
+ struct timespec reqt;
+ reqt.tv_sec = 0;
+ reqt.tv_nsec = 500000000; //0.5 sec
+ nanosleep(&reqt, NULL);
+ } while (true);
+
+ mDrmManagerService = interface_cast<IDrmManagerService>(binder);
+ }
+ mMutex.unlock();
+ return mDrmManagerService;
+}
+
+status_t DrmManagerClientImpl::loadPlugIns(int uniqueId) {
+ return getDrmManagerService()->loadPlugIns(uniqueId);
+}
+
+status_t DrmManagerClientImpl::loadPlugIns(int uniqueId, const String8& plugInDirPath) {
+ status_t status = DRM_ERROR_UNKNOWN;
+ if (EMPTY_STRING != plugInDirPath) {
+ status = getDrmManagerService()->loadPlugIns(uniqueId, plugInDirPath);
+ }
+ return status;
+}
+
+status_t DrmManagerClientImpl::setOnInfoListener(
+ int uniqueId, const sp<DrmManagerClient::OnInfoListener>& infoListener) {
+ Mutex::Autolock _l(mLock);
+ mOnInfoListener = infoListener;
+ return getDrmManagerService()->setDrmServiceListener(uniqueId, this);
+}
+
+status_t DrmManagerClientImpl::unloadPlugIns(int uniqueId) {
+ return getDrmManagerService()->unloadPlugIns(uniqueId);
+}
+
+status_t DrmManagerClientImpl::installDrmEngine(int uniqueId, const String8& drmEngineFile) {
+ status_t status = DRM_ERROR_UNKNOWN;
+ if (EMPTY_STRING != drmEngineFile) {
+ status = getDrmManagerService()->installDrmEngine(uniqueId, drmEngineFile);
+ }
+ return status;
+}
+
+DrmConstraints* DrmManagerClientImpl::getConstraints(
+ int uniqueId, const String8* path, const int action) {
+ DrmConstraints *drmConstraints = NULL;
+ if ((NULL != path) && (EMPTY_STRING != *path)) {
+ drmConstraints = getDrmManagerService()->getConstraints(uniqueId, path, action);
+ }
+ return drmConstraints;
+}
+
+bool DrmManagerClientImpl::canHandle(int uniqueId, const String8& path, const String8& mimeType) {
+ bool retCode = false;
+ if ((EMPTY_STRING != path) || (EMPTY_STRING != mimeType)) {
+ retCode = getDrmManagerService()->canHandle(uniqueId, path, mimeType);
+ }
+ return retCode;
+}
+
+DrmInfoStatus* DrmManagerClientImpl::processDrmInfo(int uniqueId, const DrmInfo* drmInfo) {
+ DrmInfoStatus *drmInfoStatus = NULL;
+ if (NULL != drmInfo) {
+ drmInfoStatus = getDrmManagerService()->processDrmInfo(uniqueId, drmInfo);
+ }
+ return drmInfoStatus;
+}
+
+DrmInfo* DrmManagerClientImpl::acquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInfoRequest) {
+ DrmInfo* drmInfo = NULL;
+ if (NULL != drmInfoRequest) {
+ drmInfo = getDrmManagerService()->acquireDrmInfo(uniqueId, drmInfoRequest);
+ }
+ return drmInfo;
+}
+
+void DrmManagerClientImpl::saveRights(int uniqueId, const DrmRights& drmRights,
+ const String8& rightsPath, const String8& contentPath) {
+ if (EMPTY_STRING != contentPath) {
+ getDrmManagerService()->saveRights(uniqueId, drmRights, rightsPath, contentPath);
+ }
+}
+
+String8 DrmManagerClientImpl::getOriginalMimeType(int uniqueId, const String8& path) {
+ String8 mimeType = EMPTY_STRING;
+ if (EMPTY_STRING != path) {
+ mimeType = getDrmManagerService()->getOriginalMimeType(uniqueId, path);
+ }
+ return mimeType;
+}
+
+int DrmManagerClientImpl::getDrmObjectType(
+ int uniqueId, const String8& path, const String8& mimeType) {
+ int drmOjectType = DrmObjectType::UNKNOWN;
+ if ((EMPTY_STRING != path) || (EMPTY_STRING != mimeType)) {
+ drmOjectType = getDrmManagerService()->getDrmObjectType(uniqueId, path, mimeType);
+ }
+ return drmOjectType;
+}
+
+int DrmManagerClientImpl::checkRightsStatus(
+ int uniqueId, const String8& path, int action) {
+ int rightsStatus = RightsStatus::RIGHTS_INVALID;
+ if (EMPTY_STRING != path) {
+ rightsStatus = getDrmManagerService()->checkRightsStatus(uniqueId, path, action);
+ }
+ return rightsStatus;
+}
+
+void DrmManagerClientImpl::consumeRights(
+ int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve) {
+ if (NULL != decryptHandle) {
+ getDrmManagerService()->consumeRights(uniqueId, decryptHandle, action, reserve);
+ }
+}
+
+void DrmManagerClientImpl::setPlaybackStatus(
+ int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int position) {
+ if (NULL != decryptHandle) {
+ getDrmManagerService()->setPlaybackStatus(
+ uniqueId, decryptHandle, playbackStatus, position);
+ }
+}
+
+bool DrmManagerClientImpl::validateAction(
+ int uniqueId, const String8& path, int action, const ActionDescription& description) {
+ bool retCode = false;
+ if (EMPTY_STRING != path) {
+ retCode = getDrmManagerService()->validateAction(uniqueId, path, action, description);
+ }
+ return retCode;
+}
+
+void DrmManagerClientImpl::removeRights(int uniqueId, const String8& path) {
+ if (EMPTY_STRING != path) {
+ getDrmManagerService()->removeRights(uniqueId, path);
+ }
+}
+
+void DrmManagerClientImpl::removeAllRights(int uniqueId) {
+ getDrmManagerService()->removeAllRights(uniqueId);
+}
+
+int DrmManagerClientImpl::openConvertSession(int uniqueId, const String8& mimeType) {
+ int retCode = INVALID_VALUE;
+ if (EMPTY_STRING != mimeType) {
+ retCode = getDrmManagerService()->openConvertSession(uniqueId, mimeType);
+ }
+ return retCode;
+}
+
+DrmConvertedStatus* DrmManagerClientImpl::convertData(
+ int uniqueId, int convertId, const DrmBuffer* inputData) {
+ DrmConvertedStatus* drmConvertedStatus = NULL;
+ if (NULL != inputData) {
+ drmConvertedStatus = getDrmManagerService()->convertData(uniqueId, convertId, inputData);
+ }
+ return drmConvertedStatus;
+}
+
+DrmConvertedStatus* DrmManagerClientImpl::closeConvertSession(int uniqueId, int convertId) {
+ return getDrmManagerService()->closeConvertSession(uniqueId, convertId);
+}
+
+status_t DrmManagerClientImpl::getAllSupportInfo(
+ int uniqueId, int* length, DrmSupportInfo** drmSupportInfoArray) {
+ status_t status = DRM_ERROR_UNKNOWN;
+ if ((NULL != drmSupportInfoArray) && (NULL != length)) {
+ status = getDrmManagerService()->getAllSupportInfo(uniqueId, length, drmSupportInfoArray);
+ }
+ return status;
+}
+
+DecryptHandle* DrmManagerClientImpl::openDecryptSession(
+ int uniqueId, int fd, int offset, int length) {
+ LOGV("Entering DrmManagerClientImpl::openDecryptSession");
+ return getDrmManagerService()->openDecryptSession(uniqueId, fd, offset, length);
+}
+
+void DrmManagerClientImpl::closeDecryptSession(int uniqueId, DecryptHandle* decryptHandle) {
+ if (NULL != decryptHandle) {
+ getDrmManagerService()->closeDecryptSession( uniqueId, decryptHandle);
+ }
+}
+
+void DrmManagerClientImpl::initializeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle,
+ int decryptUnitId, const DrmBuffer* headerInfo) {
+ if ((NULL != decryptHandle) && (NULL != headerInfo)) {
+ getDrmManagerService()->initializeDecryptUnit(
+ uniqueId, decryptHandle, decryptUnitId, headerInfo);
+ }
+}
+
+status_t DrmManagerClientImpl::decrypt(int uniqueId, DecryptHandle* decryptHandle,
+ int decryptUnitId, const DrmBuffer* encBuffer, DrmBuffer** decBuffer) {
+ status_t status = DRM_ERROR_UNKNOWN;
+ if ((NULL != decryptHandle) && (NULL != encBuffer)
+ && (NULL != decBuffer) && (NULL != *decBuffer)) {
+ status = getDrmManagerService()->decrypt(
+ uniqueId, decryptHandle, decryptUnitId, encBuffer, decBuffer);
+ }
+ return status;
+}
+
+void DrmManagerClientImpl::finalizeDecryptUnit(
+ int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId) {
+ if (NULL != decryptHandle) {
+ getDrmManagerService()->finalizeDecryptUnit(uniqueId, decryptHandle, decryptUnitId);
+ }
+}
+
+ssize_t DrmManagerClientImpl::pread(int uniqueId, DecryptHandle* decryptHandle,
+ void* buffer, ssize_t numBytes, off_t offset) {
+ ssize_t retCode = INVALID_VALUE;
+ if ((NULL != decryptHandle) && (NULL != buffer) && (0 < numBytes)) {
+ retCode = getDrmManagerService()->pread(uniqueId, decryptHandle, buffer, numBytes, offset);
+ }
+ return retCode;
+}
+
+status_t DrmManagerClientImpl::notify(const DrmInfoEvent& event) {
+ if (NULL != mOnInfoListener.get()) {
+ Mutex::Autolock _l(mLock);
+ sp<DrmManagerClient::OnInfoListener> listener = mOnInfoListener;
+ listener->onInfo(event);
+ }
+ return DRM_NO_ERROR;
+}
+
diff --git a/drm/libdrmframework/include/DrmIOService.h b/drm/libdrmframework/include/DrmIOService.h
new file mode 100644
index 0000000..244124e
--- /dev/null
+++ b/drm/libdrmframework/include/DrmIOService.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#ifndef __DRM_IO_SERVICE_H__
+#define __DRM_IO_SERVICE_H__
+
+#include "IDrmIOService.h"
+
+namespace android {
+
+/**
+ * This is the implementation class for DRM IO service.
+ *
+ * The instance of this class is created while starting the DRM IO service.
+ *
+ */
+class DrmIOService : public BnDrmIOService {
+public:
+ static void instantiate();
+
+private:
+ DrmIOService();
+ virtual ~DrmIOService();
+
+public:
+ void writeToFile(const String8& filePath, const String8& dataBuffer);
+ String8 readFromFile(const String8& filePath);
+};
+
+};
+
+#endif /* __DRM_IO_SERVICE_H__ */
+
diff --git a/drm/libdrmframework/include/DrmManager.h b/drm/libdrmframework/include/DrmManager.h
new file mode 100644
index 0000000..2ba9e99
--- /dev/null
+++ b/drm/libdrmframework/include/DrmManager.h
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#ifndef __DRM_MANAGER_H__
+#define __DRM_MANAGER_H__
+
+#include <utils/Errors.h>
+#include <utils/threads.h>
+#include <drm/drm_framework_common.h>
+#include "IDrmEngine.h"
+#include "PlugInManager.h"
+#include "IDrmServiceListener.h"
+
+namespace android {
+
+class IDrmManager;
+class DrmRegistrationInfo;
+class DrmUnregistrationInfo;
+class DrmRightsAcquisitionInfo;
+class DrmContentIds;
+class DrmConstraints;
+class DrmRights;
+class DrmInfo;
+class DrmInfoStatus;
+class DrmConvertedStatus;
+class DrmInfoRequest;
+class DrmSupportInfo;
+class ActionDescription;
+
+/**
+ * This is implementation class for DRM Manager. This class delegates the
+ * functionality to corresponding DRM Engine.
+ *
+ * The DrmManagerService class creates an instance of this class.
+ *
+ */
+class DrmManager : public IDrmEngine::OnInfoListener {
+public:
+ DrmManager();
+ virtual ~DrmManager();
+
+public:
+
+ status_t loadPlugIns(int uniqueId);
+
+ status_t loadPlugIns(int uniqueId, const String8& plugInDirPath);
+
+ status_t setDrmServiceListener(
+ int uniqueId, const sp<IDrmServiceListener>& drmServiceListener);
+
+ status_t unloadPlugIns(int uniqueId);
+
+ status_t installDrmEngine(int uniqueId, const String8& drmEngineFile);
+
+ DrmConstraints* getConstraints(int uniqueId, const String8* path, const int action);
+
+ bool canHandle(int uniqueId, const String8& path, const String8& mimeType);
+
+ DrmInfoStatus* processDrmInfo(int uniqueId, const DrmInfo* drmInfo);
+
+ DrmInfo* acquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInfoRequest);
+
+ void saveRights(int uniqueId, const DrmRights& drmRights,
+ const String8& rightsPath, const String8& contentPath);
+
+ String8 getOriginalMimeType(int uniqueId, const String8& path);
+
+ int getDrmObjectType(int uniqueId, const String8& path, const String8& mimeType);
+
+ int checkRightsStatus(int uniqueId, const String8& path, int action);
+
+ void consumeRights(int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve);
+
+ void setPlaybackStatus(
+ int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int position);
+
+ bool validateAction(
+ int uniqueId, const String8& path, int action, const ActionDescription& description);
+
+ void removeRights(int uniqueId, const String8& path);
+
+ void removeAllRights(int uniqueId);
+
+ int openConvertSession(int uniqueId, const String8& mimeType);
+
+ DrmConvertedStatus* convertData(int uniqueId, int convertId, const DrmBuffer* inputData);
+
+ DrmConvertedStatus* closeConvertSession(int uniqueId, int convertId);
+
+ status_t getAllSupportInfo(int uniqueId, int* length, DrmSupportInfo** drmSupportInfoArray);
+
+ DecryptHandle* openDecryptSession(int uniqueId, int fd, int offset, int length);
+
+ void closeDecryptSession(int uniqueId, DecryptHandle* decryptHandle);
+
+ void initializeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle,
+ int decryptUnitId, const DrmBuffer* headerInfo);
+
+ status_t decrypt(int uniqueId, DecryptHandle* decryptHandle,
+ int decryptUnitId, const DrmBuffer* encBuffer,DrmBuffer** decBuffer);
+
+ void finalizeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId);
+
+ ssize_t pread(int uniqueId, DecryptHandle* decryptHandle,
+ void* buffer, ssize_t numBytes, off_t offset);
+
+ void onInfo(const DrmInfoEvent& event);
+
+private:
+ String8 getSupportedPlugInId(int uniqueId, const String8& path, const String8& mimeType);
+
+ String8 getSupportedPlugInId(const String8& mimeType);
+
+ String8 getSupportedPlugInIdFromPath(int uniqueId, const String8& path);
+
+ void populate(int uniqueId);
+
+ bool canHandle(int uniqueId, const String8& path);
+
+ void initializePlugIns(int uniqueId);
+
+private:
+ static const String8 EMPTY_STRING;
+
+ int mDecryptSessionId;
+ int mConvertId;
+ Mutex mLock;
+ Mutex mDecryptLock;
+ Mutex mConvertLock;
+ TPlugInManager<IDrmEngine> mPlugInManager;
+ KeyedVector< DrmSupportInfo, String8 > mSupportInfoToPlugInIdMap;
+ KeyedVector< int, IDrmEngine*> mConvertSessionMap;
+ KeyedVector< int, sp<IDrmServiceListener> > mServiceListeners;
+ KeyedVector< int, IDrmEngine*> mDecryptSessionMap;
+};
+
+};
+
+#endif /* __DRM_MANAGER_H__ */
+
diff --git a/drm/libdrmframework/include/DrmManagerClientImpl.h b/drm/libdrmframework/include/DrmManagerClientImpl.h
new file mode 100644
index 0000000..e70e6e1
--- /dev/null
+++ b/drm/libdrmframework/include/DrmManagerClientImpl.h
@@ -0,0 +1,400 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#ifndef __DRM_MANAGER_CLIENT_IMPL_H__
+#define __DRM_MANAGER_CLIENT_IMPL_H__
+
+#include <binder/IMemory.h>
+#include <utils/threads.h>
+#include <drm/DrmManagerClient.h>
+
+#include "IDrmManagerService.h"
+
+namespace android {
+
+class DrmInfoEvent;
+/**
+ * This is implementation class for DrmManagerClient class.
+ *
+ * Only the JNI layer creates an instance of this class to delegate
+ * functionality to Native later.
+ *
+ */
+class DrmManagerClientImpl : public BnDrmServiceListener {
+private:
+ DrmManagerClientImpl();
+
+public:
+ static DrmManagerClientImpl* create(int* pUniqueId);
+
+ static void remove(int uniqueId);
+
+ virtual ~DrmManagerClientImpl();
+
+public:
+ /**
+ * Initialize DRM Manager
+ * load available plug-ins from default plugInDirPath
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ status_t loadPlugIns(int uniqueId);
+
+ /**
+ * Finalize DRM Manager
+ * release resources associated with each plug-in
+ * unload all plug-ins and etc.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ status_t unloadPlugIns(int uniqueId);
+
+ /**
+ * Register a callback to be invoked when the caller required to
+ * receive necessary information
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] infoListener Listener
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ status_t setOnInfoListener(
+ int uniqueId, const sp<DrmManagerClient::OnInfoListener>& infoListener);
+
+ /**
+ * Get constraint information associated with input content
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] path Path of the protected content
+ * @param[in] action Actions defined such as,
+ * Action::DEFAULT, Action::PLAY, etc
+ * @return DrmConstraints
+ * key-value pairs of constraint are embedded in it
+ * @note
+ * In case of error, return NULL
+ */
+ DrmConstraints* getConstraints(int uniqueId, const String8* path, const int action);
+
+ /**
+ * Check whether the given mimetype or path can be handled
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] path Path of the content needs to be handled
+ * @param[in] mimetype Mimetype of the content needs to be handled
+ * @return
+ * True if DrmManager can handle given path or mime type.
+ */
+ bool canHandle(int uniqueId, const String8& path, const String8& mimeType);
+
+ /**
+ * Executes given drm information based on its type
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] drmInfo Information needs to be processed
+ * @return DrmInfoStatus
+ * instance as a result of processing given input
+ */
+ DrmInfoStatus* processDrmInfo(int uniqueId, const DrmInfo* drmInfo);
+
+ /**
+ * Retrieves necessary information for registration, unregistration or rights
+ * acquisition information.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] drmInfoRequest Request information to retrieve drmInfo
+ * @return DrmInfo
+ * instance as a result of processing given input
+ */
+ DrmInfo* acquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInfoRequest);
+
+ /**
+ * Save DRM rights to specified rights path
+ * and make association with content path
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] drmRights DrmRights to be saved
+ * @param[in] rightsPath File path where rights to be saved
+ * @param[in] contentPath File path where content was saved
+ */
+ void saveRights(int uniqueId, const DrmRights& drmRights,
+ const String8& rightsPath, const String8& contentPath);
+
+ /**
+ * Retrieves the mime type embedded inside the original content
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] path the path of the protected content
+ * @return String8
+ * Returns mime-type of the original content, such as "video/mpeg"
+ */
+ String8 getOriginalMimeType(int uniqueId, const String8& path);
+
+ /**
+ * Retrieves the type of the protected object (content, rights, etc..)
+ * using specified path or mimetype. At least one parameter should be non null
+ * to retrieve DRM object type
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] path Path of the content or null.
+ * @param[in] mimeType Mime type of the content or null.
+ * @return type of the DRM content,
+ * such as DrmObjectType::CONTENT, DrmObjectType::RIGHTS_OBJECT
+ */
+ int getDrmObjectType(int uniqueId, const String8& path, const String8& mimeType);
+
+ /**
+ * Check whether the given content has valid rights or not
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] path Path of the protected content
+ * @param[in] action Action to perform (Action::DEFAULT, Action::PLAY, etc)
+ * @return the status of the rights for the protected content,
+ * such as RightsStatus::RIGHTS_VALID, RightsStatus::RIGHTS_EXPIRED, etc.
+ */
+ int checkRightsStatus(int uniqueId, const String8& path, int action);
+
+ /**
+ * Consumes the rights for a content.
+ * If the reserve parameter is true the rights is reserved until the same
+ * application calls this api again with the reserve parameter set to false.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptHandle Handle for the decryption session
+ * @param[in] action Action to perform. (Action::DEFAULT, Action::PLAY, etc)
+ * @param[in] reserve True if the rights should be reserved.
+ */
+ void consumeRights(int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve);
+
+ /**
+ * Informs the DRM engine about the playback actions performed on the DRM files.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptHandle Handle for the decryption session
+ * @param[in] playbackStatus Playback action (Playback::START, Playback::STOP, Playback::PAUSE)
+ * @param[in] position Position in the file (in milliseconds) where the start occurs.
+ * Only valid together with Playback::START.
+ */
+ void setPlaybackStatus(
+ int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int position);
+
+ /**
+ * Validates whether an action on the DRM content is allowed or not.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] path Path of the protected content
+ * @param[in] action Action to validate (Action::PLAY, Action::TRANSFER, etc)
+ * @param[in] description Detailed description of the action
+ * @return true if the action is allowed.
+ */
+ bool validateAction(
+ int uniqueId, const String8& path, int action, const ActionDescription& description);
+
+ /**
+ * Removes the rights associated with the given protected content
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] path Path of the protected content
+ */
+ void removeRights(int uniqueId, const String8& path);
+
+ /**
+ * Removes all the rights information of each plug-in associated with
+ * DRM framework. Will be used in master reset
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ */
+ void removeAllRights(int uniqueId);
+
+ /**
+ * This API is for Forward Lock based DRM scheme.
+ * Each time the application tries to download a new DRM file
+ * which needs to be converted, then the application has to
+ * begin with calling this API.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] mimeType Description/MIME type of the input data packet
+ * @return Return handle for the convert session
+ */
+ int openConvertSession(int uniqueId, const String8& mimeType);
+
+ /**
+ * Accepts and converts the input data which is part of DRM file.
+ * The resultant converted data and the status is returned in the DrmConvertedInfo
+ * object. This method will be called each time there are new block
+ * of data received by the application.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] convertId Handle for the convert session
+ * @param[in] inputData Input Data which need to be converted
+ * @return Return object contains the status of the data conversion,
+ * the output converted data and offset. In this case the
+ * application will ignore the offset information.
+ */
+ DrmConvertedStatus* convertData(int uniqueId, int convertId, const DrmBuffer* inputData);
+
+ /**
+ * Informs the Drm Agent when there is no more data which need to be converted
+ * or when an error occurs. Upon successful conversion of the complete data,
+ * the agent will inform that where the header and body signature
+ * should be added. This signature appending is needed to integrity
+ * protect the converted file.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] convertId Handle for the convert session
+ * @return Return object contains the status of the data conversion,
+ * the header and body signature data. It also informs
+ * the application on which offset these signature data
+ * should be appended.
+ */
+ DrmConvertedStatus* closeConvertSession(int uniqueId, int convertId);
+
+ /**
+ * Retrieves all DrmSupportInfo instance that native DRM framework can handle.
+ * This interface is meant to be used by JNI layer
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[out] length Number of elements in drmSupportInfoArray
+ * @param[out] drmSupportInfoArray Array contains all DrmSupportInfo
+ * that native DRM framework can handle
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ status_t getAllSupportInfo(int uniqueId, int* length, DrmSupportInfo** drmSupportInfoArray);
+
+ /**
+ * Open the decrypt session to decrypt the given protected content
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] fd File descriptor of the protected content to be decrypted
+ * @param[in] offset Start position of the content
+ * @param[in] length The length of the protected content
+ * @return
+ * Handle for the decryption session
+ */
+ DecryptHandle* openDecryptSession(int uniqueId, int fd, int offset, int length);
+
+ /**
+ * Close the decrypt session for the given handle
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptHandle Handle for the decryption session
+ */
+ void closeDecryptSession(int uniqueId, DecryptHandle* decryptHandle);
+
+ /**
+ * Initialize decryption for the given unit of the protected content
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptHandle Handle for the decryption session
+ * @param[in] decryptUnitId ID which specifies decryption unit, such as track ID
+ * @param[in] headerInfo Information for initializing decryption of this decrypUnit
+ */
+ void initializeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle,
+ int decryptUnitId, const DrmBuffer* headerInfo);
+
+ /**
+ * Decrypt the protected content buffers for the given unit
+ * This method will be called any number of times, based on number of
+ * encrypted streams received from application.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptHandle Handle for the decryption session
+ * @param[in] decryptUnitId ID which specifies decryption unit, such as track ID
+ * @param[in] encBuffer Encrypted data block
+ * @param[out] decBuffer Decrypted data block
+ * @return status_t
+ * Returns the error code for this API
+ * DRM_NO_ERROR for success, and one of DRM_ERROR_UNKNOWN, DRM_ERROR_LICENSE_EXPIRED
+ * DRM_ERROR_SESSION_NOT_OPENED, DRM_ERROR_DECRYPT_UNIT_NOT_INITIALIZED,
+ * DRM_ERROR_DECRYPT for failure.
+ */
+ status_t decrypt(int uniqueId, DecryptHandle* decryptHandle,
+ int decryptUnitId, const DrmBuffer* encBuffer, DrmBuffer** decBuffer);
+
+ /**
+ * Finalize decryption for the given unit of the protected content
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptHandle Handle for the decryption session
+ * @param[in] decryptUnitId ID which specifies decryption unit, such as track ID
+ */
+ void finalizeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId);
+
+ /**
+ * Reads the specified number of bytes from an open DRM file.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptHandle Handle for the decryption session
+ * @param[out] buffer Reference to the buffer that should receive the read data.
+ * @param[in] numBytes Number of bytes to read.
+ * @param[in] offset Offset with which to update the file position.
+ *
+ * @return Number of bytes read. Returns -1 for Failure.
+ */
+ ssize_t pread(int uniqueId, DecryptHandle* decryptHandle,
+ void* buffer, ssize_t numBytes, off_t offset);
+
+ /**
+ * Notify the event to the registered listener
+ *
+ * @param[in] event The event to be notified
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ status_t notify(const DrmInfoEvent& event);
+
+private:
+ /**
+ * Initialize DRM Manager
+ * load available plug-ins from plugInDirPath
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] plugInDirPath Directory from where to load plug-ins
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ status_t loadPlugIns(int uniqueId, const String8& plugInDirPath);
+
+ /**
+ * Install new DRM Engine Plug-in at the runtime
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] drmEngine Shared Object(so) File in which DRM Engine defined
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ status_t installDrmEngine(int uniqueId, const String8& drmEngineFile);
+
+private:
+ Mutex mLock;
+ sp<DrmManagerClient::OnInfoListener> mOnInfoListener;
+
+private:
+ static Mutex mMutex;
+ static Vector<int> mUniqueIdVector;
+ static sp<IDrmManagerService> mDrmManagerService;
+ static const sp<IDrmManagerService>& getDrmManagerService();
+ static const String8 EMPTY_STRING;
+};
+
+};
+
+#endif /* __DRM_MANAGER_CLIENT_IMPL_H__ */
+
diff --git a/drm/libdrmframework/include/DrmManagerService.h b/drm/libdrmframework/include/DrmManagerService.h
new file mode 100644
index 0000000..fef121c
--- /dev/null
+++ b/drm/libdrmframework/include/DrmManagerService.h
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#ifndef __DRM_MANAGER_SERVICE_H__
+#define __DRM_MANAGER_SERVICE_H__
+
+#include <utils/RefBase.h>
+#include <utils/KeyedVector.h>
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
+#include "IDrmManagerService.h"
+#include "IDrmServiceListener.h"
+
+namespace android {
+
+class DrmManager;
+class String8;
+class Mutex;
+
+/**
+ * This is the implementation class for DRM manager service. This delegates
+ * the responsibility to DrmManager.
+ *
+ * The instance of this class is created while starting the DRM manager service.
+ *
+ */
+class DrmManagerService : public BnDrmManagerService {
+public:
+ static void instantiate();
+
+private:
+ DrmManagerService();
+ virtual ~DrmManagerService();
+
+public:
+ status_t loadPlugIns(int uniqueId);
+
+ status_t loadPlugIns(int uniqueId, const String8& plugInDirPath);
+
+ status_t setDrmServiceListener(
+ int uniqueId, const sp<IDrmServiceListener>& drmServiceListener);
+
+ status_t unloadPlugIns(int uniqueId);
+
+ status_t installDrmEngine(int uniqueId, const String8& drmEngineFile);
+
+ DrmConstraints* getConstraints(int uniqueId, const String8* path, const int action);
+
+ bool canHandle(int uniqueId, const String8& path, const String8& mimeType);
+
+ DrmInfoStatus* processDrmInfo(int uniqueId, const DrmInfo* drmInfo);
+
+ DrmInfo* acquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInforequest);
+
+ void saveRights(int uniqueId, const DrmRights& drmRights,
+ const String8& rightsPath, const String8& contentPath);
+
+ String8 getOriginalMimeType(int uniqueId, const String8& path);
+
+ int getDrmObjectType(int uniqueId, const String8& path, const String8& mimeType);
+
+ int checkRightsStatus(int uniqueId, const String8& path,int action);
+
+ void consumeRights(int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve);
+
+ void setPlaybackStatus(
+ int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int position);
+
+ bool validateAction(int uniqueId, const String8& path,
+ int action, const ActionDescription& description);
+
+ void removeRights(int uniqueId, const String8& path);
+
+ void removeAllRights(int uniqueId);
+
+ int openConvertSession(int uniqueId, const String8& mimeType);
+
+ DrmConvertedStatus* convertData(int uniqueId, int convertId, const DrmBuffer* inputData);
+
+ DrmConvertedStatus* closeConvertSession(int uniqueId, int convertId);
+
+ status_t getAllSupportInfo(int uniqueId, int* length, DrmSupportInfo** drmSupportInfoArray);
+
+ DecryptHandle* openDecryptSession(int uniqueId, int fd, int offset, int length);
+
+ void closeDecryptSession(int uniqueId, DecryptHandle* decryptHandle);
+
+ void initializeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle,
+ int decryptUnitId, const DrmBuffer* headerInfo);
+
+ status_t decrypt(int uniqueId, DecryptHandle* decryptHandle,
+ int decryptUnitId, const DrmBuffer* encBuffer, DrmBuffer** decBuffer);
+
+ void finalizeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId);
+
+ ssize_t pread(int uniqueId, DecryptHandle* decryptHandle,
+ void* buffer, ssize_t numBytes, off_t offset);
+
+private:
+ DrmManager* mDrmManager;
+};
+
+};
+
+#endif /* __DRM_MANAGER_SERVICE_H__ */
+
diff --git a/drm/libdrmframework/include/IDrmIOService.h b/drm/libdrmframework/include/IDrmIOService.h
new file mode 100644
index 0000000..5e0d907
--- /dev/null
+++ b/drm/libdrmframework/include/IDrmIOService.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#ifndef __IDRM_IO_SERVICE_H__
+#define __IDRM_IO_SERVICE_H__
+
+#include <utils/RefBase.h>
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
+
+namespace android {
+
+/**
+ * This is the interface class for DRM IO service.
+ *
+ */
+class IDrmIOService : public IInterface
+{
+public:
+ enum {
+ WRITE_TO_FILE = IBinder::FIRST_CALL_TRANSACTION,
+ READ_FROM_FILE
+ };
+
+public:
+ DECLARE_META_INTERFACE(DrmIOService);
+
+public:
+ /**
+ * Writes the data into the file path provided
+ *
+ * @param[in] filePath Path of the file
+ * @param[in] dataBuffer Data to write
+ */
+ virtual void writeToFile(const String8& filePath, const String8& dataBuffer) = 0;
+
+ /**
+ * Reads the data from the file path provided
+ *
+ * @param[in] filePath Path of the file
+ * @return Data read from the file
+ */
+ virtual String8 readFromFile(const String8& filePath) = 0;
+};
+
+/**
+ * This is the Binder implementation class for DRM IO service.
+ */
+class BpDrmIOService: public BpInterface<IDrmIOService>
+{
+public:
+ BpDrmIOService(const sp<IBinder>& impl)
+ : BpInterface<IDrmIOService>(impl) {}
+
+ virtual void writeToFile(const String8& filePath, const String8& dataBuffer);
+
+ virtual String8 readFromFile(const String8& filePath);
+};
+
+/**
+ * This is the Binder implementation class for DRM IO service.
+ */
+class BnDrmIOService: public BnInterface<IDrmIOService>
+{
+public:
+ virtual status_t onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0);
+};
+
+};
+
+#endif /* __IDRM_IO_SERVICE_H__ */
+
diff --git a/drm/libdrmframework/include/IDrmManagerService.h b/drm/libdrmframework/include/IDrmManagerService.h
new file mode 100644
index 0000000..a4d128a
--- /dev/null
+++ b/drm/libdrmframework/include/IDrmManagerService.h
@@ -0,0 +1,242 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#ifndef __IDRM_MANAGER_SERVICE_H__
+#define __IDRM_MANAGER_SERVICE_H__
+
+#include <utils/RefBase.h>
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
+#include <drm/drm_framework_common.h>
+#include "IDrmServiceListener.h"
+
+namespace android {
+
+class DrmContentIds;
+class DrmConstraints;
+class DrmRights;
+class DrmInfo;
+class DrmInfoStatus;
+class DrmInfoRequest;
+class DrmSupportInfo;
+class DrmConvertedStatus;
+class String8;
+class ActionDescription;
+
+/**
+ * This is the interface class for DRM Manager service.
+ *
+ */
+class IDrmManagerService : public IInterface
+{
+public:
+ enum {
+ LOAD_PLUGINS = IBinder::FIRST_CALL_TRANSACTION,
+ LOAD_PLUGINS_FROM_PATH,
+ SET_DRM_SERVICE_LISTENER,
+ UNLOAD_PLUGINS,
+ INSTALL_DRM_ENGINE,
+ GET_CONSTRAINTS_FROM_CONTENT,
+ CAN_HANDLE,
+ PROCESS_DRM_INFO,
+ ACQUIRE_DRM_INFO,
+ SAVE_RIGHTS,
+ GET_ORIGINAL_MIMETYPE,
+ GET_DRM_OBJECT_TYPE,
+ CHECK_RIGHTS_STATUS,
+ CONSUME_RIGHTS,
+ SET_PLAYBACK_STATUS,
+ VALIDATE_ACTION,
+ REMOVE_RIGHTS,
+ REMOVE_ALL_RIGHTS,
+ OPEN_CONVERT_SESSION,
+ CONVERT_DATA,
+ CLOSE_CONVERT_SESSION,
+ GET_ALL_SUPPORT_INFO,
+ OPEN_DECRYPT_SESSION,
+ CLOSE_DECRYPT_SESSION,
+ INITIALIZE_DECRYPT_UNIT,
+ DECRYPT,
+ FINALIZE_DECRYPT_UNIT,
+ PREAD
+ };
+
+public:
+ DECLARE_META_INTERFACE(DrmManagerService);
+
+public:
+ virtual status_t loadPlugIns(int uniqueId) = 0;
+
+ virtual status_t loadPlugIns(int uniqueId, const String8& plugInDirPath) = 0;
+
+ virtual status_t setDrmServiceListener(
+ int uniqueId, const sp<IDrmServiceListener>& infoListener) = 0;
+
+ virtual status_t unloadPlugIns(int uniqueId) = 0;
+
+ virtual status_t installDrmEngine(int uniqueId, const String8& drmEngineFile) = 0;
+
+ virtual DrmConstraints* getConstraints(
+ int uniqueId, const String8* path, const int action) = 0;
+
+ virtual bool canHandle(int uniqueId, const String8& path, const String8& mimeType) = 0;
+
+ virtual DrmInfoStatus* processDrmInfo(int uniqueId, const DrmInfo* drmInfo) = 0;
+
+ virtual DrmInfo* acquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInforequest) = 0;
+
+ virtual void saveRights(int uniqueId, const DrmRights& drmRights,
+ const String8& rightsPath, const String8& contentPath) = 0;
+
+ virtual String8 getOriginalMimeType(int uniqueId, const String8& path) = 0;
+
+ virtual int getDrmObjectType(
+ int uniqueId, const String8& path, const String8& mimeType) = 0;
+
+ virtual int checkRightsStatus(int uniqueId, const String8& path, int action) = 0;
+
+ virtual void consumeRights(
+ int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve) = 0;
+
+ virtual void setPlaybackStatus(
+ int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int position) = 0;
+
+ virtual bool validateAction(
+ int uniqueId, const String8& path,
+ int action, const ActionDescription& description) = 0;
+
+ virtual void removeRights(int uniqueId, const String8& path) = 0;
+
+ virtual void removeAllRights(int uniqueId) = 0;
+
+ virtual int openConvertSession(int uniqueId, const String8& mimeType) = 0;
+
+ virtual DrmConvertedStatus* convertData(
+ int uniqueId, int convertId, const DrmBuffer* inputData) = 0;
+
+ virtual DrmConvertedStatus* closeConvertSession(int uniqueId, int convertId) = 0;
+
+ virtual status_t getAllSupportInfo(
+ int uniqueId, int* length, DrmSupportInfo** drmSupportInfoArray) = 0;
+
+ virtual DecryptHandle* openDecryptSession(int uniqueId, int fd, int offset, int length) = 0;
+
+ virtual void closeDecryptSession(int uniqueId, DecryptHandle* decryptHandle) = 0;
+
+ virtual void initializeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle,
+ int decryptUnitId, const DrmBuffer* headerInfo) = 0;
+
+ virtual status_t decrypt(int uniqueId, DecryptHandle* decryptHandle,
+ int decryptUnitId, const DrmBuffer* encBuffer, DrmBuffer** decBuffer) = 0;
+
+ virtual void finalizeDecryptUnit(
+ int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId) = 0;
+
+ virtual ssize_t pread(int uniqueId, DecryptHandle* decryptHandle,
+ void* buffer, ssize_t numBytes,off_t offset) = 0;
+};
+
+/**
+ * This is the Binder implementation class for DRM Manager service.
+ */
+class BpDrmManagerService: public BpInterface<IDrmManagerService>
+{
+public:
+ BpDrmManagerService(const sp<IBinder>& impl)
+ : BpInterface<IDrmManagerService>(impl) {}
+
+ virtual status_t loadPlugIns(int uniqueId);
+
+ virtual status_t loadPlugIns(int uniqueId, const String8& plugInDirPath);
+
+ virtual status_t setDrmServiceListener(
+ int uniqueId, const sp<IDrmServiceListener>& infoListener);
+
+ virtual status_t unloadPlugIns(int uniqueId);
+
+ virtual status_t installDrmEngine(int uniqueId, const String8& drmEngineFile);
+
+ virtual DrmConstraints* getConstraints(int uniqueId, const String8* path, const int action);
+
+ virtual bool canHandle(int uniqueId, const String8& path, const String8& mimeType);
+
+ virtual DrmInfoStatus* processDrmInfo(int uniqueId, const DrmInfo* drmInfo);
+
+ virtual DrmInfo* acquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInforequest);
+
+ virtual void saveRights(int uniqueId, const DrmRights& drmRights,
+ const String8& rightsPath, const String8& contentPath);
+
+ virtual String8 getOriginalMimeType(int uniqueId, const String8& path);
+
+ virtual int getDrmObjectType(int uniqueId, const String8& path, const String8& mimeType);
+
+ virtual int checkRightsStatus(int uniqueId, const String8& path, int action);
+
+ virtual void consumeRights(
+ int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve);
+
+ virtual void setPlaybackStatus(
+ int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int position);
+
+ virtual bool validateAction(
+ int uniqueId, const String8& path, int action, const ActionDescription& description);
+
+ virtual void removeRights(int uniqueId, const String8& path);
+
+ virtual void removeAllRights(int uniqueId);
+
+ virtual int openConvertSession(int uniqueId, const String8& mimeType);
+
+ virtual DrmConvertedStatus* convertData(
+ int uniqueId, int convertId, const DrmBuffer* inputData);
+
+ virtual DrmConvertedStatus* closeConvertSession(int uniqueId, int convertId);
+
+ virtual status_t getAllSupportInfo(
+ int uniqueId, int* length, DrmSupportInfo** drmSupportInfoArray);
+
+ virtual DecryptHandle* openDecryptSession(int uniqueId, int fd, int offset, int length);
+
+ virtual void closeDecryptSession(int uniqueId, DecryptHandle* decryptHandle);
+
+ virtual void initializeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle,
+ int decryptUnitId, const DrmBuffer* headerInfo);
+
+ virtual status_t decrypt(int uniqueId, DecryptHandle* decryptHandle,
+ int decryptUnitId, const DrmBuffer* encBuffer, DrmBuffer** decBuffer);
+
+ virtual void finalizeDecryptUnit(
+ int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId);
+
+ virtual ssize_t pread(int uniqueId, DecryptHandle* decryptHandle,
+ void* buffer, ssize_t numBytes, off_t offset);
+};
+
+/**
+ * This is the Binder implementation class for DRM Manager service.
+ */
+class BnDrmManagerService: public BnInterface<IDrmManagerService>
+{
+public:
+ virtual status_t onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0);
+};
+
+};
+
+#endif /* __IDRM_MANAGER_SERVICE_H__ */
+
diff --git a/drm/libdrmframework/include/IDrmServiceListener.h b/drm/libdrmframework/include/IDrmServiceListener.h
new file mode 100644
index 0000000..7f7109f
--- /dev/null
+++ b/drm/libdrmframework/include/IDrmServiceListener.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#ifndef __IDRM_SERVICE_LISTENER_H__
+#define __IDRM_SERVICE_LISTENER_H__
+
+#include <utils/RefBase.h>
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
+
+namespace android {
+
+class DrmInfoEvent;
+
+/**
+ * This is the interface class for DRM service listener.
+ *
+ */
+class IDrmServiceListener : public IInterface
+{
+public:
+ enum {
+ NOTIFY = IBinder::FIRST_CALL_TRANSACTION,
+ };
+
+public:
+ DECLARE_META_INTERFACE(DrmServiceListener);
+
+public:
+ virtual status_t notify(const DrmInfoEvent& event) = 0;
+};
+
+/**
+ * This is the Binder implementation class for DRM service listener.
+ */
+class BpDrmServiceListener: public BpInterface<IDrmServiceListener>
+{
+public:
+ BpDrmServiceListener(const sp<IBinder>& impl)
+ : BpInterface<IDrmServiceListener>(impl) {}
+
+ virtual status_t notify(const DrmInfoEvent& event);
+};
+
+/**
+ * This is the Binder implementation class for DRM service listener.
+ */
+class BnDrmServiceListener: public BnInterface<IDrmServiceListener>
+{
+public:
+ virtual status_t onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0);
+};
+
+};
+
+#endif /* __IDRM_SERVICE_LISTENER_H__ */
+
diff --git a/drm/libdrmframework/include/PlugInManager.h b/drm/libdrmframework/include/PlugInManager.h
new file mode 100644
index 0000000..9ad195f
--- /dev/null
+++ b/drm/libdrmframework/include/PlugInManager.h
@@ -0,0 +1,273 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#ifndef __PLUGIN_MANAGER_H__
+#define __PLUGIN_MANAGER_H__
+
+#include <dlfcn.h>
+#include <sys/types.h>
+#include <dirent.h>
+
+#include <utils/String8.h>
+#include <utils/Vector.h>
+#include <utils/KeyedVector.h>
+
+namespace android {
+
+const char* const PLUGIN_MANAGER_CREATE = "create";
+const char* const PLUGIN_MANAGER_DESTROY = "destroy";
+const char* const PLUGIN_EXTENSION = ".so";
+
+/**
+ * This is the template class for Plugin manager.
+ *
+ * The DrmManager uses this class to handle the plugins.
+ *
+ */
+template<typename Type>
+class TPlugInManager {
+private:
+ typedef void* HANDLE;
+ typedef Type* create_t(void);
+ typedef void destroy_t(Type*);
+ typedef create_t* FPCREATE;
+ typedef destroy_t* FPDESTORY;
+
+ typedef struct _PlugInContainer {
+ String8 sPath;
+ HANDLE hHandle;
+ FPCREATE fpCreate;
+ FPDESTORY fpDestory;
+ Type* pInstance;
+
+ _PlugInContainer():
+ sPath("")
+ ,hHandle(NULL)
+ ,fpCreate(NULL)
+ ,fpDestory(NULL)
+ ,pInstance(NULL)
+ {}
+ } PlugInContainer;
+
+ typedef KeyedVector<String8, PlugInContainer*> PlugInMap;
+ PlugInMap m_plugInMap;
+
+ typedef Vector<String8> PlugInIdList;
+ PlugInIdList m_plugInIdList;
+
+public:
+ /**
+ * Load all the plug-ins in the specified directory
+ *
+ * @param[in] rsPlugInDirPath
+ * Directory path which plug-ins (dynamic library) are stored
+ * @note Plug-ins should be implemented according to the specification
+ */
+ void loadPlugIns(const String8& rsPlugInDirPath) {
+ Vector<String8> plugInFileList = getPlugInPathList(rsPlugInDirPath);
+
+ if (!plugInFileList.isEmpty()) {
+ for (unsigned int i = 0; i < plugInFileList.size(); ++i) {
+ loadPlugIn(plugInFileList[i]);
+ }
+ }
+ }
+
+ /**
+ * Unload all the plug-ins
+ *
+ */
+ void unloadPlugIns() {
+ for (unsigned int i = 0; i < m_plugInIdList.size(); ++i) {
+ unloadPlugIn(m_plugInIdList[i]);
+ }
+ m_plugInIdList.clear();
+ }
+
+ /**
+ * Get all the IDs of available plug-ins
+ *
+ * @return[in] plugInIdList
+ * String type Vector in which all plug-in IDs are stored
+ */
+ Vector<String8> getPlugInIdList() const {
+ return m_plugInIdList;
+ }
+
+ /**
+ * Get a plug-in reference of specified ID
+ *
+ * @param[in] rsPlugInId
+ * Plug-in ID to be used
+ * @return plugIn
+ * Reference of specified plug-in instance
+ */
+ Type& getPlugIn(const String8& rsPlugInId) {
+ if (!contains(rsPlugInId)) {
+ // This error case never happens
+ }
+ return *(m_plugInMap.valueFor(rsPlugInId)->pInstance);
+ }
+
+public:
+ /**
+ * Load a plug-in stored in the specified path
+ *
+ * @param[in] rsPlugInPath
+ * Plug-in (dynamic library) file path
+ * @note Plug-in should be implemented according to the specification
+ */
+ void loadPlugIn(const String8& rsPlugInPath) {
+ if (contains(rsPlugInPath)) {
+ return;
+ }
+
+ PlugInContainer* pPlugInContainer = new PlugInContainer();
+
+ pPlugInContainer->hHandle = dlopen(rsPlugInPath.string(), RTLD_LAZY);
+
+ if (NULL == pPlugInContainer->hHandle) {
+ delete pPlugInContainer;
+ pPlugInContainer = NULL;
+ return;
+ }
+
+ pPlugInContainer->sPath = rsPlugInPath;
+ pPlugInContainer->fpCreate
+ = (FPCREATE)dlsym(pPlugInContainer->hHandle, PLUGIN_MANAGER_CREATE);
+ pPlugInContainer->fpDestory
+ = (FPDESTORY)dlsym(pPlugInContainer->hHandle, PLUGIN_MANAGER_DESTROY);
+
+ if (NULL != pPlugInContainer->fpCreate && NULL != pPlugInContainer->fpDestory) {
+ pPlugInContainer->pInstance = (Type*)pPlugInContainer->fpCreate();
+ m_plugInIdList.add(rsPlugInPath);
+ m_plugInMap.add(rsPlugInPath, pPlugInContainer);
+ } else {
+ dlclose(pPlugInContainer->hHandle);
+ delete pPlugInContainer;
+ pPlugInContainer = NULL;
+ return;
+ }
+ }
+
+ /**
+ * Unload a plug-in stored in the specified path
+ *
+ * @param[in] rsPlugInPath
+ * Plug-in (dynamic library) file path
+ */
+ void unloadPlugIn(const String8& rsPlugInPath) {
+ if (!contains(rsPlugInPath)) {
+ return;
+ }
+
+ PlugInContainer* pPlugInContainer = m_plugInMap.valueFor(rsPlugInPath);
+ pPlugInContainer->fpDestory(pPlugInContainer->pInstance);
+ dlclose(pPlugInContainer->hHandle);
+
+ m_plugInMap.removeItem(rsPlugInPath);
+ delete pPlugInContainer;
+ pPlugInContainer = NULL;
+ }
+
+private:
+ /**
+ * True if TPlugInManager contains rsPlugInId
+ */
+ bool contains(const String8& rsPlugInId) {
+ return m_plugInMap.indexOfKey(rsPlugInId) != NAME_NOT_FOUND;
+ }
+
+ /**
+ * Return file path list of plug-ins stored in the specified directory
+ *
+ * @param[in] rsDirPath
+ * Directory path in which plug-ins are stored
+ * @return plugInFileList
+ * String type Vector in which file path of plug-ins are stored
+ */
+ Vector<String8> getPlugInPathList(const String8& rsDirPath) {
+ Vector<String8> fileList;
+ DIR* pDir = opendir(rsDirPath.string());
+ struct dirent* pEntry = new dirent();
+
+ while (NULL != pDir && NULL != (pEntry = readdir(pDir))) {
+ if (!isPlugIn(pEntry)) {
+ continue;
+ }
+ String8 plugInPath;
+ plugInPath += rsDirPath;
+ plugInPath += "/";
+ plugInPath += pEntry->d_name;
+
+ fileList.add(plugInPath);
+ }
+
+ if (NULL != pDir) {
+ closedir(pDir);
+ }
+ delete pEntry;
+ pEntry = NULL;
+
+ return fileList;
+ }
+
+ /**
+ * True if the input name denotes plug-in
+ */
+ bool isPlugIn(const struct dirent* pEntry) const {
+ String8 sName(pEntry->d_name);
+ int extentionPos = sName.size() - String8(PLUGIN_EXTENSION).size();
+ if (extentionPos < 0) {
+ return false;
+ }
+ return extentionPos == (int)sName.find(PLUGIN_EXTENSION);
+ }
+
+ /**
+ * True if the input entry is "." or ".."
+ */
+ bool isDotOrDDot(const struct dirent* pEntry) const {
+ String8 sName(pEntry->d_name);
+ return "." == sName || ".." == sName;
+ }
+
+ /**
+ * True if input entry is directory
+ */
+ bool isDirectory(const struct dirent* pEntry) const {
+ return DT_DIR == pEntry->d_type;
+ }
+
+ /**
+ * True if input entry is regular file
+ */
+ bool isRegularFile(const struct dirent* pEntry) const {
+ return DT_REG == pEntry->d_type;
+ }
+
+ /**
+ * True if input entry is link
+ */
+ bool isLink(const struct dirent* pEntry) const {
+ return DT_LNK == pEntry->d_type;
+ }
+};
+
+};
+
+#endif /* __PLUGIN_MANAGER_H__ */
+
diff --git a/drm/libdrmframework/include/ReadWriteUtils.h b/drm/libdrmframework/include/ReadWriteUtils.h
new file mode 100644
index 0000000..022149e
--- /dev/null
+++ b/drm/libdrmframework/include/ReadWriteUtils.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#ifndef __READ_WRITE_UTILS_H__
+#define __READ_WRITE_UTILS_H__
+
+#include <utils/FileMap.h>
+#include <drm/drm_framework_common.h>
+
+namespace android {
+
+/**
+ * This is an utility class which performs IO operations.
+ *
+ */
+class ReadWriteUtils {
+public:
+ /**
+ * Constructor for ReadWriteUtils
+ */
+ ReadWriteUtils() {}
+
+ /**
+ * Destructor for ReadWriteUtils
+ */
+ virtual ~ReadWriteUtils();
+
+public:
+ /**
+ * Reads the data from the file path provided
+ *
+ * @param[in] filePath Path of the file
+ * @return Data read from the file
+ */
+ static String8 readBytes(const String8& filePath);
+ /**
+ * Writes the data into the file path provided
+ *
+ * @param[in] filePath Path of the file
+ * @param[in] dataBuffer Data to write
+ */
+ static void writeToFile(const String8& filePath, const String8& data);
+ /**
+ * Appends the data into the file path provided
+ *
+ * @param[in] filePath Path of the file
+ * @param[in] dataBuffer Data to append
+ */
+ static void appendToFile(const String8& filePath, const String8& data);
+
+private:
+ FileMap* mFileMap;
+};
+
+};
+
+#endif /* __READ_WRITE_UTILS_H__ */
+
diff --git a/drm/libdrmframework/include/StringTokenizer.h b/drm/libdrmframework/include/StringTokenizer.h
new file mode 100644
index 0000000..70e7558
--- /dev/null
+++ b/drm/libdrmframework/include/StringTokenizer.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#ifndef __STRING_TOKENIZER_H__
+#define __STRING_TOKENIZER_H__
+
+#include <drm/drm_framework_common.h>
+
+namespace android {
+
+/**
+ * This is an utility class for String manipulation.
+ *
+ */
+class StringTokenizer {
+public:
+ /**
+ * Iterator for string tokens
+ */
+ class Iterator {
+ friend class StringTokenizer;
+ private:
+ Iterator(StringTokenizer* StringTokenizer)
+ : mStringTokenizer(StringTokenizer), mIndex(0) {}
+
+ public:
+ Iterator(const Iterator& iterator);
+ Iterator& operator=(const Iterator& iterator);
+ virtual ~Iterator() {}
+
+ public:
+ bool hasNext();
+ String8& next();
+
+ private:
+ StringTokenizer* mStringTokenizer;
+ unsigned int mIndex;
+ };
+
+public:
+ /**
+ * Constructor for StringTokenizer
+ *
+ * @param[in] string Complete string data
+ * @param[in] delimeter Delimeter used to split the string
+ */
+ StringTokenizer(const String8& string, const String8& delimeter);
+
+ /**
+ * Destructor for StringTokenizer
+ */
+ ~StringTokenizer() {}
+
+private:
+ /**
+ * Splits the string according to the delimeter
+ */
+ void splitString(const String8& string, const String8& delimeter);
+
+public:
+ /**
+ * Returns Iterator object to walk through the split string values
+ *
+ * @return Iterator object
+ */
+ Iterator iterator();
+
+private:
+ Vector<String8> mStringTokenizerVector;
+};
+
+};
+#endif /* __STRING_TOKENIZER_H__ */
+
diff --git a/drm/libdrmframework/plugins/Android.mk b/drm/libdrmframework/plugins/Android.mk
new file mode 100644
index 0000000..9ee7961
--- /dev/null
+++ b/drm/libdrmframework/plugins/Android.mk
@@ -0,0 +1,16 @@
+#
+# Copyright (C) 2010 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.
+#
+include $(call all-subdir-makefiles)
diff --git a/drm/libdrmframework/plugins/common/include/DrmEngineBase.h b/drm/libdrmframework/plugins/common/include/DrmEngineBase.h
new file mode 100644
index 0000000..667958a
--- /dev/null
+++ b/drm/libdrmframework/plugins/common/include/DrmEngineBase.h
@@ -0,0 +1,411 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#ifndef __DRM_ENGINE_BASE_H__
+#define __DRM_ENGINE_BASE_H__
+
+#include <drm/drm_framework_common.h>
+#include "IDrmEngine.h"
+
+namespace android {
+
+/**
+ * This class is an interface for plug-in developers
+ *
+ * Responsibility of this class is control the sequence of actual plug-in.
+ * All each plug-in developer has to do is implement onXXX() type virtual interfaces.
+ */
+class DrmEngineBase : public IDrmEngine {
+public:
+ DrmEngineBase();
+ virtual ~DrmEngineBase();
+
+public:
+ DrmConstraints* getConstraints(int uniqueId, const String8* path, int action);
+
+ status_t initialize(int uniqueId);
+
+ status_t setOnInfoListener(int uniqueId, const IDrmEngine::OnInfoListener* infoListener);
+
+ status_t terminate(int uniqueId);
+
+ bool canHandle(int uniqueId, const String8& path);
+
+ DrmInfoStatus* processDrmInfo(int uniqueId, const DrmInfo* drmInfo);
+
+ void saveRights(int uniqueId, const DrmRights& drmRights,
+ const String8& rightsPath, const String8& contentPath);
+
+ DrmInfo* acquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInfoRequest);
+
+ String8 getOriginalMimeType(int uniqueId, const String8& path);
+
+ int getDrmObjectType(int uniqueId, const String8& path, const String8& mimeType);
+
+ int checkRightsStatus(int uniqueId, const String8& path, int action);
+
+ void consumeRights(int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve);
+
+ void setPlaybackStatus(
+ int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int position);
+
+ bool validateAction(
+ int uniqueId, const String8& path, int action, const ActionDescription& description);
+
+ void removeRights(int uniqueId, const String8& path);
+
+ void removeAllRights(int uniqueId);
+
+ void openConvertSession(int uniqueId, int convertId);
+
+ DrmConvertedStatus* convertData(int uniqueId, int convertId, const DrmBuffer* inputData);
+
+ DrmConvertedStatus* closeConvertSession(int uniqueId, int convertId);
+
+ DrmSupportInfo* getSupportInfo(int uniqueId);
+
+ status_t openDecryptSession(
+ int uniqueId, DecryptHandle* decryptHandle, int fd, int offset, int length);
+
+ void closeDecryptSession(int uniqueId, DecryptHandle* decryptHandle);
+
+ void initializeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle,
+ int decryptUnitId, const DrmBuffer* headerInfo);
+
+ status_t decrypt(int uniqueId, DecryptHandle* decryptHandle,
+ int decryptUnitId, const DrmBuffer* encBuffer, DrmBuffer** decBuffer);
+
+ void finalizeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId);
+
+ ssize_t pread(int uniqueId, DecryptHandle* decryptHandle,
+ void* buffer, ssize_t numBytes, off_t offset);
+
+protected:
+ /////////////////////////////////////////////////////
+ // Interface for plug-in developers //
+ // each plug-in has to implement following method //
+ /////////////////////////////////////////////////////
+ /**
+ * Get constraint information associated with input content
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] path Path of the protected content
+ * @param[in] action Actions defined such as,
+ * Action::DEFAULT, Action::PLAY, etc
+ * @return DrmConstraints
+ * key-value pairs of constraint are embedded in it
+ * @note
+ * In case of error, return NULL
+ */
+ virtual DrmConstraints* onGetConstraints(
+ int uniqueId, const String8* path, int action) = 0;
+
+ /**
+ * Initialize plug-in
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ virtual status_t onInitialize(int uniqueId) = 0;
+
+ /**
+ * Register a callback to be invoked when the caller required to
+ * receive necessary information
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] infoListener Listener
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ virtual status_t onSetOnInfoListener(
+ int uniqueId, const IDrmEngine::OnInfoListener* infoListener) = 0;
+
+ /**
+ * Terminate the plug-in
+ * and release resource bound to plug-in
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ virtual status_t onTerminate(int uniqueId) = 0;
+
+ /**
+ * Get whether the given content can be handled by this plugin or not
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] path Path the protected object
+ * @return bool
+ * Returns true if this plugin can handle , false in case of not able to handle
+ */
+ virtual bool onCanHandle(int uniqueId, const String8& path) = 0;
+
+ /**
+ * Executes given drm information based on its type
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] drmInfo Information needs to be processed
+ * @return DrmInfoStatus
+ * instance as a result of processing given input
+ */
+ virtual DrmInfoStatus* onProcessDrmInfo(int uniqueId, const DrmInfo* drmInfo) = 0;
+
+ /**
+ * Save DRM rights to specified rights path
+ * and make association with content path
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] drmRights DrmRights to be saved
+ * @param[in] rightsPath File path where rights to be saved
+ * @param[in] contentPath File path where content was saved
+ */
+ virtual void onSaveRights(int uniqueId, const DrmRights& drmRights,
+ const String8& rightspath, const String8& contentPath) = 0;
+
+ /**
+ * Retrieves necessary information for registration, unregistration or rights
+ * acquisition information.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] drmInfoRequest Request information to retrieve drmInfo
+ * @return DrmInfo
+ * instance as a result of processing given input
+ */
+ virtual DrmInfo* onAcquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInforequest) = 0;
+
+ /**
+ * Retrieves the mime type embedded inside the original content
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] path Path of the protected content
+ * @return String8
+ * Returns mime-type of the original content, such as "video/mpeg"
+ */
+ virtual String8 onGetOriginalMimeType(int uniqueId, const String8& path) = 0;
+
+ /**
+ * Retrieves the type of the protected object (content, rights, etc..)
+ * using specified path or mimetype. At least one parameter should be non null
+ * to retrieve DRM object type
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] path Path of the content or null.
+ * @param[in] mimeType Mime type of the content or null.
+ * @return type of the DRM content,
+ * such as DrmObjectType::CONTENT, DrmObjectType::RIGHTS_OBJECT
+ */
+ virtual int onGetDrmObjectType(
+ int uniqueId, const String8& path, const String8& mimeType) = 0;
+
+ /**
+ * Check whether the given content has valid rights or not
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] path Path of the protected content
+ * @param[in] action Action to perform (Action::DEFAULT, Action::PLAY, etc)
+ * @return the status of the rights for the protected content,
+ * such as RightsStatus::RIGHTS_VALID, RightsStatus::RIGHTS_EXPIRED, etc.
+ */
+ virtual int onCheckRightsStatus(int uniqueId, const String8& path, int action) = 0;
+
+ /**
+ * Consumes the rights for a content.
+ * If the reserve parameter is true the rights is reserved until the same
+ * application calls this api again with the reserve parameter set to false.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptHandle Handle for the decryption session
+ * @param[in] action Action to perform. (Action::DEFAULT, Action::PLAY, etc)
+ * @param[in] reserve True if the rights should be reserved.
+ */
+ virtual void onConsumeRights(int uniqueId, DecryptHandle* decryptHandle,
+ int action, bool reserve) = 0;
+
+ /**
+ * Informs the DRM Engine about the playback actions performed on the DRM files.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptHandle Handle for the decryption session
+ * @param[in] playbackStatus Playback action (Playback::START, Playback::STOP, Playback::PAUSE)
+ * @param[in] position Position in the file (in milliseconds) where the start occurs.
+ * Only valid together with Playback::START.
+ */
+ virtual void onSetPlaybackStatus(
+ int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int position) = 0;
+
+ /**
+ * Validates whether an action on the DRM content is allowed or not.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] path Path of the protected content
+ * @param[in] action Action to validate (Action::PLAY, Action::TRANSFER, etc)
+ * @param[in] description Detailed description of the action
+ * @return true if the action is allowed.
+ */
+ virtual bool onValidateAction(int uniqueId, const String8& path,
+ int action, const ActionDescription& description) = 0;
+
+ /**
+ * Removes the rights associated with the given protected content
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] path Path of the protected content
+ */
+ virtual void onRemoveRights(int uniqueId, const String8& path) = 0;
+
+ /**
+ * Removes all the rights information of each plug-in associated with
+ * DRM framework. Will be used in master reset
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ */
+ virtual void onRemoveAllRights(int uniqueId) = 0;
+
+ /**
+ * This API is for Forward Lock based DRM scheme.
+ * Each time the application tries to download a new DRM file
+ * which needs to be converted, then the application has to
+ * begin with calling this API.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] convertId Handle for the convert session
+ */
+ virtual void onOpenConvertSession(int uniqueId, int convertId) = 0;
+
+ /**
+ * Accepts and converts the input data which is part of DRM file.
+ * The resultant converted data and the status is returned in the DrmConvertedInfo
+ * object. This method will be called each time there are new block
+ * of data received by the application.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] convertId Handle for the convert session
+ * @param[in] inputData Input Data which need to be converted
+ * @return Return object contains the status of the data conversion,
+ * the output converted data and offset. In this case the
+ * application will ignore the offset information.
+ */
+ virtual DrmConvertedStatus* onConvertData(
+ int uniqueId, int convertId, const DrmBuffer* inputData) = 0;
+
+ /**
+ * Informs the Drm Agent when there is no more data which need to be converted
+ * or when an error occurs. Upon successful conversion of the complete data,
+ * the agent will inform that where the header and body signature
+ * should be added. This signature appending is needed to integrity
+ * protect the converted file.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] convertId Handle for the convert session
+ * @return Return object contains the status of the data conversion,
+ * the header and body signature data. It also informs
+ * the application on which offset these signature data
+ * should be appended.
+ */
+ virtual DrmConvertedStatus* onCloseConvertSession(int uniqueId, int convertId) = 0;
+
+ /**
+ * Returns the information about the Drm Engine capabilities which includes
+ * supported MimeTypes and file suffixes.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @return DrmSupportInfo
+ * instance which holds the capabilities of a plug-in
+ */
+ virtual DrmSupportInfo* onGetSupportInfo(int uniqueId) = 0;
+
+ /**
+ * Open the decrypt session to decrypt the given protected content
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptHandle Handle for the current decryption session
+ * @param[in] fd File descriptor of the protected content to be decrypted
+ * @param[in] offset Start position of the content
+ * @param[in] length The length of the protected content
+ * @return
+ * DRM_ERROR_CANNOT_HANDLE for failure and DRM_NO_ERROR for success
+ */
+ virtual status_t onOpenDecryptSession(
+ int uniqueId, DecryptHandle* decryptHandle, int fd, int offset, int length) = 0;
+
+ /**
+ * Close the decrypt session for the given handle
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptHandle Handle for the decryption session
+ */
+ virtual void onCloseDecryptSession(int uniqueId, DecryptHandle* decryptHandle) = 0;
+
+ /**
+ * Initialize decryption for the given unit of the protected content
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptId Handle for the decryption session
+ * @param[in] decryptUnitId ID Specifies decryption unit, such as track ID
+ * @param[in] headerInfo Information for initializing decryption of this decrypUnit
+ */
+ virtual void onInitializeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle,
+ int decryptUnitId, const DrmBuffer* headerInfo) = 0;
+
+ /**
+ * Decrypt the protected content buffers for the given unit
+ * This method will be called any number of times, based on number of
+ * encrypted streams received from application.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptId Handle for the decryption session
+ * @param[in] decryptUnitId ID Specifies decryption unit, such as track ID
+ * @param[in] encBuffer Encrypted data block
+ * @param[out] decBuffer Decrypted data block
+ * @return status_t
+ * Returns the error code for this API
+ * DRM_NO_ERROR for success, and one of DRM_ERROR_UNKNOWN, DRM_ERROR_LICENSE_EXPIRED
+ * DRM_ERROR_SESSION_NOT_OPENED, DRM_ERROR_DECRYPT_UNIT_NOT_INITIALIZED,
+ * DRM_ERROR_DECRYPT for failure.
+ */
+ virtual status_t onDecrypt(int uniqueId, DecryptHandle* decryptHandle,
+ int decryptUnitId, const DrmBuffer* encBuffer, DrmBuffer** decBuffer) = 0;
+
+ /**
+ * Finalize decryption for the given unit of the protected content
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptHandle Handle for the decryption session
+ * @param[in] decryptUnitId ID Specifies decryption unit, such as track ID
+ */
+ virtual void onFinalizeDecryptUnit(
+ int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId) = 0;
+
+ /**
+ * Reads the specified number of bytes from an open DRM file.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptHandle Handle for the decryption session
+ * @param[out] buffer Reference to the buffer that should receive the read data.
+ * @param[in] numBytes Number of bytes to read.
+ * @param[in] offset Offset with which to update the file position.
+ *
+ * @return Number of bytes read. Returns -1 for Failure.
+ */
+ virtual ssize_t onPread(int uniqueId, DecryptHandle* decryptHandle,
+ void* buffer, ssize_t numBytes, off_t offset) = 0;
+};
+
+};
+
+#endif /* __DRM_ENGINE_BASE_H__ */
+
diff --git a/drm/libdrmframework/plugins/common/include/IDrmEngine.h b/drm/libdrmframework/plugins/common/include/IDrmEngine.h
new file mode 100644
index 0000000..0d52f66
--- /dev/null
+++ b/drm/libdrmframework/plugins/common/include/IDrmEngine.h
@@ -0,0 +1,371 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#ifndef __IDRM_ENGINE_H__
+#define __IDRM_ENGINE_H__
+
+#include <drm/drm_framework_common.h>
+
+namespace android {
+
+class DrmContentIds;
+class DrmConstraints;
+class DrmRights;
+class DrmInfo;
+class DrmInfoStatus;
+class DrmConvertedStatus;
+class DrmInfoRequest;
+class DrmSupportInfo;
+class DrmInfoEvent;
+
+/**
+ * This class is an interface for plug-in user
+ *
+ * Responsibility of this class is provide generic interface to DRM Engine Manager.
+ * Each interface need to be as abstract as possible.
+ */
+class IDrmEngine {
+public:
+ virtual ~IDrmEngine() {
+ }
+
+public:
+ class OnInfoListener {
+
+ public:
+ virtual void onInfo(const DrmInfoEvent& event) = 0;
+
+ virtual ~OnInfoListener() { }
+ };
+
+public:
+
+ //////////////////////////////////
+ // Implementation of IDrmEngine //
+ //////////////////////////////////
+
+ /**
+ * Initialize plug-in
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ virtual status_t initialize(int uniqueId) = 0;
+
+ /**
+ * Register a callback to be invoked when the caller required to
+ * receive necessary information
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] infoListener Listener
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ virtual status_t setOnInfoListener(
+ int uniqueId, const IDrmEngine::OnInfoListener* infoListener) = 0;
+
+ /**
+ * Terminate the plug-in
+ * and release resource bound to plug-in
+ * e.g.) release native resource
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ virtual status_t terminate(int uniqueId) = 0;
+
+ /**
+ * Get constraint information associated with input content
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] path Path of the protected content
+ * @param[in] action Actions defined such as,
+ * Action::DEFAULT, Action::PLAY, etc
+ * @return DrmConstraints
+ * key-value pairs of constraint are embedded in it
+ * @note
+ * In case of error, return NULL
+ */
+ virtual DrmConstraints* getConstraints(
+ int uniqueId, const String8* path, int action) = 0;
+
+ /**
+ * Get whether the given content can be handled by this plugin or not
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] path Path the protected object
+ * @return bool
+ * true if this plugin can handle , false in case of not able to handle
+ */
+ virtual bool canHandle(int uniqueId, const String8& path) = 0;
+
+ /**
+ * Executes given drm information based on its type
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] drmInfo Information needs to be processed
+ * @return DrmInfoStatus
+ * instance as a result of processing given input
+ */
+ virtual DrmInfoStatus* processDrmInfo(int uniqueId, const DrmInfo* drmInfo) = 0;
+
+ /**
+ * Retrieves necessary information for registration, unregistration or rights
+ * acquisition information.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] drmInfoRequest Request information to retrieve drmInfo
+ * @return DrmInfo
+ * instance as a result of processing given input
+ */
+ virtual DrmInfo* acquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInfoRequest) = 0;
+
+ /**
+ * Save DRM rights to specified rights path
+ * and make association with content path
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] drmRights DrmRights to be saved
+ * @param[in] rightsPath File path where rights to be saved
+ * @param[in] contentPath File path where content was saved
+ */
+ virtual void saveRights(int uniqueId, const DrmRights& drmRights,
+ const String8& rightsPath, const String8& contentPath) = 0;
+
+ /**
+ * Retrieves the mime type embedded inside the original content
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] path Path of the protected content
+ * @return String8
+ * Returns mime-type of the original content, such as "video/mpeg"
+ */
+ virtual String8 getOriginalMimeType(int uniqueId, const String8& path) = 0;
+
+ /**
+ * Retrieves the type of the protected object (content, rights, etc..)
+ * using specified path or mimetype. At least one parameter should be non null
+ * to retrieve DRM object type
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] path Path of the content or null.
+ * @param[in] mimeType Mime type of the content or null.
+ * @return type of the DRM content,
+ * such as DrmObjectType::CONTENT, DrmObjectType::RIGHTS_OBJECT
+ */
+ virtual int getDrmObjectType(
+ int uniqueId, const String8& path, const String8& mimeType) = 0;
+
+ /**
+ * Check whether the given content has valid rights or not
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] path Path of the protected content
+ * @param[in] action Action to perform (Action::DEFAULT, Action::PLAY, etc)
+ * @return the status of the rights for the protected content,
+ * such as RightsStatus::RIGHTS_VALID, RightsStatus::RIGHTS_EXPIRED, etc.
+ */
+ virtual int checkRightsStatus(int uniqueId, const String8& path, int action) = 0;
+
+ /**
+ * Consumes the rights for a content.
+ * If the reserve parameter is true the rights is reserved until the same
+ * application calls this api again with the reserve parameter set to false.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptHandle Handle for the decryption session
+ * @param[in] action Action to perform. (Action::DEFAULT, Action::PLAY, etc)
+ * @param[in] reserve True if the rights should be reserved.
+ */
+ virtual void consumeRights(
+ int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve) = 0;
+
+ /**
+ * Informs the DRM Engine about the playback actions performed on the DRM files.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptHandle Handle for the decryption session
+ * @param[in] playbackStatus Playback action (Playback::START, Playback::STOP, Playback::PAUSE)
+ * @param[in] position Position in the file (in milliseconds) where the start occurs.
+ * Only valid together with Playback::START.
+ */
+ virtual void setPlaybackStatus(int uniqueId, DecryptHandle* decryptHandle,
+ int playbackStatus, int position) = 0;
+
+ /**
+ * Validates whether an action on the DRM content is allowed or not.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] path Path of the protected content
+ * @param[in] action Action to validate (Action::PLAY, Action::TRANSFER, etc)
+ * @param[in] description Detailed description of the action
+ * @return true if the action is allowed.
+ */
+ virtual bool validateAction(int uniqueId, const String8& path,
+ int action, const ActionDescription& description) = 0;
+
+ /**
+ * Removes the rights associated with the given protected content
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] path Path of the protected content
+ */
+ virtual void removeRights(int uniqueId, const String8& path) = 0;
+
+ /**
+ * Removes all the rights information of each plug-in associated with
+ * DRM framework. Will be used in master reset
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ */
+ virtual void removeAllRights(int uniqueId) = 0;
+
+ /**
+ * This API is for Forward Lock based DRM scheme.
+ * Each time the application tries to download a new DRM file
+ * which needs to be converted, then the application has to
+ * begin with calling this API.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] convertId Handle for the convert session
+ */
+ virtual void openConvertSession(int uniqueId, int convertId) = 0;
+
+ /**
+ * Accepts and converts the input data which is part of DRM file.
+ * The resultant converted data and the status is returned in the DrmConvertedInfo
+ * object. This method will be called each time there are new block
+ * of data received by the application.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] convertId Handle for the convert session
+ * @param[in] inputData Input Data which need to be converted
+ * @return Return object contains the status of the data conversion,
+ * the output converted data and offset. In this case the
+ * application will ignore the offset information.
+ */
+ virtual DrmConvertedStatus* convertData(
+ int uniqueId, int convertId, const DrmBuffer* inputData) = 0;
+
+ /**
+ * Informs the Drm Agent when there is no more data which need to be converted
+ * or when an error occurs. Upon successful conversion of the complete data,
+ * the agent will inform that where the header and body signature
+ * should be added. This signature appending is needed to integrity
+ * protect the converted file.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] convertId Handle for the convert session
+ * @return Return object contains the status of the data conversion,
+ * the header and body signature data. It also informs
+ * the application on which offset these signature data
+ * should be appended.
+ */
+ virtual DrmConvertedStatus* closeConvertSession( int uniqueId, int convertId) = 0;
+
+ /**
+ * Returns the information about the Drm Engine capabilities which includes
+ * supported MimeTypes and file suffixes.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @return DrmSupportInfo
+ * instance which holds the capabilities of a plug-in
+ */
+ virtual DrmSupportInfo* getSupportInfo(int uniqueId) = 0;
+
+ /**
+ * Open the decrypt session to decrypt the given protected content
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptHandle Handle for the current decryption session
+ * @param[in] fd File descriptor of the protected content to be decrypted
+ * @param[in] offset Start position of the content
+ * @param[in] length The length of the protected content
+ * @return
+ * DRM_ERROR_CANNOT_HANDLE for failure and DRM_NO_ERROR for success
+ */
+ virtual status_t openDecryptSession(
+ int uniqueId, DecryptHandle* decryptHandle, int fd, int offset, int length) = 0;
+
+ /**
+ * Close the decrypt session for the given handle
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptHandle Handle for the decryption session
+ */
+ virtual void closeDecryptSession(int uniqueId, DecryptHandle* decryptHandle) = 0;
+
+ /**
+ * Initialize decryption for the given unit of the protected content
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptHandle Handle for the decryption session
+ * @param[in] decryptUnitId ID which specifies decryption unit, such as track ID
+ * @param[in] headerInfo Information for initializing decryption of this decrypUnit
+ */
+ virtual void initializeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle,
+ int decryptUnitId, const DrmBuffer* headerInfo) = 0;
+
+ /**
+ * Decrypt the protected content buffers for the given unit
+ * This method will be called any number of times, based on number of
+ * encrypted streams received from application.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptHandle Handle for the decryption session
+ * @param[in] decryptUnitId ID which specifies decryption unit, such as track ID
+ * @param[in] encBuffer Encrypted data block
+ * @param[out] decBuffer Decrypted data block
+ * @return status_t
+ * Returns the error code for this API
+ * DRM_NO_ERROR for success, and one of DRM_ERROR_UNKNOWN, DRM_ERROR_LICENSE_EXPIRED
+ * DRM_ERROR_SESSION_NOT_OPENED, DRM_ERROR_DECRYPT_UNIT_NOT_INITIALIZED,
+ * DRM_ERROR_DECRYPT for failure.
+ */
+ virtual status_t decrypt(int uniqueId, DecryptHandle* decryptHandle,
+ int decryptUnitId, const DrmBuffer* encBuffer, DrmBuffer** decBuffer) = 0;
+
+ /**
+ * Finalize decryption for the given unit of the protected content
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptHandle Handle for the decryption session
+ * @param[in] decryptUnitId ID which specifies decryption unit, such as track ID
+ */
+ virtual void finalizeDecryptUnit(
+ int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId) = 0;
+
+ /**
+ * Reads the specified number of bytes from an open DRM file.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptHandle Handle for the decryption session
+ * @param[out] buffer Reference to the buffer that should receive the read data.
+ * @param[in] numBytes Number of bytes to read.
+ * @param[in] offset Offset with which to update the file position.
+ *
+ * @return Number of bytes read. Returns -1 for Failure.
+ */
+ virtual ssize_t pread(int uniqueId, DecryptHandle* decryptHandle,
+ void* buffer, ssize_t numBytes, off_t offset) = 0;
+};
+
+};
+
+#endif /* __IDRM_ENGINE_H__ */
+
diff --git a/drm/libdrmframework/plugins/passthru/Android.mk b/drm/libdrmframework/plugins/passthru/Android.mk
new file mode 100644
index 0000000..a7bbf23
--- /dev/null
+++ b/drm/libdrmframework/plugins/passthru/Android.mk
@@ -0,0 +1,44 @@
+#
+# Copyright (C) 2010 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.
+#
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ src/DrmPassthruPlugIn.cpp
+
+LOCAL_MODULE := libdrmpassthruplugin
+
+LOCAL_STATIC_LIBRARIES := libdrmframeworkcommon
+
+LOCAL_SHARED_LIBRARIES := \
+ libutils \
+ libdl
+
+LOCAL_PRELINK_MODULE := false
+
+LOCAL_C_INCLUDES += \
+ $(TOP)/frameworks/base/drm/libdrmframework/include \
+ $(TOP)/frameworks/base/drm/libdrmframework/plugins/passthru/include \
+ $(TOP)/frameworks/base/drm/libdrmframework/plugins/common/include \
+ $(TOP)/frameworks/base/include
+
+# Set the following flag to enable the decryption passthru flow
+#LOCAL_CFLAGS += -DENABLE_PASSTHRU_DECRYPTION
+
+PRODUCT_COPY_FILES += \
+ $(TARGET_OUT_SHARED_LIBRARIES)/libdrmpassthruplugin.so:system/lib/drm/plugins/native/libdrmpassthruplugin.so
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/drm/libdrmframework/plugins/passthru/include/DrmPassthruPlugIn.h b/drm/libdrmframework/plugins/passthru/include/DrmPassthruPlugIn.h
new file mode 100644
index 0000000..d2c7852
--- /dev/null
+++ b/drm/libdrmframework/plugins/passthru/include/DrmPassthruPlugIn.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#ifndef __DRM_PASSTHRU_PLUGIN_H__
+#define __DRM_PASSTHRU_PLUGIN_H__
+
+#include <DrmEngineBase.h>
+
+namespace android {
+
+class DrmPassthruPlugIn : public DrmEngineBase {
+
+public:
+ DrmPassthruPlugIn();
+ virtual ~DrmPassthruPlugIn();
+
+protected:
+ DrmConstraints* onGetConstraints(int uniqueId, const String8* path, int action);
+
+ status_t onInitialize(int uniqueId);
+
+ status_t onSetOnInfoListener(int uniqueId, const IDrmEngine::OnInfoListener* infoListener);
+
+ status_t onTerminate(int uniqueId);
+
+ bool onCanHandle(int uniqueId, const String8& path);
+
+ DrmInfoStatus* onProcessDrmInfo(int uniqueId, const DrmInfo* drmInfo);
+
+ void onSaveRights(int uniqueId, const DrmRights& drmRights,
+ const String8& rightsPath, const String8& contentPath);
+
+ DrmInfo* onAcquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInfoRequest);
+
+ String8 onGetOriginalMimeType(int uniqueId, const String8& path);
+
+ int onGetDrmObjectType(int uniqueId, const String8& path, const String8& mimeType);
+
+ int onCheckRightsStatus(int uniqueId, const String8& path, int action);
+
+ void onConsumeRights(int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve);
+
+ void onSetPlaybackStatus(
+ int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int position);
+
+ bool onValidateAction(
+ int uniqueId, const String8& path, int action, const ActionDescription& description);
+
+ void onRemoveRights(int uniqueId, const String8& path);
+
+ void onRemoveAllRights(int uniqueId);
+
+ void onOpenConvertSession(int uniqueId, int convertId);
+
+ DrmConvertedStatus* onConvertData(int uniqueId, int convertId, const DrmBuffer* inputData);
+
+ DrmConvertedStatus* onCloseConvertSession(int uniqueId, int convertId);
+
+ DrmSupportInfo* onGetSupportInfo(int uniqueId);
+
+ status_t onOpenDecryptSession(
+ int uniqueId, DecryptHandle* decryptHandle, int fd, int offset, int length);
+
+ void onCloseDecryptSession(int uniqueId, DecryptHandle* decryptHandle);
+
+ void onInitializeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle,
+ int decryptUnitId, const DrmBuffer* headerInfo);
+
+ status_t onDecrypt(int uniqueId, DecryptHandle* decryptHandle,
+ int decryptUnitId, const DrmBuffer* encBuffer, DrmBuffer** decBuffer);
+
+ void onFinalizeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId);
+
+ ssize_t onPread(int uniqueId, DecryptHandle* decryptHandle,
+ void* buffer, ssize_t numBytes, off_t offset);
+
+private:
+ DecryptHandle* openDecryptSessionImpl();
+};
+
+};
+
+#endif /* __DRM_PASSTHRU_PLUGIN_H__ */
+
diff --git a/drm/libdrmframework/plugins/passthru/src/DrmPassthruPlugIn.cpp b/drm/libdrmframework/plugins/passthru/src/DrmPassthruPlugIn.cpp
new file mode 100644
index 0000000..2655d0b
--- /dev/null
+++ b/drm/libdrmframework/plugins/passthru/src/DrmPassthruPlugIn.cpp
@@ -0,0 +1,280 @@
+/*
+ * Copyright (C) 2010 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 "DrmPassthruPlugIn"
+#include <utils/Log.h>
+
+#include <drm/DrmRights.h>
+#include <drm/DrmConstraints.h>
+#include <drm/DrmInfo.h>
+#include <drm/DrmInfoEvent.h>
+#include <drm/DrmInfoStatus.h>
+#include <drm/DrmConvertedStatus.h>
+#include <drm/DrmInfoRequest.h>
+#include <drm/DrmSupportInfo.h>
+#include <DrmPassthruPlugIn.h>
+
+using namespace android;
+
+
+// This extern "C" is mandatory to be managed by TPlugInManager
+extern "C" IDrmEngine* create() {
+ return new DrmPassthruPlugIn();
+}
+
+// This extern "C" is mandatory to be managed by TPlugInManager
+extern "C" void destroy(IDrmEngine* pPlugIn) {
+ delete pPlugIn;
+ pPlugIn = NULL;
+}
+
+DrmPassthruPlugIn::DrmPassthruPlugIn()
+ : DrmEngineBase() {
+
+}
+
+DrmPassthruPlugIn::~DrmPassthruPlugIn() {
+
+}
+
+DrmConstraints* DrmPassthruPlugIn::onGetConstraints(
+ int uniqueId, const String8* path, int action) {
+ LOGD("DrmPassthruPlugIn::onGetConstraints From Path: %d", uniqueId);
+ DrmConstraints* drmConstraints = new DrmConstraints();
+
+ String8 value("dummy_available_time");
+ char* charValue = NULL;
+ charValue = new char[value.length() + 1];
+ strncpy(charValue, value.string(), value.length());
+
+ //Just add dummy available time for verification
+ drmConstraints->put(&(DrmConstraints::LICENSE_AVAILABLE_TIME), charValue);
+
+ return drmConstraints;
+}
+
+DrmInfoStatus* DrmPassthruPlugIn::onProcessDrmInfo(int uniqueId, const DrmInfo* drmInfo) {
+ LOGD("DrmPassthruPlugIn::onProcessDrmInfo - Enter : %d", uniqueId);
+ DrmInfoStatus* drmInfoStatus = NULL;
+ if (NULL != drmInfo) {
+ switch (drmInfo->getInfoType()) {
+ case DrmInfoRequest::TYPE_REGISTRATION_INFO: {
+ const DrmBuffer* emptyBuffer = new DrmBuffer();
+ drmInfoStatus
+ = new DrmInfoStatus(DrmInfoStatus::STATUS_OK, emptyBuffer, drmInfo->getMimeType());
+ break;
+ }
+ case DrmInfoRequest::TYPE_UNREGISTRATION_INFO: {
+ const DrmBuffer* emptyBuffer = new DrmBuffer();
+ drmInfoStatus
+ = new DrmInfoStatus(DrmInfoStatus::STATUS_OK, emptyBuffer, drmInfo->getMimeType());
+ break;
+ }
+ case DrmInfoRequest::TYPE_RIGHTS_ACQUISITION_INFO: {
+ String8 licenseString("dummy_license_string");
+ const int bufferSize = licenseString.size();
+ char* data = NULL;
+ data = new char[bufferSize];
+ memcpy(data, licenseString.string(), bufferSize);
+ const DrmBuffer* buffer = new DrmBuffer(data, bufferSize);
+ drmInfoStatus
+ = new DrmInfoStatus(DrmInfoStatus::STATUS_OK, buffer, drmInfo->getMimeType());
+ break;
+ }
+ }
+ }
+ LOGD("DrmPassthruPlugIn::onProcessDrmInfo - Exit");
+ return drmInfoStatus;
+}
+
+status_t DrmPassthruPlugIn::onSetOnInfoListener(
+ int uniqueId, const IDrmEngine::OnInfoListener* infoListener) {
+ LOGD("DrmPassthruPlugIn::onSetOnInfoListener : %d", uniqueId);
+ return DRM_NO_ERROR;
+}
+
+status_t DrmPassthruPlugIn::onInitialize(int uniqueId) {
+ LOGD("DrmPassthruPlugIn::onInitialize : %d", uniqueId);
+ return DRM_NO_ERROR;
+}
+
+status_t DrmPassthruPlugIn::onTerminate(int uniqueId) {
+ LOGD("DrmPassthruPlugIn::onTerminate : %d", uniqueId);
+ return DRM_NO_ERROR;
+}
+
+DrmSupportInfo* DrmPassthruPlugIn::onGetSupportInfo(int uniqueId) {
+ LOGD("DrmPassthruPlugIn::onGetSupportInfo : %d", uniqueId);
+ DrmSupportInfo* drmSupportInfo = new DrmSupportInfo();
+ // Add mimetype's
+ drmSupportInfo->addMimeType(String8("application/vnd.passthru.drm"));
+ // Add File Suffixes
+ drmSupportInfo->addFileSuffix(String8(".passthru"));
+ // Add plug-in description
+ drmSupportInfo->setDescription(String8("Passthru plug-in"));
+ return drmSupportInfo;
+}
+
+void DrmPassthruPlugIn::onSaveRights(int uniqueId, const DrmRights& drmRights,
+ const String8& rightsPath, const String8& contentPath) {
+ LOGD("DrmPassthruPlugIn::onSaveRights : %d", uniqueId);
+}
+
+DrmInfo* DrmPassthruPlugIn::onAcquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInfoRequest) {
+ LOGD("DrmPassthruPlugIn::onAcquireDrmInfo : %d", uniqueId);
+ DrmInfo* drmInfo = NULL;
+
+ if (NULL != drmInfoRequest) {
+ String8 dataString("dummy_acquistion_string");
+ int length = dataString.length();
+ char* data = NULL;
+ data = new char[length];
+ memcpy(data, dataString.string(), length);
+ drmInfo = new DrmInfo(drmInfoRequest->getInfoType(),
+ DrmBuffer(data, length), drmInfoRequest->getMimeType());
+ }
+ return drmInfo;
+}
+
+bool DrmPassthruPlugIn::onCanHandle(int uniqueId, const String8& path) {
+ LOGD("DrmPassthruPlugIn::canHandle: %s ", path.string());
+ String8 extension = path.getPathExtension();
+ extension.toLower();
+ return (String8(".passthru") == extension);
+}
+
+String8 DrmPassthruPlugIn::onGetOriginalMimeType(int uniqueId, const String8& path) {
+ LOGD("DrmPassthruPlugIn::onGetOriginalMimeType() : %d", uniqueId);
+ return String8("video/passthru");
+}
+
+int DrmPassthruPlugIn::onGetDrmObjectType(
+ int uniqueId, const String8& path, const String8& mimeType) {
+ LOGD("DrmPassthruPlugIn::onGetDrmObjectType() : %d", uniqueId);
+ return DrmObjectType::UNKNOWN;
+}
+
+int DrmPassthruPlugIn::onCheckRightsStatus(int uniqueId, const String8& path, int action) {
+ LOGD("DrmPassthruPlugIn::onCheckRightsStatus() : %d", uniqueId);
+ int rightsStatus = RightsStatus::RIGHTS_VALID;
+ return rightsStatus;
+}
+
+void DrmPassthruPlugIn::onConsumeRights(int uniqueId, DecryptHandle* decryptHandle,
+ int action, bool reserve) {
+ LOGD("DrmPassthruPlugIn::onConsumeRights() : %d", uniqueId);
+}
+
+void DrmPassthruPlugIn::onSetPlaybackStatus(int uniqueId, DecryptHandle* decryptHandle,
+ int playbackStatus, int position) {
+ LOGD("DrmPassthruPlugIn::onSetPlaybackStatus() : %d", uniqueId);
+}
+
+bool DrmPassthruPlugIn::onValidateAction(int uniqueId, const String8& path,
+ int action, const ActionDescription& description) {
+ LOGD("DrmPassthruPlugIn::onValidateAction() : %d", uniqueId);
+ return true;
+}
+
+void DrmPassthruPlugIn::onRemoveRights(int uniqueId, const String8& path) {
+ LOGD("DrmPassthruPlugIn::onRemoveRights() : %d", uniqueId);
+}
+
+void DrmPassthruPlugIn::onRemoveAllRights(int uniqueId) {
+ LOGD("DrmPassthruPlugIn::onRemoveAllRights() : %d", uniqueId);
+}
+
+void DrmPassthruPlugIn::onOpenConvertSession(int uniqueId, int convertId) {
+ LOGD("DrmPassthruPlugIn::onOpenConvertSession() : %d", uniqueId);
+}
+
+DrmConvertedStatus* DrmPassthruPlugIn::onConvertData(
+ int uniqueId, int convertId, const DrmBuffer* inputData) {
+ LOGD("DrmPassthruPlugIn::onConvertData() : %d", uniqueId);
+ DrmBuffer* convertedData = NULL;
+
+ if (NULL != inputData && 0 < inputData->length) {
+ int length = inputData->length;
+ char* data = NULL;
+ data = new char[length];
+ convertedData = new DrmBuffer(data, length);
+ memcpy(convertedData->data, inputData->data, length);
+ }
+ return new DrmConvertedStatus(DrmConvertedStatus::STATUS_OK, convertedData, 0 /*offset*/);
+}
+
+DrmConvertedStatus* DrmPassthruPlugIn::onCloseConvertSession(int uniqueId, int convertId) {
+ LOGD("DrmPassthruPlugIn::onCloseConvertSession() : %d", uniqueId);
+ return new DrmConvertedStatus(DrmConvertedStatus::STATUS_OK, NULL, 0 /*offset*/);
+}
+
+status_t DrmPassthruPlugIn::onOpenDecryptSession(
+ int uniqueId, DecryptHandle* decryptHandle, int fd, int offset, int length) {
+ LOGD("DrmPassthruPlugIn::onOpenDecryptSession() : %d", uniqueId);
+
+#ifdef ENABLE_PASSTHRU_DECRYPTION
+ decryptHandle->mimeType = String8("video/passthru");
+ decryptHandle->decryptApiType = DecryptApiType::ELEMENTARY_STREAM_BASED;
+ decryptHandle->status = DRM_NO_ERROR;
+ decryptHandle->decryptInfo = NULL;
+ return DRM_NO_ERROR;
+#endif
+
+ return DRM_ERROR_CANNOT_HANDLE;
+}
+
+void DrmPassthruPlugIn::onCloseDecryptSession(int uniqueId, DecryptHandle* decryptHandle) {
+ LOGD("DrmPassthruPlugIn::onCloseDecryptSession() : %d", uniqueId);
+ if (NULL != decryptHandle) {
+ if (NULL != decryptHandle->decryptInfo) {
+ delete decryptHandle->decryptInfo; decryptHandle->decryptInfo = NULL;
+ }
+ delete decryptHandle; decryptHandle = NULL;
+ }
+}
+
+void DrmPassthruPlugIn::onInitializeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle,
+ int decryptUnitId, const DrmBuffer* headerInfo) {
+ LOGD("DrmPassthruPlugIn::onInitializeDecryptUnit() : %d", uniqueId);
+}
+
+status_t DrmPassthruPlugIn::onDecrypt(int uniqueId, DecryptHandle* decryptHandle,
+ int decryptUnitId, const DrmBuffer* encBuffer, DrmBuffer** decBuffer) {
+ LOGD("DrmPassthruPlugIn::onDecrypt() : %d", uniqueId);
+ /**
+ * As a workaround implementation passthru would copy the given
+ * encrypted buffer as it is to decrypted buffer. Note, decBuffer
+ * memory has to be allocated by the caller.
+ */
+ if (NULL != (*decBuffer) && 0 < (*decBuffer)->length) {
+ memcpy((*decBuffer)->data, encBuffer->data, encBuffer->length);
+ (*decBuffer)->length = encBuffer->length;
+ }
+ return DRM_NO_ERROR;
+}
+
+void DrmPassthruPlugIn::onFinalizeDecryptUnit(
+ int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId) {
+ LOGD("DrmPassthruPlugIn::onFinalizeDecryptUnit() : %d", uniqueId);
+}
+
+ssize_t DrmPassthruPlugIn::onPread(int uniqueId, DecryptHandle* decryptHandle,
+ void* buffer, ssize_t numBytes, off_t offset) {
+ LOGD("DrmPassthruPlugIn::onPread() : %d", uniqueId);
+ return 0;
+}
+
diff --git a/include/drm/DrmConstraints.h b/include/drm/DrmConstraints.h
new file mode 100644
index 0000000..a9ec942
--- /dev/null
+++ b/include/drm/DrmConstraints.h
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#ifndef __DRM_CONSTRAINTS_H__
+#define __DRM_CONSTRAINTS_H__
+
+#include "drm_framework_common.h"
+
+namespace android {
+
+/**
+ * This is an utility class which contains the constraints information.
+ *
+ * As a result of DrmManagerClient::getConstraints(const String8*, const int)
+ * an instance of DrmConstraints would be returned.
+ *
+ */
+class DrmConstraints {
+public:
+ /**
+ * The following variables are replica of android.drm.DrmStore.ConstraintsColumns
+ * Any changes should also be incorporated with Java Layer as well
+ */
+ /**
+ * The max repeat count
+ */
+ static const String8 MAX_REPEAT_COUNT;
+ /**
+ * The remaining repeat count
+ */
+ static const String8 REMAINING_REPEAT_COUNT;
+
+ /**
+ * The time before which the protected file can not be played/viewed
+ */
+ static const String8 LICENSE_START_TIME;
+
+ /**
+ * The time after which the protected file can not be played/viewed
+ */
+ static const String8 LICENSE_EXPIRY_TIME;
+
+ /**
+ * The available time for license
+ */
+ static const String8 LICENSE_AVAILABLE_TIME;
+
+ /**
+ * The data stream for extended metadata
+ */
+ static const String8 EXTENDED_METADATA;
+
+public:
+ /**
+ * Iterator for key
+ */
+ class KeyIterator {
+ friend class DrmConstraints;
+ private:
+ KeyIterator(DrmConstraints* drmConstraints)
+ : mDrmConstraints(drmConstraints), mIndex(0) {}
+
+ public:
+ KeyIterator(const KeyIterator& keyIterator);
+ KeyIterator& operator=(const KeyIterator& keyIterator);
+ virtual ~KeyIterator() {}
+
+ public:
+ bool hasNext();
+ const String8& next();
+
+ private:
+ DrmConstraints* mDrmConstraints;
+ unsigned int mIndex;
+ };
+
+ /**
+ * Iterator for constraints
+ */
+ class Iterator {
+ friend class DrmConstraints;
+ private:
+ Iterator(DrmConstraints* drmConstraints)
+ : mDrmConstraints(drmConstraints), mIndex(0) {}
+
+ public:
+ Iterator(const Iterator& iterator);
+ Iterator& operator=(const Iterator& iterator);
+ virtual ~Iterator() {}
+
+ public:
+ bool hasNext();
+ String8 next();
+
+ private:
+ DrmConstraints* mDrmConstraints;
+ unsigned int mIndex;
+ };
+
+public:
+ DrmConstraints() {}
+ virtual ~DrmConstraints() {
+ DrmConstraints::KeyIterator keyIt = this->keyIterator();
+
+ while (keyIt.hasNext()) {
+ String8 key = keyIt.next();
+ const char* value = this->getAsByteArray(&key);
+ if (NULL != value) {
+ delete[] value;
+ value = NULL;
+ }
+ }
+ mConstraintMap.clear();
+ }
+public:
+ /**
+ * Returns the number of constraints contained in this instance
+ *
+ * @return Number of constraints
+ */
+ int getCount(void) const;
+
+ /**
+ * Adds constraint information as <key, value> pair to this instance
+ *
+ * @param[in] key Key to add
+ * @param[in] value Value to add
+ * @return Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ status_t put(const String8* key, const char* value);
+
+ /**
+ * Retrieves the value of given key
+ *
+ * @param key Key whose value to be retrieved
+ * @return The value
+ */
+ String8 get(const String8& key) const;
+
+ /**
+ * Retrieves the value as byte array of given key
+ * @param key Key whose value to be retrieved as byte array
+ * @return The byte array value
+ */
+ const char* getAsByteArray(const String8* key) const;
+
+ /**
+ * Returns KeyIterator object to walk through the keys associated with this instance
+ *
+ * @return KeyIterator object
+ */
+ KeyIterator keyIterator();
+
+ /**
+ * Returns Iterator object to walk through the values associated with this instance
+ *
+ * @return Iterator object
+ */
+ Iterator iterator();
+private:
+ const char* getValue(const String8* key) const;
+private:
+ typedef KeyedVector<String8, const char*> DrmConstraintsMap;
+ DrmConstraintsMap mConstraintMap;
+};
+
+};
+
+#endif /* __DRM_CONSTRAINTS_H__ */
+
diff --git a/include/drm/DrmConvertedStatus.h b/include/drm/DrmConvertedStatus.h
new file mode 100644
index 0000000..679e48d
--- /dev/null
+++ b/include/drm/DrmConvertedStatus.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#ifndef __DRM_CONVERTED_STATUS_H__
+#define __DRM_CONVERTED_STATUS_H__
+
+#include "drm_framework_common.h"
+
+namespace android {
+
+/**
+ * This is an utility class which wraps the status of the conversion, the converted
+ * data/checksum data and the offset. Offset is going to be used in the case of close
+ * session where the agent will inform where the header and body signature should be added
+ *
+ * As a result of DrmManagerClient::convertData(int, const DrmBuffer*) and
+ * DrmManagerClient::closeConvertSession(int) an instance of DrmConvertedStatus
+ * would be returned.
+ *
+ */
+class DrmConvertedStatus {
+public:
+ // Should be in sync with DrmConvertedStatus.java
+ static const int STATUS_OK = 1;
+ static const int STATUS_INPUTDATA_ERROR = 2;
+ static const int STATUS_ERROR = 3;
+
+public:
+ /**
+ * Constructor for DrmConvertedStatus
+ *
+ * @param[in] _statusCode Status of the conversion
+ * @param[in] _convertedData Converted data/checksum data
+ * @param[in] _offset Offset value
+ */
+ DrmConvertedStatus(int _statusCode, const DrmBuffer* _convertedData, int _offset);
+
+ /**
+ * Destructor for DrmConvertedStatus
+ */
+ virtual ~DrmConvertedStatus() {
+
+ }
+
+public:
+ int statusCode;
+ const DrmBuffer* convertedData;
+ int offset;
+};
+
+};
+
+#endif /* __DRM_CONVERTED_STATUS_H__ */
+
diff --git a/include/drm/DrmInfo.h b/include/drm/DrmInfo.h
new file mode 100644
index 0000000..7b48541
--- /dev/null
+++ b/include/drm/DrmInfo.h
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#ifndef __DRM_INFO_H__
+#define __DRM_INFO_H__
+
+#include "drm_framework_common.h"
+
+namespace android {
+
+/**
+ * This is an utility class in which necessary information required to transact
+ * between device and online DRM server is described. DRM Framework achieves
+ * server registration, license acquisition and any other server related transaction
+ * by passing an instance of this class to DrmManagerClient::processDrmInfo(const DrmInfo*).
+ *
+ * The Caller can retrieve the DrmInfo instance by using
+ * DrmManagerClient::acquireDrmInfo(const DrmInfoRequest*) by passing DrmInfoRequest instance.
+ *
+ */
+class DrmInfo {
+public:
+ /**
+ * Constructor for DrmInfo
+ *
+ * @param[in] infoType Type of information
+ * @param[in] drmBuffer Trigger data
+ * @param[in] mimeType MIME type
+ */
+ DrmInfo(int infoType, const DrmBuffer& drmBuffer, const String8& mimeType);
+
+ /**
+ * Destructor for DrmInfo
+ */
+ virtual ~DrmInfo() {}
+
+public:
+ /**
+ * Iterator for key
+ */
+ class KeyIterator {
+ friend class DrmInfo;
+
+ private:
+ KeyIterator(const DrmInfo* drmInfo)
+ : mDrmInfo(const_cast <DrmInfo*> (drmInfo)), mIndex(0) {}
+
+ public:
+ KeyIterator(const KeyIterator& keyIterator);
+ KeyIterator& operator=(const KeyIterator& keyIterator);
+ virtual ~KeyIterator() {}
+
+ public:
+ bool hasNext();
+ const String8& next();
+
+ private:
+ DrmInfo* mDrmInfo;
+ unsigned int mIndex;
+ };
+
+ /**
+ * Iterator
+ */
+ class Iterator {
+ friend class DrmInfo;
+
+ private:
+ Iterator(const DrmInfo* drmInfo)
+ : mDrmInfo(const_cast <DrmInfo*> (drmInfo)), mIndex(0) {}
+
+ public:
+ Iterator(const Iterator& iterator);
+ Iterator& operator=(const Iterator& iterator);
+ virtual ~Iterator() {}
+
+ public:
+ bool hasNext();
+ String8& next();
+
+ private:
+ DrmInfo* mDrmInfo;
+ unsigned int mIndex;
+ };
+
+public:
+ /**
+ * Returns information type associated with this instance
+ *
+ * @return Information type
+ */
+ int getInfoType(void) const;
+
+ /**
+ * Returns MIME type associated with this instance
+ *
+ * @return MIME type
+ */
+ String8 getMimeType(void) const;
+
+ /**
+ * Returns the trigger data associated with this instance
+ *
+ * @return Trigger data
+ */
+ const DrmBuffer& getData(void) const;
+
+ /**
+ * Returns the number of attributes contained in this instance
+ *
+ * @return Number of attributes
+ */
+ int getCount(void) const;
+
+ /**
+ * Adds optional information as <key, value> pair to this instance
+ *
+ * @param[in] key Key to add
+ * @param[in] value Value to add
+ * @return Returns the error code
+ */
+ status_t put(const String8& key, const String8& value);
+
+ /**
+ * Retrieves the value of given key
+ *
+ * @param key Key whose value to be retrieved
+ * @return The value
+ */
+ String8 get(const String8& key) const;
+
+ /**
+ * Returns KeyIterator object to walk through the keys associated with this instance
+ *
+ * @return KeyIterator object
+ */
+ KeyIterator keyIterator() const;
+
+ /**
+ * Returns Iterator object to walk through the values associated with this instance
+ *
+ * @return Iterator object
+ */
+ Iterator iterator() const;
+
+ /**
+ * Returns index of the given key
+ *
+ * @return index
+ */
+ int indexOfKey(const String8& key) const;
+
+protected:
+ int mInfoType;
+ DrmBuffer mData;
+ String8 mMimeType;
+ KeyedVector<String8, String8> mAttributes;
+};
+
+};
+
+#endif /* __DRM_INFO_H__ */
+
diff --git a/include/drm/DrmInfoEvent.h b/include/drm/DrmInfoEvent.h
new file mode 100644
index 0000000..5e8817c
--- /dev/null
+++ b/include/drm/DrmInfoEvent.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#ifndef __DRM_INFO_EVENT_H__
+#define __DRM_INFO_EVENT_H__
+
+namespace android {
+
+class String8;
+
+/**
+ * This is an entity class which would be passed to caller in
+ * DrmManagerClient::OnInfoListener::onInfo(const DrmInfoEvent&).
+ */
+class DrmInfoEvent {
+public:
+ //! TYPE_ALREADY_REGISTERED_BY_ANOTHER_ACCOUNT, when registration has been
+ //! already done by another account ID.
+ static const int TYPE_ALREADY_REGISTERED_BY_ANOTHER_ACCOUNT = 0x0000001;
+ //! TYPE_REMOVE_RIGHTS, when the rights needs to be removed completely.
+ static const int TYPE_REMOVE_RIGHTS = 0x0000002;
+ //! TYPE_RIGHTS_INSTALLED, when the rights are downloaded and installed ok.
+ static const int TYPE_RIGHTS_INSTALLED = 0x0000003;
+ //! TYPE_RIGHTS_NOT_INSTALLED, when something went wrong installing the rights
+ static const int TYPE_RIGHTS_NOT_INSTALLED = 0x0000004;
+ //! TYPE_RIGHTS_RENEWAL_NOT_ALLOWED, when the server rejects renewal of rights
+ static const int TYPE_RIGHTS_RENEWAL_NOT_ALLOWED = 0x0000005;
+ //! TYPE_NOT_SUPPORTED, when answer from server can not be handled by the native agent
+ static const int TYPE_NOT_SUPPORTED = 0x0000006;
+ //! TYPE_WAIT_FOR_RIGHTS, rights object is on it's way to phone,
+ //! wait before calling checkRights again
+ static const int TYPE_WAIT_FOR_RIGHTS = 0x0000007;
+ //! TYPE_OUT_OF_MEMORY, when memory allocation fail during renewal.
+ //! Can in the future perhaps be used to trigger garbage collector
+ static const int TYPE_OUT_OF_MEMORY = 0x0000008;
+ //! TYPE_NO_INTERNET_CONNECTION, when the Internet connection is missing and no attempt
+ //! can be made to renew rights
+ static const int TYPE_NO_INTERNET_CONNECTION = 0x0000009;
+
+public:
+ /**
+ * Constructor for DrmInfoEvent
+ *
+ * @param[in] uniqueId Unique session identifier
+ * @param[in] infoType Type of information
+ * @param[in] message Message description
+ */
+ DrmInfoEvent(int uniqueId, int infoType, const String8& message);
+
+ /**
+ * Destructor for DrmInfoEvent
+ */
+ virtual ~DrmInfoEvent() {}
+
+public:
+ /**
+ * Returns the Unique Id associated with this instance
+ *
+ * @return Unique Id
+ */
+ int getUniqueId() const;
+
+ /**
+ * Returns the Type of information associated with this object
+ *
+ * @return Type of information
+ */
+ int getType() const;
+
+ /**
+ * Returns the message description associated with this object
+ *
+ * @return Message description
+ */
+ const String8& getMessage() const;
+
+private:
+ int mUniqueId;
+ int mInfoType;
+ const String8& mMessage;
+};
+
+};
+
+#endif /* __DRM_INFO_EVENT_H__ */
+
diff --git a/include/drm/DrmInfoRequest.h b/include/drm/DrmInfoRequest.h
new file mode 100644
index 0000000..3e48ecc
--- /dev/null
+++ b/include/drm/DrmInfoRequest.h
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#ifndef __DRM_INFO_REQUEST_H__
+#define __DRM_INFO_REQUEST_H__
+
+#include "drm_framework_common.h"
+
+namespace android {
+
+/**
+ * This is an utility class used to pass required parameters to get
+ * the necessary information to communicate with online DRM server
+ *
+ * An instance of this class is passed to
+ * DrmManagerClient::acquireDrmInfo(const DrmInfoRequest*) to get the
+ * instance of DrmInfo.
+ *
+ */
+class DrmInfoRequest {
+public:
+ // Changes in following constants should be in sync with DrmInfoRequest.java
+ static const int TYPE_REGISTRATION_INFO = 1;
+ static const int TYPE_UNREGISTRATION_INFO = 2;
+ static const int TYPE_RIGHTS_ACQUISITION_INFO = 3;
+ static const int TYPE_RIGHTS_ACQUISITION_PROGRESS_INFO = 4;
+
+ /**
+ * Key to pass the unique id for the account or the user
+ */
+ static const String8 ACCOUNT_ID;
+ /**
+ * Key to pass the subscription id
+ */
+ static const String8 SUBSCRIPTION_ID;
+
+public:
+ /**
+ * Constructor for DrmInfoRequest
+ *
+ * @param[in] infoType Type of information
+ * @param[in] mimeType MIME type
+ */
+ DrmInfoRequest(int infoType, const String8& mimeType);
+
+ /**
+ * Destructor for DrmInfoRequest
+ */
+ virtual ~DrmInfoRequest() {}
+
+public:
+ /**
+ * Iterator for key
+ */
+ class KeyIterator {
+ friend class DrmInfoRequest;
+
+ private:
+ KeyIterator(const DrmInfoRequest* drmInfoRequest)
+ : mDrmInfoRequest(const_cast <DrmInfoRequest*> (drmInfoRequest)), mIndex(0) {}
+
+ public:
+ KeyIterator(const KeyIterator& keyIterator);
+ KeyIterator& operator=(const KeyIterator& keyIterator);
+ virtual ~KeyIterator() {}
+
+ public:
+ bool hasNext();
+ const String8& next();
+
+ private:
+ DrmInfoRequest* mDrmInfoRequest;
+ unsigned int mIndex;
+ };
+
+ /**
+ * Iterator
+ */
+ class Iterator {
+ friend class DrmInfoRequest;
+
+ private:
+ Iterator(const DrmInfoRequest* drmInfoRequest)
+ : mDrmInfoRequest(const_cast <DrmInfoRequest*> (drmInfoRequest)), mIndex(0) {}
+
+ public:
+ Iterator(const Iterator& iterator);
+ Iterator& operator=(const Iterator& iterator);
+ virtual ~Iterator() {}
+
+ public:
+ bool hasNext();
+ String8& next();
+
+ private:
+ DrmInfoRequest* mDrmInfoRequest;
+ unsigned int mIndex;
+ };
+
+public:
+ /**
+ * Returns information type associated with this instance
+ *
+ * @return Information type
+ */
+ int getInfoType(void) const;
+
+ /**
+ * Returns MIME type associated with this instance
+ *
+ * @return MIME type
+ */
+ String8 getMimeType(void) const;
+
+ /**
+ * Returns the number of entries in DrmRequestInfoMap
+ *
+ * @return Number of entries
+ */
+ int getCount(void) const;
+
+ /**
+ * Adds optional information as <key, value> pair to this instance
+ *
+ * @param[in] key Key to add
+ * @param[in] value Value to add
+ * @return Returns the error code
+ */
+ status_t put(const String8& key, const String8& value);
+
+ /**
+ * Retrieves the value of given key
+ *
+ * @param key Key whose value to be retrieved
+ * @return The value
+ */
+ String8 get(const String8& key) const;
+
+ /**
+ * Returns KeyIterator object to walk through the keys associated with this instance
+ *
+ * @return KeyIterator object
+ */
+ KeyIterator keyIterator() const;
+
+ /**
+ * Returns Iterator object to walk through the values associated with this instance
+ *
+ * @return Iterator object
+ */
+ Iterator iterator() const;
+
+private:
+ int mInfoType;
+ String8 mMimeType;
+
+ typedef KeyedVector<String8, String8> DrmRequestInfoMap;
+ DrmRequestInfoMap mRequestInformationMap;
+};
+
+};
+
+#endif /* __DRM_INFO_REQUEST_H__ */
+
diff --git a/include/drm/DrmInfoStatus.h b/include/drm/DrmInfoStatus.h
new file mode 100644
index 0000000..806aea1
--- /dev/null
+++ b/include/drm/DrmInfoStatus.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#ifndef __DRM_INFO_STATUS_H__
+#define __DRM_INFO_STATUS_H__
+
+#include "drm_framework_common.h"
+
+namespace android {
+
+/**
+ * This is an utility class which wraps the result of communication between device
+ * and online DRM server.
+ *
+ * As a result of DrmManagerClient::processDrmInfo(const DrmInfo*) an instance of
+ * DrmInfoStatus would be returned. This class holds DrmBuffer which could be
+ * used to instantiate DrmRights in license acquisition.
+ *
+ */
+class DrmInfoStatus {
+public:
+ // Should be in sync with DrmInfoStatus.java
+ static const int STATUS_OK = 1;
+ static const int STATUS_ERROR = 2;
+
+public:
+ /**
+ * Constructor for DrmInfoStatus
+ *
+ * @param[in] _statusCode Status of the communication
+ * @param[in] _drmBuffer Rights information
+ * @param[in] _mimeType MIME type
+ */
+ DrmInfoStatus(int _statusCode, const DrmBuffer* _drmBuffer, const String8& _mimeType);
+
+ /**
+ * Destructor for DrmInfoStatus
+ */
+ virtual ~DrmInfoStatus() {
+
+ }
+
+public:
+ int statusCode;
+ const DrmBuffer* drmBuffer;
+ String8 mimeType;
+};
+
+};
+
+#endif /* __DRM_INFO_STATUS_H__ */
+
diff --git a/include/drm/DrmManagerClient.h b/include/drm/DrmManagerClient.h
new file mode 100644
index 0000000..7d14c44
--- /dev/null
+++ b/include/drm/DrmManagerClient.h
@@ -0,0 +1,351 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#ifndef __DRM_MANAGER_CLIENT_H__
+#define __DRM_MANAGER_CLIENT_H__
+
+#include <binder/IInterface.h>
+#include "drm_framework_common.h"
+
+namespace android {
+
+class DrmInfo;
+class DrmRights;
+class DrmInfoEvent;
+class DrmInfoStatus;
+class DrmInfoRequest;
+class DrmSupportInfo;
+class DrmConstraints;
+class DrmConvertedStatus;
+class DrmManagerClientImpl;
+
+/**
+ * The Native application will instantiate this class and access DRM Framework
+ * services through this class.
+ *
+ */
+class DrmManagerClient {
+public:
+ DrmManagerClient();
+
+ virtual ~DrmManagerClient();
+
+public:
+ class OnInfoListener: virtual public RefBase {
+
+ public:
+ virtual void onInfo(const DrmInfoEvent& event) = 0;
+ };
+
+/**
+ * APIs which will be used by native modules (e.g. StageFright)
+ *
+ */
+public:
+ /**
+ * Open the decrypt session to decrypt the given protected content
+ *
+ * @param[in] fd File descriptor of the protected content to be decrypted
+ * @param[in] offset Start position of the content
+ * @param[in] length The length of the protected content
+ * @return
+ * Handle for the decryption session
+ */
+ DecryptHandle* openDecryptSession(int fd, int offset, int length);
+
+ /**
+ * Close the decrypt session for the given handle
+ *
+ * @param[in] decryptHandle Handle for the decryption session
+ */
+ void closeDecryptSession(DecryptHandle* decryptHandle);
+
+ /**
+ * Consumes the rights for a content.
+ * If the reserve parameter is true the rights is reserved until the same
+ * application calls this api again with the reserve parameter set to false.
+ *
+ * @param[in] decryptHandle Handle for the decryption session
+ * @param[in] action Action to perform. (Action::DEFAULT, Action::PLAY, etc)
+ * @param[in] reserve True if the rights should be reserved.
+ */
+ void consumeRights(DecryptHandle* decryptHandle, int action, bool reserve);
+
+ /**
+ * Informs the DRM engine about the playback actions performed on the DRM files.
+ *
+ * @param[in] decryptHandle Handle for the decryption session
+ * @param[in] playbackStatus Playback action (Playback::START, Playback::STOP, Playback::PAUSE)
+ * @param[in] position Position in the file (in milliseconds) where the start occurs.
+ * Only valid together with Playback::START.
+ */
+ void setPlaybackStatus(DecryptHandle* decryptHandle, int playbackStatus, int position);
+
+ /**
+ * Initialize decryption for the given unit of the protected content
+ *
+ * @param[in] decryptHandle Handle for the decryption session
+ * @param[in] decryptUnitId ID which specifies decryption unit, such as track ID
+ * @param[in] headerInfo Information for initializing decryption of this decrypUnit
+ */
+ void initializeDecryptUnit(
+ DecryptHandle* decryptHandle, int decryptUnitId, const DrmBuffer* headerInfo);
+
+ /**
+ * Decrypt the protected content buffers for the given unit
+ * This method will be called any number of times, based on number of
+ * encrypted streams received from application.
+ *
+ * @param[in] decryptHandle Handle for the decryption session
+ * @param[in] decryptUnitId ID which specifies decryption unit, such as track ID
+ * @param[in] encBuffer Encrypted data block
+ * @param[out] decBuffer Decrypted data block
+ * @return status_t
+ * Returns the error code for this API
+ * DRM_NO_ERROR for success, and one of DRM_ERROR_UNKNOWN, DRM_ERROR_LICENSE_EXPIRED
+ * DRM_ERROR_SESSION_NOT_OPENED, DRM_ERROR_DECRYPT_UNIT_NOT_INITIALIZED,
+ * DRM_ERROR_DECRYPT for failure.
+ */
+ status_t decrypt(
+ DecryptHandle* decryptHandle, int decryptUnitId,
+ const DrmBuffer* encBuffer, DrmBuffer** decBuffer);
+
+ /**
+ * Finalize decryption for the given unit of the protected content
+ *
+ * @param[in] decryptHandle Handle for the decryption session
+ * @param[in] decryptUnitId ID which specifies decryption unit, such as track ID
+ */
+ void finalizeDecryptUnit(DecryptHandle* decryptHandle, int decryptUnitId);
+
+ /**
+ * Reads the specified number of bytes from an open DRM file.
+ *
+ * @param[in] decryptHandle Handle for the decryption session
+ * @param[out] buffer Reference to the buffer that should receive the read data.
+ * @param[in] numBytes Number of bytes to read.
+ * @param[in] offset Offset with which to update the file position.
+ *
+ * @return Number of bytes read. Returns -1 for Failure.
+ */
+ ssize_t pread(DecryptHandle* decryptHandle, void* buffer, ssize_t numBytes, off_t offset);
+
+ /**
+ * Validates whether an action on the DRM content is allowed or not.
+ *
+ * @param[in] path Path of the protected content
+ * @param[in] action Action to validate. (Action::DEFAULT, Action::PLAY, etc)
+ * @param[in] description Detailed description of the action
+ * @return true if the action is allowed.
+ */
+ bool validateAction(const String8& path, int action, const ActionDescription& description);
+
+/**
+ * APIs which are just the underlying implementation for the Java API
+ *
+ */
+public:
+ /**
+ * Register a callback to be invoked when the caller required to
+ * receive necessary information
+ *
+ * @param[in] infoListener Listener
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ status_t setOnInfoListener(const sp<DrmManagerClient::OnInfoListener>& infoListener);
+
+ /**
+ * Get constraint information associated with input content
+ *
+ * @param[in] path Path of the protected content
+ * @param[in] action Actions defined such as,
+ * Action::DEFAULT, Action::PLAY, etc
+ * @return DrmConstraints
+ * key-value pairs of constraint are embedded in it
+ * @note
+ * In case of error, return NULL
+ */
+ DrmConstraints* getConstraints(const String8* path, const int action);
+
+ /**
+ * Check whether the given mimetype or path can be handled
+ *
+ * @param[in] path Path of the content needs to be handled
+ * @param[in] mimetype Mimetype of the content needs to be handled
+ * @return
+ * True if DrmManager can handle given path or mime type.
+ */
+ bool canHandle(const String8& path, const String8& mimeType);
+
+ /**
+ * Executes given drm information based on its type
+ *
+ * @param[in] drmInfo Information needs to be processed
+ * @return DrmInfoStatus
+ * instance as a result of processing given input
+ */
+ DrmInfoStatus* processDrmInfo(const DrmInfo* drmInfo);
+
+ /**
+ * Retrieves necessary information for registration, unregistration or rights
+ * acquisition information.
+ *
+ * @param[in] drmInfoRequest Request information to retrieve drmInfo
+ * @return DrmInfo
+ * instance as a result of processing given input
+ */
+ DrmInfo* acquireDrmInfo(const DrmInfoRequest* drmInfoRequest);
+
+ /**
+ * Save DRM rights to specified rights path
+ * and make association with content path
+ *
+ * @param[in] drmRights DrmRights to be saved
+ * @param[in] rightsPath File path where rights to be saved
+ * @param[in] contentPath File path where content was saved
+ */
+ void saveRights(
+ const DrmRights& drmRights, const String8& rightsPath, const String8& contentPath);
+
+ /**
+ * Retrieves the mime type embedded inside the original content
+ *
+ * @param[in] path the path of the protected content
+ * @return String8
+ * Returns mime-type of the original content, such as "video/mpeg"
+ */
+ String8 getOriginalMimeType(const String8& path);
+
+ /**
+ * Retrieves the type of the protected object (content, rights, etc..)
+ * by using specified path or mimetype. At least one parameter should be non null
+ * to retrieve DRM object type
+ *
+ * @param[in] path Path of the content or null.
+ * @param[in] mimeType Mime type of the content or null.
+ * @return type of the DRM content,
+ * such as DrmObjectType::CONTENT, DrmObjectType::RIGHTS_OBJECT
+ */
+ int getDrmObjectType(const String8& path, const String8& mimeType);
+
+ /**
+ * Check whether the given content has valid rights or not
+ *
+ * @param[in] path Path of the protected content
+ * @param[in] action Action to perform
+ * @return the status of the rights for the protected content,
+ * such as RightsStatus::RIGHTS_VALID, RightsStatus::RIGHTS_EXPIRED, etc.
+ */
+ int checkRightsStatus(const String8& path, int action);
+
+ /**
+ * Removes the rights associated with the given protected content
+ *
+ * @param[in] path Path of the protected content
+ */
+ void removeRights(const String8& path);
+
+ /**
+ * Removes all the rights information of each plug-in associated with
+ * DRM framework. Will be used in master reset
+ *
+ */
+ void removeAllRights();
+
+ /**
+ * This API is for Forward Lock DRM.
+ * Each time the application tries to download a new DRM file
+ * which needs to be converted, then the application has to
+ * begin with calling this API.
+ *
+ * @param[in] convertId Handle for the convert session
+ * @param[in] mimeType Description/MIME type of the input data packet
+ * @return Return handle for the convert session
+ */
+ int openConvertSession(const String8& mimeType);
+
+ /**
+ * Passes the input data which need to be converted. The resultant
+ * converted data and the status is returned in the DrmConvertedInfo
+ * object. This method will be called each time there are new block
+ * of data received by the application.
+ *
+ * @param[in] convertId Handle for the convert session
+ * @param[in] inputData Input Data which need to be converted
+ * @return Return object contains the status of the data conversion,
+ * the output converted data and offset. In this case the
+ * application will ignore the offset information.
+ */
+ DrmConvertedStatus* convertData(int convertId, const DrmBuffer* inputData);
+
+ /**
+ * When there is no more data which need to be converted or when an
+ * error occurs that time the application has to inform the Drm agent
+ * via this API. Upon successful conversion of the complete data,
+ * the agent will inform that where the header and body signature
+ * should be added. This signature appending is needed to integrity
+ * protect the converted file.
+ *
+ * @param[in] convertId Handle for the convert session
+ * @return Return object contains the status of the data conversion,
+ * the header and body signature data. It also informs
+ * the application on which offset these signature data
+ * should be appended.
+ */
+ DrmConvertedStatus* closeConvertSession(int convertId);
+
+ /**
+ * Retrieves all DrmSupportInfo instance that native DRM framework can handle.
+ * This interface is meant to be used by JNI layer
+ *
+ * @param[out] length Number of elements in drmSupportInfoArray
+ * @param[out] drmSupportInfoArray Array contains all DrmSupportInfo
+ * that native DRM framework can handle
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ status_t getAllSupportInfo(int* length, DrmSupportInfo** drmSupportInfoArray);
+
+private:
+ /**
+ * Initialize DRM Manager
+ * load available plug-ins from default plugInDirPath
+ *
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ status_t loadPlugIns();
+
+ /**
+ * Finalize DRM Manager
+ * release resources associated with each plug-in
+ * unload all plug-ins and etc.
+ *
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ status_t unloadPlugIns();
+
+private:
+ int mUniqueId;
+ DrmManagerClientImpl* mDrmManagerClientImpl;
+};
+
+};
+
+#endif /* __DRM_MANAGER_CLIENT_H__ */
+
diff --git a/include/drm/DrmRights.h b/include/drm/DrmRights.h
new file mode 100644
index 0000000..e04a066
--- /dev/null
+++ b/include/drm/DrmRights.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#ifndef __DRM_RIGHTS_H__
+#define __DRM_RIGHTS_H__
+
+#include "drm_framework_common.h"
+
+namespace android {
+
+/**
+ * This is an utility class which wraps the license information which was
+ * retrieved from the online DRM server.
+ *
+ * Caller can instantiate DrmRights by invoking DrmRights(const DrmBuffer&, String)
+ * constructor by using the result of DrmManagerClient::ProcessDrmInfo(const DrmInfo*) API.
+ * Caller can also instantiate DrmRights using the file path which contains rights information.
+ *
+ */
+class DrmRights {
+public:
+ /**
+ * Constructor for DrmRights
+ *
+ * @param[in] rightsFilePath Path of the file containing rights data
+ * @param[in] mimeType MIME type
+ * @param[in] accountId Account Id of the user
+ * @param[in] subscriptionId Subscription Id of the user
+ */
+ DrmRights(
+ const String8& rightsFilePath, const String8& mimeType,
+ const String8& accountId = String8("_NO_USER"),
+ const String8& subscriptionId = String8(""));
+
+ /**
+ * Constructor for DrmRights
+ *
+ * @param[in] rightsData Rights data
+ * @param[in] mimeType MIME type
+ * @param[in] accountId Account Id of the user
+ * @param[in] subscriptionId Subscription Id of the user
+ */
+ DrmRights(
+ const DrmBuffer& rightsData, const String8& mimeType,
+ const String8& accountId = String8("_NO_USER"),
+ const String8& subscriptionId = String8(""));
+
+ /**
+ * Destructor for DrmRights
+ */
+ virtual ~DrmRights() {}
+
+public:
+ /**
+ * Returns the rights data associated with this instance
+ *
+ * @return Rights data
+ */
+ const DrmBuffer& getData(void) const;
+
+ /**
+ * Returns MIME type associated with this instance
+ *
+ * @return MIME type
+ */
+ String8 getMimeType(void) const;
+
+ /**
+ * Returns the account-id associated with this instance
+ *
+ * @return Account Id
+ */
+ String8 getAccountId(void) const;
+
+ /**
+ * Returns the subscription-id associated with this object
+ *
+ * @return Subscription Id
+ */
+ String8 getSubscriptionId(void) const;
+
+private:
+ DrmBuffer mData;
+ String8 mMimeType;
+ String8 mAccountId;
+ String8 mSubscriptionId;
+};
+
+};
+
+#endif /* __DRM_RIGHTS_H__ */
+
diff --git a/include/drm/DrmSupportInfo.h b/include/drm/DrmSupportInfo.h
new file mode 100644
index 0000000..bf12b0b
--- /dev/null
+++ b/include/drm/DrmSupportInfo.h
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#ifndef __DRM_SUPPORT_INFO_H__
+#define __DRM_SUPPORT_INFO_H__
+
+#include "drm_framework_common.h"
+
+namespace android {
+
+/**
+ * This is an utility class which wraps the capability of each plug-in,
+ * such as mimetype's and file suffixes it could handle.
+ *
+ * Plug-in developer could return the capability of the plugin by passing
+ * DrmSupportInfo instance.
+ *
+ */
+class DrmSupportInfo {
+public:
+ /**
+ * Iterator for mMimeTypeVector
+ */
+ class MimeTypeIterator {
+ friend class DrmSupportInfo;
+ private:
+ MimeTypeIterator(DrmSupportInfo* drmSupportInfo)
+ : mDrmSupportInfo(drmSupportInfo), mIndex(0) {}
+ public:
+ MimeTypeIterator(const MimeTypeIterator& iterator);
+ MimeTypeIterator& operator=(const MimeTypeIterator& iterator);
+ virtual ~MimeTypeIterator() {}
+
+ public:
+ bool hasNext();
+ String8& next();
+
+ private:
+ DrmSupportInfo* mDrmSupportInfo;
+ unsigned int mIndex;
+ };
+
+ /**
+ * Iterator for mFileSuffixVector
+ */
+ class FileSuffixIterator {
+ friend class DrmSupportInfo;
+
+ private:
+ FileSuffixIterator(DrmSupportInfo* drmSupportInfo)
+ : mDrmSupportInfo(drmSupportInfo), mIndex(0) {}
+ public:
+ FileSuffixIterator(const FileSuffixIterator& iterator);
+ FileSuffixIterator& operator=(const FileSuffixIterator& iterator);
+ virtual ~FileSuffixIterator() {}
+
+ public:
+ bool hasNext();
+ String8& next();
+
+ private:
+ DrmSupportInfo* mDrmSupportInfo;
+ unsigned int mIndex;
+ };
+
+public:
+ /**
+ * Constructor for DrmSupportInfo
+ */
+ DrmSupportInfo();
+
+ /**
+ * Copy constructor for DrmSupportInfo
+ */
+ DrmSupportInfo(const DrmSupportInfo& drmSupportInfo);
+
+ /**
+ * Destructor for DrmSupportInfo
+ */
+ virtual ~DrmSupportInfo() {}
+
+ DrmSupportInfo& operator=(const DrmSupportInfo& drmSupportInfo);
+ bool operator<(const DrmSupportInfo& drmSupportInfo) const;
+ bool operator==(const DrmSupportInfo& drmSupportInfo) const;
+
+ /**
+ * Returns FileSuffixIterator object to walk through file suffix values
+ * associated with this instance
+ *
+ * @return FileSuffixIterator object
+ */
+ FileSuffixIterator getFileSuffixIterator();
+
+ /**
+ * Returns MimeTypeIterator object to walk through mimetype values
+ * associated with this instance
+ *
+ * @return MimeTypeIterator object
+ */
+ MimeTypeIterator getMimeTypeIterator();
+
+public:
+ /**
+ * Returns the number of mimetypes supported.
+ *
+ * @return Number of mimetypes supported
+ */
+ int getMimeTypeCount(void) const;
+
+ /**
+ * Returns the number of file types supported.
+ *
+ * @return Number of file types supported
+ */
+ int getFileSuffixCount(void) const;
+
+ /**
+ * Adds the mimetype to the list of supported mimetypes
+ *
+ * @param[in] mimeType mimetype to be added
+ * @return Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ status_t addMimeType(const String8& mimeType);
+
+ /**
+ * Adds the filesuffix to the list of supported file types
+ *
+ * @param[in] filesuffix file suffix to be added
+ * @return Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ status_t addFileSuffix(const String8& fileSuffix);
+
+ /**
+ * Set the unique description about the plugin
+ *
+ * @param[in] description Unique description
+ * @return Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ status_t setDescription(const String8& description);
+
+ /**
+ * Returns the unique description associated with the plugin
+ *
+ * @return Unique description
+ */
+ String8 getDescription() const;
+
+ /**
+ * Returns whether given mimetype is supported or not
+ *
+ * @param[in] mimeType MIME type
+ * @return
+ * true - if mime-type is supported
+ * false - if mime-type is not supported
+ */
+ bool isSupportedMimeType(const String8& mimeType) const;
+
+ /**
+ * Returns whether given file type is supported or not
+ *
+ * @param[in] fileType File type
+ * @return
+ * true if file type is supported
+ * false if file type is not supported
+ */
+ bool isSupportedFileSuffix(const String8& fileType) const;
+
+private:
+ Vector<String8> mMimeTypeVector;
+ Vector<String8> mFileSuffixVector;
+
+ String8 mDescription;
+};
+
+};
+
+#endif /* __DRM_SUPPORT_INFO_H__ */
+
diff --git a/include/drm/drm_framework_common.h b/include/drm/drm_framework_common.h
new file mode 100644
index 0000000..8b8a9f5
--- /dev/null
+++ b/include/drm/drm_framework_common.h
@@ -0,0 +1,300 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#ifndef __DRM_FRAMEWORK_COMMON_H__
+#define __DRM_FRAMEWORK_COMMON_H__
+
+#include <utils/Vector.h>
+#include <utils/KeyedVector.h>
+#include <utils/String8.h>
+#include <utils/Errors.h>
+
+#define INVALID_VALUE -1
+
+namespace android {
+
+/**
+ * Error code for DRM Frameowrk
+ */
+enum {
+ DRM_ERROR_BASE = -2000,
+
+ DRM_ERROR_UNKNOWN = DRM_ERROR_BASE,
+ DRM_ERROR_LICENSE_EXPIRED = DRM_ERROR_BASE - 1,
+ DRM_ERROR_SESSION_NOT_OPENED = DRM_ERROR_BASE - 2,
+ DRM_ERROR_DECRYPT_UNIT_NOT_INITIALIZED = DRM_ERROR_BASE - 3,
+ DRM_ERROR_DECRYPT = DRM_ERROR_BASE - 4,
+ DRM_ERROR_CANNOT_HANDLE = DRM_ERROR_BASE - 5,
+
+ DRM_NO_ERROR = NO_ERROR
+};
+
+/**
+ * Defines DRM Buffer
+ */
+class DrmBuffer {
+public:
+ char* data;
+ int length;
+
+ DrmBuffer() :
+ data(NULL),
+ length(0) {
+ }
+
+ DrmBuffer(char* dataBytes, int dataLength) :
+ data(dataBytes),
+ length(dataLength) {
+ }
+
+};
+
+/**
+ * Defines detailed description of the action
+ */
+class ActionDescription {
+public:
+ ActionDescription(int _outputType, int _configuration) :
+ outputType(_outputType),
+ configuration(_configuration) {
+ }
+
+public:
+ int outputType; /* BLUETOOTH , HDMI*/
+ int configuration; /* RESOLUTION_720_480 , RECORDABLE etc.*/
+};
+
+/**
+ * Defines constants related to DRM types
+ */
+class DrmObjectType {
+private:
+ DrmObjectType();
+
+public:
+ /**
+ * Field specifies the unknown type
+ */
+ static const int UNKNOWN = 0x00;
+ /**
+ * Field specifies the protected content type
+ */
+ static const int CONTENT = 0x01;
+ /**
+ * Field specifies the rights information
+ */
+ static const int RIGHTS_OBJECT = 0x02;
+ /**
+ * Field specifies the trigger information
+ */
+ static const int TRIGGER_OBJECT = 0x03;
+};
+
+/**
+ * Defines constants related to play back
+ */
+class Playback {
+private:
+ Playback();
+
+public:
+ /**
+ * Constant field signifies playback start
+ */
+ static const int START = 0x00;
+ /**
+ * Constant field signifies playback stop
+ */
+ static const int STOP = 0x01;
+ /**
+ * Constant field signifies playback paused
+ */
+ static const int PAUSE = 0x02;
+ /**
+ * Constant field signifies playback resumed
+ */
+ static const int RESUME = 0x03;
+};
+
+/**
+ * Defines actions that can be performed on protected content
+ */
+class Action {
+private:
+ Action();
+
+public:
+ /**
+ * Constant field signifies that the default action
+ */
+ static const int DEFAULT = 0x00;
+ /**
+ * Constant field signifies that the content can be played
+ */
+ static const int PLAY = 0x01;
+ /**
+ * Constant field signifies that the content can be set as ring tone
+ */
+ static const int RINGTONE = 0x02;
+ /**
+ * Constant field signifies that the content can be transfered
+ */
+ static const int TRANSFER = 0x03;
+ /**
+ * Constant field signifies that the content can be set as output
+ */
+ static const int OUTPUT = 0x04;
+ /**
+ * Constant field signifies that preview is allowed
+ */
+ static const int PREVIEW = 0x05;
+ /**
+ * Constant field signifies that the content can be executed
+ */
+ static const int EXECUTE = 0x06;
+ /**
+ * Constant field signifies that the content can displayed
+ */
+ static const int DISPLAY = 0x07;
+};
+
+/**
+ * Defines constants related to status of the rights
+ */
+class RightsStatus {
+private:
+ RightsStatus();
+
+public:
+ /**
+ * Constant field signifies that the rights are valid
+ */
+ static const int RIGHTS_VALID = 0x00;
+ /**
+ * Constant field signifies that the rights are invalid
+ */
+ static const int RIGHTS_INVALID = 0x01;
+ /**
+ * Constant field signifies that the rights are expired for the content
+ */
+ static const int RIGHTS_EXPIRED = 0x02;
+ /**
+ * Constant field signifies that the rights are not acquired for the content
+ */
+ static const int RIGHTS_NOT_ACQUIRED = 0x03;
+};
+
+/**
+ * Defines API set for decryption
+ */
+class DecryptApiType {
+private:
+ DecryptApiType();
+
+public:
+ /**
+ * Decrypt API set for non encrypted content
+ */
+ static const int NON_ENCRYPTED = 0x00;
+ /**
+ * Decrypt API set for ES based DRM
+ */
+ static const int ELEMENTARY_STREAM_BASED = 0x01;
+ /**
+ * POSIX based Decrypt API set for container based DRM
+ */
+ static const int CONTAINER_BASED = 0x02;
+};
+
+/**
+ * Defines decryption information
+ */
+class DecryptInfo {
+public:
+ /**
+ * size of memory to be allocated to get the decrypted content.
+ */
+ int decryptBufferLength;
+ /**
+ * reserved for future purpose
+ */
+};
+
+/**
+ * Defines decryption handle
+ */
+class DecryptHandle {
+public:
+ /**
+ * Decryption session Handle
+ */
+ int decryptId;
+ /**
+ * Mimetype of the content to be used to select the media extractor
+ * For e.g., "video/mpeg" or "audio/mp3"
+ */
+ String8 mimeType;
+ /**
+ * Defines which decryption pattern should be used to decrypt the given content
+ * DrmFramework provides two different set of decryption APIs.
+ * 1. Decrypt APIs for elementary stream based DRM
+ * (file format is not encrypted but ES is encrypted)
+ * e.g., Marlin DRM (MP4 file format), WM-DRM (asf file format)
+ *
+ * DecryptAPI::TYPE_ELEMENTARY_STREAM_BASED
+ * Decryption API set for ES based DRM
+ * initializeDecryptUnit(), decrypt(), and finalizeDecryptUnit()
+ * 2. Decrypt APIs for container based DRM (file format itself is encrypted)
+ * e.g., OMA DRM (dcf file format)
+ *
+ * DecryptAPI::TYPE_CONTAINER_BASED
+ * POSIX based Decryption API set for container based DRM
+ * pread()
+ */
+ int decryptApiType;
+ /**
+ * Defines the status of the rights like
+ * RIGHTS_VALID, RIGHTS_INVALID, RIGHTS_EXPIRED or RIGHTS_NOT_ACQUIRED
+ */
+ int status;
+ /**
+ * Information required to decrypt content
+ * e.g. size of memory to be allocated to get the decrypted content.
+ */
+ DecryptInfo* decryptInfo;
+
+public:
+ DecryptHandle():
+ decryptId(INVALID_VALUE),
+ mimeType(""),
+ decryptApiType(INVALID_VALUE),
+ status(INVALID_VALUE) {
+
+ }
+
+ bool operator<(const DecryptHandle& handle) const {
+ return (decryptId < handle.decryptId);
+ }
+
+ bool operator==(const DecryptHandle& handle) const {
+ return (decryptId == handle.decryptId);
+ }
+};
+
+};
+
+#endif /* __DRM_FRAMEWORK_COMMON_H__ */
+
diff --git a/include/media/EffectEnvironmentalReverbApi.h b/include/media/EffectEnvironmentalReverbApi.h
index 2233e3f..36accd8 100644
--- a/include/media/EffectEnvironmentalReverbApi.h
+++ b/include/media/EffectEnvironmentalReverbApi.h
@@ -48,16 +48,16 @@
//t_reverb_settings is equal to SLEnvironmentalReverbSettings defined in OpenSL ES specification.
typedef struct s_reverb_settings {
- int16_t roomLevel;
- int16_t roomHFLevel;
- int32_t decayTime;
- int16_t decayHFRatio;
- int16_t reflectionsLevel;
- int32_t reflectionsDelay;
- int16_t reverbLevel;
- int32_t reverbDelay;
- int16_t diffusion;
- int16_t density;
+ int16_t roomLevel;
+ int16_t roomHFLevel;
+ uint32_t decayTime;
+ int16_t decayHFRatio;
+ int16_t reflectionsLevel;
+ uint32_t reflectionsDelay;
+ int16_t reverbLevel;
+ uint32_t reverbDelay;
+ int16_t diffusion;
+ int16_t density;
} __attribute__((packed)) t_reverb_settings;
diff --git a/include/media/IOMX.h b/include/media/IOMX.h
index 2f61cbe..1f8ce71 100644
--- a/include/media/IOMX.h
+++ b/include/media/IOMX.h
@@ -19,6 +19,7 @@
#define ANDROID_IOMX_H_
#include <binder/IInterface.h>
+#include <ui/GraphicBuffer.h>
#include <utils/List.h>
#include <utils/String8.h>
@@ -78,10 +79,17 @@
node_id node, OMX_INDEXTYPE index,
const void *params, size_t size) = 0;
+ virtual status_t enableGraphicBuffers(
+ node_id node, OMX_U32 port_index, OMX_BOOL enable) = 0;
+
virtual status_t useBuffer(
node_id node, OMX_U32 port_index, const sp<IMemory> ¶ms,
buffer_id *buffer) = 0;
+ virtual status_t useGraphicBuffer(
+ node_id node, OMX_U32 port_index,
+ const sp<GraphicBuffer> &graphicBuffer, buffer_id *buffer) = 0;
+
// This API clearly only makes sense if the caller lives in the
// same process as the callee, i.e. is the media_server, as the
// returned "buffer_data" pointer is just that, a pointer into local
diff --git a/include/media/stagefright/AudioSource.h b/include/media/stagefright/AudioSource.h
index 1af4254..a5cec78 100644
--- a/include/media/stagefright/AudioSource.h
+++ b/include/media/stagefright/AudioSource.h
@@ -72,6 +72,7 @@
int64_t mPrevSampleTimeUs;
int64_t mTotalLostFrames;
int64_t mPrevLostBytes;
+ int64_t mInitialReadTimeUs;
MediaBufferGroup *mGroup;
diff --git a/include/media/stagefright/HardwareAPI.h b/include/media/stagefright/HardwareAPI.h
index 221c679..4ded5e8 100644
--- a/include/media/stagefright/HardwareAPI.h
+++ b/include/media/stagefright/HardwareAPI.h
@@ -21,10 +21,60 @@
#include <media/stagefright/OMXPluginBase.h>
#include <media/stagefright/VideoRenderer.h>
#include <surfaceflinger/ISurface.h>
+#include <ui/android_native_buffer.h>
#include <utils/RefBase.h>
#include <OMX_Component.h>
+namespace android {
+
+// A pointer to this struct is passed to the OMX_SetParameter when the extension
+// index for the 'OMX.google.android.index.enableAndroidNativeBuffers' extension
+// is given.
+//
+// When Android native buffer use is disabled for a port (the default state),
+// the OMX node should operate as normal, and expect UseBuffer calls to set its
+// buffers. This is the mode that will be used when CPU access to the buffer is
+// required.
+//
+// When Android native buffer use has been enabled, the OMX node must support
+// only color formats in the range [OMX_COLOR_FormatAndroidPrivateStart,
+// OMX_COLOR_FormatAndroidPrivateEnd). The node should then expect to receive
+// UseAndroidNativeBuffer calls (via OMX_SetParameter) rather than UseBuffer
+// calls.
+struct EnableAndroidNativeBuffersParams {
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_U32 nPortIndex;
+ OMX_BOOL enable;
+};
+
+// Color formats in the range [OMX_COLOR_FormatAndroidPrivateStart,
+// OMX_COLOR_FormatAndroidPrivateEnd) will be converted to a gralloc pixel
+// format when used to allocate Android native buffers via gralloc. The
+// conversion is done by subtracting OMX_COLOR_FormatAndroidPrivateStart from
+// the color format reported by the codec.
+enum {
+ OMX_COLOR_FormatAndroidPrivateStart = 0xA0000000,
+ OMX_COLOR_FormatAndroidPrivateEnd = 0xB0000000,
+};
+
+// A pointer to this struct is passed to OMX_SetParameter when the extension
+// index for the 'OMX.google.android.index.useAndroidNativeBuffer' extension is
+// given. This call will only be performed if a prior call was made with the
+// 'OMX.google.android.index.enableAndroidNativeBuffers' extension index,
+// enabling use of Android native buffers.
+struct UseAndroidNativeBufferParams {
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_U32 nPortIndex;
+ OMX_PTR pAppPrivate;
+ OMX_BUFFERHEADERTYPE **bufferHeader;
+ const sp<android_native_buffer_t>& nativeBuffer;
+};
+
+} // namespace android
+
extern android::VideoRenderer *createRenderer(
const android::sp<android::ISurface> &surface,
const char *componentName,
@@ -35,4 +85,3 @@
extern android::OMXPluginBase *createOMXPlugin();
#endif // HARDWARE_API_H_
-
diff --git a/include/media/stagefright/MPEG4Writer.h b/include/media/stagefright/MPEG4Writer.h
index 2412f6a..70bd8e8 100644
--- a/include/media/stagefright/MPEG4Writer.h
+++ b/include/media/stagefright/MPEG4Writer.h
@@ -62,6 +62,7 @@
class Track;
FILE *mFile;
+ bool mUse4ByteNalLength;
bool mUse32BitOffset;
bool mPaused;
bool mStarted;
@@ -132,9 +133,13 @@
// Adjust other track media clock (presumably wall clock)
// based on audio track media clock with the drift time.
int64_t mDriftTimeUs;
- void addDriftTimeUs(int64_t driftTimeUs);
+ void setDriftTimeUs(int64_t driftTimeUs);
int64_t getDriftTimeUs();
+ // Return whether the nal length is 4 bytes or 2 bytes
+ // Only makes sense for H.264/AVC
+ bool useNalLengthFour();
+
void lock();
void unlock();
@@ -144,6 +149,7 @@
inline size_t write(const void *ptr, size_t size, size_t nmemb, FILE* stream);
bool exceedsFileSizeLimit();
+ bool use32BitFileOffset() const;
bool exceedsFileDurationLimit();
void trackProgressStatus(const Track* track, int64_t timeUs, status_t err = OK);
diff --git a/include/media/stagefright/MetaData.h b/include/media/stagefright/MetaData.h
index 43354c2..1594e31 100644
--- a/include/media/stagefright/MetaData.h
+++ b/include/media/stagefright/MetaData.h
@@ -48,6 +48,8 @@
kKeyTime = 'time', // int64_t (usecs)
kKeyNTPTime = 'ntpT', // uint64_t (ntp-timestamp)
kKeyTargetTime = 'tarT', // int64_t (usecs)
+ kKeyDriftTime = 'dftT', // int64_t (usecs)
+ kKeyAnchorTime = 'ancT', // int64_t (usecs)
kKeyDuration = 'dura', // int64_t (usecs)
kKeyColorFormat = 'colf',
kKeyPlatformPrivate = 'priv', // pointer
@@ -78,6 +80,7 @@
// Set this key to enable authoring files in 64-bit offset
kKey64BitFileOffset = 'fobt', // int32_t (bool)
+ kKey2ByteNalLength = '2NAL', // int32_t (bool)
// Identify the file output format for authoring
// Please see <media/mediarecorder.h> for the supported
@@ -90,6 +93,8 @@
kKeyNotRealTime = 'ntrt', // bool (int32_t)
+ // Ogg files can be tagged to be automatically looping...
+ kKeyAutoLoop = 'autL', // bool (int32_t)
};
enum {
diff --git a/media/libeffects/lvm/lib/Bass/src/LVDBE_Private.h b/media/libeffects/lvm/lib/Bass/src/LVDBE_Private.h
index 495b38f..8339d3c 100644
--- a/media/libeffects/lvm/lib/Bass/src/LVDBE_Private.h
+++ b/media/libeffects/lvm/lib/Bass/src/LVDBE_Private.h
@@ -64,7 +64,7 @@
#define LVDBE_PERSISTENT_COEF_ALIGN 4 /* 32-bit alignment for coef */
#define LVDBE_SCRATCH_ALIGN 4 /* 32-bit alignment for long data */
-#define LVDBE_SCRATCHBUFFERS_INPLACE 4 /* Number of buffers required for inplace processing */
+#define LVDBE_SCRATCHBUFFERS_INPLACE 6 /* Number of buffers required for inplace processing */
#define LVDBE_MIXER_TC 5 /* Mixer time */
#define LVDBE_BYPASS_MIXER_TC 100 /* Bypass mixer time */
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_ApplyNewSettings.c b/media/libeffects/lvm/lib/Reverb/src/LVREV_ApplyNewSettings.c
index 6a8b39b..ac2ef9d 100644
--- a/media/libeffects/lvm/lib/Reverb/src/LVREV_ApplyNewSettings.c
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_ApplyNewSettings.c
@@ -496,7 +496,6 @@
* Update the bypass mixer time constant
*/
if((pPrivate->NewParams.SampleRate != pPrivate->CurrentParams.SampleRate) ||
- (pPrivate->NewParams.SourceFormat != pPrivate->CurrentParams.SourceFormat) ||
(pPrivate->bFirstControl == LVM_TRUE))
{
LVM_UINT16 NumChannels = 1; /* Assume MONO format */
@@ -508,11 +507,7 @@
pPrivate->FeedbackMixer[2].Alpha=Alpha;
pPrivate->FeedbackMixer[3].Alpha=Alpha;
- if (pPrivate->NewParams.SourceFormat != LVM_MONO)
- {
- /* Stereo or Mono-in-Stereo format data */
- NumChannels = 2;
- }
+ NumChannels = 2; /* Always stereo output */
pPrivate->BypassMixer.Alpha1 = (LVM_INT32)LVM_Mixer_TimeConstant(LVREV_BYPASSMIXER_TC, LVM_GetFsFromTable(pPrivate->NewParams.SampleRate), NumChannels);
pPrivate->BypassMixer.Alpha2 = pPrivate->BypassMixer.Alpha1;
pPrivate->GainMixer.Alpha = pPrivate->BypassMixer.Alpha1;
@@ -526,7 +521,7 @@
(pPrivate->NewParams.OperatingMode == LVM_MODE_ON))
{
pPrivate->BypassMixer.Target2 = ((LVM_INT32)(pPrivate->NewParams.Level * 32767)/100)<<16;
- pPrivate->BypassMixer.Target1 = LVREV_HEADROOM << 16;
+ pPrivate->BypassMixer.Target1 = 0x00000000;
if ((pPrivate->NewParams.Level == 0) && (pPrivate->bFirstControl == LVM_FALSE))
{
pPrivate->BypassMixer.CallbackSet2 = LVM_TRUE;
@@ -542,7 +537,7 @@
if(pPrivate->NewParams.OperatingMode == LVM_MODE_ON)
{
pPrivate->BypassMixer.Target2 = ((LVM_INT32)(pPrivate->NewParams.Level * 32767)/100)<<16;
- pPrivate->BypassMixer.Target1 = LVREV_HEADROOM << 16;
+ pPrivate->BypassMixer.Target1 = 0x00000000;
pPrivate->BypassMixer.CallbackSet2 = LVM_FALSE;
OperatingMode = LVM_MODE_ON;
@@ -558,7 +553,7 @@
else if (pPrivate->bFirstControl == LVM_FALSE)
{
pPrivate->BypassMixer.Target2 = 0x00000000;
- pPrivate->BypassMixer.Target1 = 0x7FFFFFFF;
+ pPrivate->BypassMixer.Target1 = 0x00000000;
pPrivate->BypassMixer.CallbackSet2 = LVM_TRUE;
pPrivate->GainMixer.Target = 0x03FFFFFF;
OperatingMode = LVM_MODE_ON;
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_GetInstanceHandle.c b/media/libeffects/lvm/lib/Reverb/src/LVREV_GetInstanceHandle.c
index c2b266a..ffa5138 100644
--- a/media/libeffects/lvm/lib/Reverb/src/LVREV_GetInstanceHandle.c
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_GetInstanceHandle.c
@@ -238,8 +238,8 @@
pLVREV_Private->BypassMixer.pGeneralPurpose1 = LVM_NULL;
pLVREV_Private->BypassMixer.pCallBack1 = LVM_NULL;
pLVREV_Private->BypassMixer.CallbackSet1 = LVM_FALSE;
- pLVREV_Private->BypassMixer.Current1 = 0x7fffffff;
- pLVREV_Private->BypassMixer.Target1 = 0x7fffffff;
+ pLVREV_Private->BypassMixer.Current1 = 0x00000000;
+ pLVREV_Private->BypassMixer.Target1 = 0x00000000;
pLVREV_Private->RoomSizeInms = 100; // 100 msec
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_Process.c b/media/libeffects/lvm/lib/Reverb/src/LVREV_Process.c
index 81521ba..5c7a8a0 100644
--- a/media/libeffects/lvm/lib/Reverb/src/LVREV_Process.c
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_Process.c
@@ -54,7 +54,8 @@
LVREV_Instance_st *pLVREV_Private = (LVREV_Instance_st *)hInstance;
LVM_INT32 *pInput = (LVM_INT32 *)pInData;
LVM_INT32 *pOutput = pOutData;
- LVM_INT32 SamplesToProcess, RemainingSamples, format;
+ LVM_INT32 SamplesToProcess, RemainingSamples;
+ LVM_INT32 format = 1;
/*
* Check for error conditions
@@ -66,7 +67,6 @@
return LVREV_NULLADDRESS;
}
-
/*
* Apply the new controls settings if required
*/
@@ -95,9 +95,31 @@
return LVREV_SUCCESS;
}
+ /*
+ * If OFF copy and reformat the data as necessary
+ */
+ if (pLVREV_Private->CurrentParams.OperatingMode == LVM_MODE_OFF)
+ {
+ if(pInput != pOutput)
+ {
+ /*
+ * Copy the data to the output buffer, convert to stereo is required
+ */
+
+ if(pLVREV_Private->CurrentParams.SourceFormat == LVM_MONO){
+ MonoTo2I_32(pInput, pOutput, NumSamples);
+ } else {
+ Copy_16((LVM_INT16 *)pInput,
+ (LVM_INT16 *)pOutput,
+ (LVM_INT16)(NumSamples << 2)); // 32 bit data, stereo
+ }
+ }
+
+ return LVREV_SUCCESS;
+ }
+
RemainingSamples = (LVM_INT32)NumSamples;
- format = 1;
if (pLVREV_Private->CurrentParams.SourceFormat != LVM_MONO)
{
format = 2;
@@ -106,51 +128,24 @@
while (RemainingSamples!=0)
{
/*
- * If OFF copy and reformat the data as necessary
+ * Process the data
*/
- if (pLVREV_Private->CurrentParams.OperatingMode == LVM_MODE_OFF)
+
+ if(RemainingSamples > pLVREV_Private->MaxBlkLen)
{
- if((pInput != pOutput) || (pLVREV_Private->CurrentParams.SourceFormat == LVM_MONO))
- {
- /*
- * Copy the data to the output buffer
- */
-
- if (pLVREV_Private->CurrentParams.SourceFormat != LVM_MONO)
- {
- RemainingSamples = (RemainingSamples << 1); /* Stereo data */
- }
-
- Copy_16((LVM_INT16 *)pInput,
- (LVM_INT16 *)pOutput,
- (LVM_INT16)(RemainingSamples << 1));
- }
-
+ SamplesToProcess = pLVREV_Private->MaxBlkLen;
+ RemainingSamples = (LVM_INT16)(RemainingSamples - SamplesToProcess);
+ }
+ else
+ {
+ SamplesToProcess = RemainingSamples;
RemainingSamples = 0;
}
- /*
- * Process the data
- */
- else
- {
+ ReverbBlock(pInput, pOutput, pLVREV_Private, (LVM_UINT16)SamplesToProcess);
- if(RemainingSamples > pLVREV_Private->MaxBlkLen)
- {
- SamplesToProcess = pLVREV_Private->MaxBlkLen;
- RemainingSamples = (LVM_INT16)(RemainingSamples - SamplesToProcess);
- }
- else
- {
- SamplesToProcess = RemainingSamples;
- RemainingSamples = 0;
- }
-
- ReverbBlock(pInput, pOutput, pLVREV_Private, (LVM_UINT16)SamplesToProcess);
-
- pInput = (LVM_INT32 *)(pInput +(SamplesToProcess*format));
- pOutput = (LVM_INT32 *)(pOutput+(SamplesToProcess*format));
- }
+ pInput = (LVM_INT32 *)(pInput +(SamplesToProcess*format));
+ pOutput = (LVM_INT32 *)(pOutput+(SamplesToProcess*2)); // Always stereo output
}
return LVREV_SUCCESS;
@@ -420,26 +415,13 @@
pPrivate->pScratchDelayLine[1],
(LVM_INT16)NumSamples);
- if(pPrivate->CurrentParams.SourceFormat != LVM_MONO)
- {
- JoinTo2i_32x32(pPrivate->pScratchDelayLine[0],
- pPrivate->pScratchDelayLine[1],
- pTemp,
- (LVM_INT16)NumSamples);
- }
- else
- {
- Add2_Sat_32x32(pPrivate->pScratchDelayLine[1],
- pPrivate->pScratchDelayLine[0],
- (LVM_INT16)NumSamples);
+ JoinTo2i_32x32(pPrivate->pScratchDelayLine[0],
+ pPrivate->pScratchDelayLine[1],
+ pTemp,
+ (LVM_INT16)NumSamples);
- /*Apply 3-dB gain in-order to compensate for the gain change in stereo mode*/
- Mult3s_32x16(pPrivate->pScratchDelayLine[0],
- LVREV_MIN3DB,
- pTemp,
- (LVM_INT16)NumSamples);
- }
+
break;
case LVREV_DELAYLINES_2:
@@ -447,49 +429,25 @@
(LVM_INT16*)pScratch,
(LVM_INT16)(NumSamples << 1));
-
-
- if(pPrivate->CurrentParams.SourceFormat != LVM_MONO)
- {
-
- Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[0],
- -0x8000,
- pScratch,
- (LVM_INT16)NumSamples);
- }
+ Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[0],
+ -0x8000,
+ pScratch,
+ (LVM_INT16)NumSamples);
Add2_Sat_32x32(pPrivate->pScratchDelayLine[1],
pPrivate->pScratchDelayLine[0],
(LVM_INT16)NumSamples);
- if(pPrivate->CurrentParams.SourceFormat != LVM_MONO)
- {
- JoinTo2i_32x32(pPrivate->pScratchDelayLine[0],
- pScratch,
- pTemp,
- (LVM_INT16)NumSamples);
- }
- else
- {
- Copy_16( (LVM_INT16*)pPrivate->pScratchDelayLine[0],
- (LVM_INT16*)pTemp,
- (LVM_INT16)(NumSamples << 1));
-
- }
- break;
- case LVREV_DELAYLINES_1:
- if(pPrivate->CurrentParams.SourceFormat != LVM_MONO)
- {
-
- MonoTo2I_32(pPrivate->pScratchDelayLine[0],
+ JoinTo2i_32x32(pPrivate->pScratchDelayLine[0],
+ pScratch,
pTemp,
(LVM_INT16)NumSamples);
- }
- else
- {
- pTemp = pPrivate->pScratchDelayLine[0];
- }
+ break;
+ case LVREV_DELAYLINES_1:
+ MonoTo2I_32(pPrivate->pScratchDelayLine[0],
+ pTemp,
+ (LVM_INT16)NumSamples);
break;
default:
break;
@@ -499,30 +457,15 @@
/*
* Dry/wet mixer
*/
- if(pPrivate->CurrentParams.SourceFormat != LVM_MONO)
- {
- size = (LVM_INT16)(NumSamples << 1);
- }
- else
- {
- size = (LVM_INT16)NumSamples;
- }
+ size = (LVM_INT16)(NumSamples << 1);
MixSoft_2St_D32C31_SAT(&pPrivate->BypassMixer,
- pInput,
+ pTemp,
pTemp,
pOutput,
size);
/* Apply Gain*/
- if(pPrivate->CurrentParams.SourceFormat != LVM_MONO)
- {
- size = (LVM_INT16)(NumSamples << 1);
- }
- else
- {
- size = (LVM_INT16)NumSamples;
- }
Shift_Sat_v32xv32 (LVREV_OUTPUTGAIN_SHIFT,
pOutput,
@@ -533,6 +476,7 @@
pOutput,
pOutput,
size);
+
return;
}
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Control.c b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Control.c
index a3ba42b..ce6d410 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Control.c
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Control.c
@@ -202,7 +202,9 @@
/* Set the reverb delay timeout */
if(pInstance->bInOperatingModeTransition != LVM_TRUE){
pInstance->bTimerDone = LVM_FALSE;
- pInstance->TimerParams.TimeInMs = (LVM_INT16)(((pInstance->Reverberation.DelaySize << 2)/pInstance->TimerParams.SamplingRate) + 1);
+ pInstance->TimerParams.TimeInMs =
+ (LVM_INT16)(((pInstance->Reverberation.DelaySize << 2)
+ /pInstance->TimerParams.SamplingRate) + 1);
LVM_Timer_Init ( &pInstance->TimerInstance,
&pInstance->TimerParams);
}
diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
index d3bb96e..e86ed99 100644
--- a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
+++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
@@ -258,14 +258,21 @@
pContext->pBundledContext->firstVolume = LVM_TRUE;
#ifdef LVM_PCM
- pContext->pBundledContext->PcmInPtr = NULL;
- pContext->pBundledContext->PcmOutPtr = NULL;
- pContext->pBundledContext->PcmInPtr = fopen("/data/tmp/bundle_pcm_in.pcm", "w");
- pContext->pBundledContext->PcmOutPtr = fopen("/data/tmp/bundle_pcm_out.pcm", "w");
+ char fileName[256];
+ snprintf(fileName, 256, "/data/tmp/bundle_%p_pcm_in.pcm", pContext->pBundledContext);
+ pContext->pBundledContext->PcmInPtr = fopen(fileName, "w");
+ if (pContext->pBundledContext->PcmInPtr == NULL) {
+ LOGV("cannot open %s", fileName);
+ return -EINVAL;
+ }
- if((pContext->pBundledContext->PcmInPtr == NULL)||
- (pContext->pBundledContext->PcmOutPtr == NULL)){
+ snprintf(fileName, 256, "/data/tmp/bundle_%p_pcm_out.pcm", pContext->pBundledContext);
+ pContext->pBundledContext->PcmOutPtr = fopen(fileName, "w");
+ if (pContext->pBundledContext->PcmOutPtr == NULL) {
+ LOGV("cannot open %s", fileName);
+ fclose(pContext->pBundledContext->PcmInPtr);
+ pContext->pBundledContext->PcmInPtr = NULL;
return -EINVAL;
}
#endif
@@ -375,8 +382,14 @@
(GlobalSessionMemory[pContext->pBundledContext->SessionNo].bVirtualizerInstantiated==LVM_FALSE))
{
#ifdef LVM_PCM
- fclose(pContext->pBundledContext->PcmInPtr);
- fclose(pContext->pBundledContext->PcmOutPtr);
+ if (pContext->pBundledContext->PcmInPtr != NULL) {
+ fclose(pContext->pBundledContext->PcmInPtr);
+ pContext->pBundledContext->PcmInPtr = NULL;
+ }
+ if (pContext->pBundledContext->PcmOutPtr != NULL) {
+ fclose(pContext->pBundledContext->PcmOutPtr);
+ pContext->pBundledContext->PcmOutPtr = NULL;
+ }
#endif
LvmSessionsActive--;
@@ -551,9 +564,6 @@
params.SpeakerType = LVM_HEADPHONES;
pContext->pBundledContext->SampleRate = LVM_FS_44100;
- pContext->pBundledContext->SamplesToExitCountEq = 44100*2*2; // 2 secs Stereo
- pContext->pBundledContext->SamplesToExitCountBb = 44100*2*2; // 2 secs Stereo
- pContext->pBundledContext->SamplesToExitCountVirt = 44100*2*2; // 2 secs Stereo
/* Concert Sound parameters */
params.VirtualizerOperatingMode = LVM_MODE_OFF;
@@ -2417,7 +2427,7 @@
if(pContext->pBundledContext->SamplesToExitCountBb > 0){
status2Sec = -ENODATA;
pContext->pBundledContext->SamplesToExitCountBb -= outBuffer->frameCount * 2; // STEREO
- //LOGV("\tEffect_process: Waiting for 2 secs to turn off BASS_BOOST, %d samples left",
+ //LOGV("\tEffect_process: Waiting to turn off BASS_BOOST, %d samples left",
// pContext->pBundledContext->SamplesToExitCountBb);
} else {
status = -ENODATA;
@@ -2883,11 +2893,11 @@
pContext->pBundledContext->NumberEffectsEnabled++;
android::LvmEffect_enable(pContext);
pContext->pBundledContext->SamplesToExitCountEq =
- (LVM_INT32)(pContext->pBundledContext->SamplesPerSecond*1); // 0.1 secs Stereo
+ (LVM_INT32)(pContext->pBundledContext->SamplesPerSecond*0.1); // 0.1 secs Stereo
pContext->pBundledContext->SamplesToExitCountBb =
- (LVM_INT32)(pContext->pBundledContext->SamplesPerSecond*6); // 2 secs Stereo
+ (LVM_INT32)(pContext->pBundledContext->SamplesPerSecond*0.1); // 0.1 secs Stereo
pContext->pBundledContext->SamplesToExitCountVirt =
- (LVM_INT32)(pContext->pBundledContext->SamplesPerSecond*1); // 2 secs Stereo
+ (LVM_INT32)(pContext->pBundledContext->SamplesPerSecond*0.1); // 0.1 secs Stereo
LOGV("\tEffect_command cmdCode Case: EFFECT_CMD_ENABLE Samples to Exit = %d",
pContext->pBundledContext->SamplesToExitCountBb);
//LOGV("\tEffect_command cmdCode Case: EFFECT_CMD_ENABLE NumberEffectsEnabled = %d",
diff --git a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
index 10c3e92..60f4288 100755
--- a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
+++ b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
@@ -152,6 +152,7 @@
bool preset;
uint16_t curPreset;
uint16_t nextPreset;
+ int SamplesToExitCount;
};
#define REVERB_DEFAULT_PRESET REVERB_PRESET_MEDIUMROOM
@@ -212,6 +213,7 @@
desc = gDescriptors[i];
if (memcmp(uuid, &desc->uuid, sizeof(effect_uuid_t))
== 0) {
+ LOGV("\tEffectCreate - UUID matched Reverb type %d, UUID = %x", i, desc->uuid.timeLow);
break;
}
}
@@ -228,6 +230,9 @@
pContext->auxiliary = false;
if ((desc->flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY){
pContext->auxiliary = true;
+ LOGV("\tEffectCreate - AUX");
+ }else{
+ LOGV("\tEffectCreate - INS");
}
pContext->preset = false;
@@ -236,6 +241,9 @@
// force reloading preset at first call to process()
pContext->curPreset = REVERB_PRESET_LAST + 1;
pContext->nextPreset = REVERB_DEFAULT_PRESET;
+ LOGV("\tEffectCreate - PRESET");
+ }else{
+ LOGV("\tEffectCreate - ENVIRONMENTAL");
}
LOGV("\tEffectCreate - Calling Reverb_init");
@@ -389,22 +397,19 @@
int frameCount,
ReverbContext *pContext){
- LVM_INT16 samplesPerFrame = 0;
+ LVM_INT16 samplesPerFrame = 1;
LVREV_ReturnStatus_en LvmStatus = LVREV_SUCCESS; /* Function call status */
LVM_INT16 *OutFrames16;
// Check that the input is either mono or stereo
- if(pContext->config.inputCfg.channels == CHANNEL_STEREO){
+ if (pContext->config.inputCfg.channels == CHANNEL_STEREO) {
samplesPerFrame = 2;
- } else if (pContext->config.inputCfg.channels == CHANNEL_MONO){
- samplesPerFrame = 1;
- } else {
+ } else if (pContext->config.inputCfg.channels != CHANNEL_MONO) {
LOGV("\tLVREV_ERROR : process invalid PCM format");
return -EINVAL;
}
-
OutFrames16 = (LVM_INT16 *)pContext->OutFrames32;
// Check for NULL pointers
@@ -426,54 +431,49 @@
pContext->InFrames32[i] = (LVM_INT32)pIn[i]<<8;
}
- // If the input was MONO, convert to STEREO
- if(pContext->config.inputCfg.channels == CHANNEL_MONO){
- //LOGV("\tConverting Output from MONO to STEREO");
- MonoTo2I_32(pContext->InFrames32, pContext->InFrames32, frameCount);
- }
-
- //LOGV("\tProcess, frames: %d, InFormat: %d(MONO=%d), OutFormat: %d(STEREO=%d)",
- //frameCount, pContext->config.inputCfg.channels, CHANNEL_MONO,
- //pContext->config.outputCfg.channels, CHANNEL_STEREO);
-
if (pContext->preset && pContext->curPreset == REVERB_PRESET_NONE) {
- memset(pContext->OutFrames32, 0, frameCount * sizeof(LVM_INT32) * 2);
+ memset(pContext->OutFrames32, 0, frameCount * sizeof(LVM_INT32) * 2); //always stereo here
} else {
- /* Process the samples */
- LvmStatus = LVREV_Process(pContext->hInstance, /* Instance handle */
- pContext->InFrames32, /* Input buffer */
- pContext->OutFrames32, /* Output buffer */
- frameCount); /* Number of samples to read */
- }
-
- if (!pContext->auxiliary) {
- for (int i=0; i<frameCount*2; i++){
- pContext->OutFrames32[i] += pContext->InFrames32[i];
+ if(pContext->bEnabled == LVM_FALSE && pContext->SamplesToExitCount > 0) {
+ memset(pContext->InFrames32,0,frameCount * sizeof(LVM_INT32) * samplesPerFrame);
+ LOGV("\tZeroing %d samples per frame at the end of call", samplesPerFrame);
}
+
+ /* Process the samples, producing a stereo output */
+ LvmStatus = LVREV_Process(pContext->hInstance, /* Instance handle */
+ pContext->InFrames32, /* Input buffer */
+ pContext->OutFrames32, /* Output buffer */
+ frameCount); /* Number of samples to read */
}
LVM_ERROR_CHECK(LvmStatus, "LVREV_Process", "process")
if(LvmStatus != LVREV_SUCCESS) return -EINVAL;
// Convert to 16 bits
- for(int i=0; i<frameCount*2; i++){ // Always stereo
- OutFrames16[i] = clamp16(pContext->OutFrames32[i]>>8);
+ if (pContext->auxiliary) {
+ for (int i=0; i < frameCount*2; i++) { //always stereo here
+ OutFrames16[i] = clamp16(pContext->OutFrames32[i]>>8);
+ }
+ } else {
+ for (int i=0; i < frameCount*2; i++) { //always stereo here
+ OutFrames16[i] = clamp16((pContext->OutFrames32[i]>>8) + (LVM_INT32)pIn[i]);
+ }
}
#ifdef LVM_PCM
- fwrite(OutFrames16, frameCount*sizeof(LVM_INT16)*samplesPerFrame, 1, pContext->PcmOutPtr);
+ fwrite(OutFrames16, frameCount*sizeof(LVM_INT16)*2, 1, pContext->PcmOutPtr);
fflush(pContext->PcmOutPtr);
#endif
// Accumulate if required
if (pContext->config.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE){
//LOGV("\tBuffer access is ACCUMULATE");
- for (int i=0; i<frameCount*2; i++){
+ for (int i=0; i<frameCount*2; i++){ //always stereo here
pOut[i] = clamp16((int32_t)pOut[i] + (int32_t)OutFrames16[i]);
}
}else{
//LOGV("\tBuffer access is WRITE");
- memcpy(pOut, OutFrames16, frameCount*sizeof(LVM_INT16)*2); // 2 is for stereo output
+ memcpy(pOut, OutFrames16, frameCount*sizeof(LVM_INT16)*2);
}
return 0;
@@ -560,6 +560,7 @@
//LOGV("\tReverb_configure calling memcpy");
memcpy(&pContext->config, pConfig, sizeof(effect_config_t));
+
switch (pConfig->inputCfg.samplingRate) {
case 8000:
SampleRate = LVM_FS_8000;
@@ -665,7 +666,7 @@
/* Set the capabilities */
InstParams.MaxBlockSize = MAX_CALL_SIZE;
- InstParams.SourceFormat = LVM_STEREO;
+ InstParams.SourceFormat = LVM_STEREO; // Max format, could be mono during process
InstParams.NumDelays = LVREV_DELAYLINES_4;
/* Allocate memory, forcing alignment */
@@ -730,7 +731,12 @@
/* General parameters */
params.OperatingMode = LVM_MODE_ON;
params.SampleRate = LVM_FS_44100;
- params.SourceFormat = LVM_STEREO;
+
+ if(pContext->config.inputCfg.channels == CHANNEL_MONO){
+ params.SourceFormat = LVM_MONO;
+ } else {
+ params.SourceFormat = LVM_STEREO;
+ }
/* Reverb parameters */
params.Level = 0;
@@ -741,6 +747,8 @@
params.Damping = 21;
params.RoomSize = 100;
+ pContext->SamplesToExitCount = (params.T60 * pContext->config.inputCfg.samplingRate)/1000;
+
/* Saved strength is used to return the exact strength that was used in the set to the get
* because we map the original strength range of 0:1000 to 1:15, and this will avoid
* quantisation like effect when returning
@@ -1082,7 +1090,8 @@
//LOGV("\tReverbGetRoomLevel, Level = %d, pContext->SavedRoomLevel = %d, "
// "pContext->SavedReverbLevel = %d, CombinedLevel = %d, level = %d",
- //ActiveParams.Level, pContext->SavedRoomLevel, pContext->SavedReverbLevel, CombinedLevel, level);
+ // ActiveParams.Level, pContext->SavedRoomLevel,
+ // pContext->SavedReverbLevel, CombinedLevel, level);
if(ActiveParams.Level != level){
LOGV("\tLVM_ERROR : (ignore at start up) ReverbGetRoomLevel() has wrong level -> %d %d\n",
@@ -1118,7 +1127,7 @@
//LOGV("\tReverbSetDecayTime() just Got -> %d\n", ActiveParams.T60);
if (time <= LVREV_MAX_T60) {
- ActiveParams.T60 = time;
+ ActiveParams.T60 = (LVM_UINT16)time;
}
else {
ActiveParams.T60 = LVREV_MAX_T60;
@@ -1129,7 +1138,9 @@
LVM_ERROR_CHECK(LvmStatus, "LVREV_SetControlParameters", "ReverbSetDecayTime")
//LOGV("\tReverbSetDecayTime() just Set -> %d\n", ActiveParams.T60);
- pContext->SavedDecayTime = time;
+ pContext->SamplesToExitCount = (ActiveParams.T60 * pContext->config.inputCfg.samplingRate)/1000;
+ //LOGV("\tReverbSetDecayTime() just Set SamplesToExitCount-> %d\n",pContext->SamplesToExitCount);
+ pContext->SavedDecayTime = (int16_t)time;
//LOGV("\tReverbSetDecayTime end");
return;
}
@@ -1145,7 +1156,7 @@
//
//----------------------------------------------------------------------------
-int32_t ReverbGetDecayTime(ReverbContext *pContext){
+uint32_t ReverbGetDecayTime(ReverbContext *pContext){
//LOGV("\tReverbGetDecayTime start");
LVREV_ControlParams_st ActiveParams; /* Current control Parameters */
@@ -1164,7 +1175,7 @@
}
//LOGV("\tReverbGetDecayTime end");
- return ActiveParams.T60;
+ return (uint32_t)ActiveParams.T60;
}
//----------------------------------------------------------------------------
@@ -1589,7 +1600,7 @@
// *(int16_t *)pValue);
break;
case REVERB_PARAM_DECAY_TIME:
- *(int32_t *)pValue = ReverbGetDecayTime(pContext);
+ *(uint32_t *)pValue = ReverbGetDecayTime(pContext);
//LOGV("\tReverb_getParameter() REVERB_PARAM_DECAY_TIME Value is %d",
// *(int32_t *)pValue);
@@ -1654,6 +1665,7 @@
int Reverb_setParameter (ReverbContext *pContext, void *pParam, void *pValue){
int status = 0;
int16_t level;
+ int16_t ratio;
uint32_t time;
t_reverb_settings *pProperties;
int32_t *pParamTemp = (int32_t *)pParam;
@@ -1671,6 +1683,7 @@
return -EINVAL;
}
pContext->nextPreset = preset;
+ return 0;
}
switch (param){
@@ -1707,10 +1720,10 @@
//LOGV("\tReverb_setParameter() Called ReverbSetDecayTime");
break;
case REVERB_PARAM_DECAY_HF_RATIO:
- time = *(int16_t *)pValue;
- //LOGV("\tReverb_setParameter() REVERB_PARAM_DECAY_HF_RATIO value is %d", time);
+ ratio = *(int16_t *)pValue;
+ //LOGV("\tReverb_setParameter() REVERB_PARAM_DECAY_HF_RATIO value is %d", ratio);
//LOGV("\tReverb_setParameter() Calling ReverbSetDecayHfRatio");
- ReverbSetDecayHfRatio(pContext, time);
+ ReverbSetDecayHfRatio(pContext, ratio);
//LOGV("\tReverb_setParameter() Called ReverbSetDecayHfRatio");
break;
case REVERB_PARAM_REVERB_LEVEL:
@@ -1721,17 +1734,17 @@
//LOGV("\tReverb_setParameter() Called ReverbSetReverbLevel");
break;
case REVERB_PARAM_DIFFUSION:
- time = *(int16_t *)pValue;
- //LOGV("\tReverb_setParameter() REVERB_PARAM_DECAY_DIFFUSION value is %d", time);
+ ratio = *(int16_t *)pValue;
+ //LOGV("\tReverb_setParameter() REVERB_PARAM_DECAY_DIFFUSION value is %d", ratio);
//LOGV("\tReverb_setParameter() Calling ReverbSetDiffusion");
- ReverbSetDiffusion(pContext, time);
+ ReverbSetDiffusion(pContext, ratio);
//LOGV("\tReverb_setParameter() Called ReverbSetDiffusion");
break;
case REVERB_PARAM_DENSITY:
- time = *(int16_t *)pValue;
- //LOGV("\tReverb_setParameter() REVERB_PARAM_DECAY_DENSITY value is %d", time);
+ ratio = *(int16_t *)pValue;
+ //LOGV("\tReverb_setParameter() REVERB_PARAM_DECAY_DENSITY value is %d", ratio);
//LOGV("\tReverb_setParameter() Calling ReverbSetDensity");
- ReverbSetDensity(pContext, time);
+ ReverbSetDensity(pContext, ratio);
//LOGV("\tReverb_setParameter() Called ReverbSetDensity");
break;
break;
@@ -1769,8 +1782,13 @@
return -EINVAL;
}
if (pContext->bEnabled == LVM_FALSE){
- LOGV("\tReverb_process() ERROR Effect is not enabled");
- return -ENODATA;
+ if( pContext->SamplesToExitCount > 0){
+ pContext->SamplesToExitCount -= outBuffer->frameCount;
+ LOGV("\tReverb_process() Effect is being stopped %d", pContext->SamplesToExitCount);
+ }else{
+ LOGV("\tReverb_process() Effect is being stopped");
+ return -ENODATA;
+ }
}
//LOGV("\tReverb_process() Calling process with %d frames", outBuffer->frameCount);
/* Process all the available frames, block processing is handled internalLY by the LVM bundle */
@@ -1791,6 +1809,9 @@
void *pReplyData){
android::ReverbContext * pContext = (android::ReverbContext *) self;
int retsize;
+ LVREV_ControlParams_st ActiveParams; /* Current control Parameters */
+ LVREV_ReturnStatus_en LvmStatus=LVREV_SUCCESS; /* Function call status */
+
if (pContext == NULL){
LOGV("\tLVM_ERROR : Reverb_command ERROR pContext == NULL");
@@ -1917,6 +1938,12 @@
}
*(int *)pReplyData = 0;
pContext->bEnabled = LVM_TRUE;
+ /* Get the current settings */
+ LvmStatus = LVREV_GetControlParameters(pContext->hInstance, &ActiveParams);
+ LVM_ERROR_CHECK(LvmStatus, "LVREV_GetControlParameters", "EFFECT_CMD_ENABLE")
+ pContext->SamplesToExitCount =
+ (ActiveParams.T60 * pContext->config.inputCfg.samplingRate)/1000;
+ //LOGV("\tEFFECT_CMD_ENABLE SamplesToExitCount = %d", pContext->SamplesToExitCount);
break;
case EFFECT_CMD_DISABLE:
//LOGV("\tReverb_command cmdCode Case: "
@@ -1939,8 +1966,8 @@
case EFFECT_CMD_SET_DEVICE:
case EFFECT_CMD_SET_VOLUME:
case EFFECT_CMD_SET_AUDIO_MODE:
- //LOGV("\tReverb_command cmdCode Case: "
- // "EFFECT_CMD_SET_DEVICE/EFFECT_CMD_SET_VOLUME/EFFECT_CMD_SET_AUDIO_MODE start");
+ //LOGV("\tReverb_command cmdCode Case: "
+ // "EFFECT_CMD_SET_DEVICE/EFFECT_CMD_SET_VOLUME/EFFECT_CMD_SET_AUDIO_MODE start");
break;
default:
diff --git a/media/libmedia/IOMX.cpp b/media/libmedia/IOMX.cpp
index f3804b8..40801a2 100644
--- a/media/libmedia/IOMX.cpp
+++ b/media/libmedia/IOMX.cpp
@@ -21,7 +21,9 @@
SET_PARAMETER,
GET_CONFIG,
SET_CONFIG,
+ ENABLE_GRAPHIC_BUFFERS,
USE_BUFFER,
+ USE_GRAPHIC_BUFFER,
ALLOC_BUFFER,
ALLOC_BUFFER_WITH_BACKUP,
FREE_BUFFER,
@@ -216,6 +218,19 @@
return reply.readInt32();
}
+ virtual status_t enableGraphicBuffers(
+ node_id node, OMX_U32 port_index, OMX_BOOL enable) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
+ data.writeIntPtr((intptr_t)node);
+ data.writeInt32(port_index);
+ data.writeInt32((uint32_t)enable);
+ remote()->transact(ENABLE_GRAPHIC_BUFFERS, data, &reply);
+
+ status_t err = reply.readInt32();
+ return err;
+ }
+
virtual status_t useBuffer(
node_id node, OMX_U32 port_index, const sp<IMemory> ¶ms,
buffer_id *buffer) {
@@ -238,6 +253,29 @@
return err;
}
+
+ virtual status_t useGraphicBuffer(
+ node_id node, OMX_U32 port_index,
+ const sp<GraphicBuffer> &graphicBuffer, buffer_id *buffer) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
+ data.writeIntPtr((intptr_t)node);
+ data.writeInt32(port_index);
+ data.write(*graphicBuffer);
+ remote()->transact(USE_GRAPHIC_BUFFER, data, &reply);
+
+ status_t err = reply.readInt32();
+ if (err != OK) {
+ *buffer = 0;
+
+ return err;
+ }
+
+ *buffer = (void*)reply.readIntPtr();
+
+ return err;
+ }
+
virtual status_t allocateBuffer(
node_id node, OMX_U32 port_index, size_t size,
buffer_id *buffer, void **buffer_data) {
@@ -541,6 +579,20 @@
return NO_ERROR;
}
+ case ENABLE_GRAPHIC_BUFFERS:
+ {
+ CHECK_INTERFACE(IOMX, data, reply);
+
+ node_id node = (void*)data.readIntPtr();
+ OMX_U32 port_index = data.readInt32();
+ OMX_BOOL enable = (OMX_BOOL)data.readInt32();
+
+ status_t err = enableGraphicBuffers(node, port_index, enable);
+ reply->writeInt32(err);
+
+ return NO_ERROR;
+ }
+
case USE_BUFFER:
{
CHECK_INTERFACE(IOMX, data, reply);
@@ -561,6 +613,27 @@
return NO_ERROR;
}
+ case USE_GRAPHIC_BUFFER:
+ {
+ CHECK_INTERFACE(IOMX, data, reply);
+
+ node_id node = (void*)data.readIntPtr();
+ OMX_U32 port_index = data.readInt32();
+ sp<GraphicBuffer> graphicBuffer = new GraphicBuffer();
+ data.read(*graphicBuffer);
+
+ buffer_id buffer;
+ status_t err = useGraphicBuffer(
+ node, port_index, graphicBuffer, &buffer);
+ reply->writeInt32(err);
+
+ if (err == OK) {
+ reply->writeIntPtr((intptr_t)buffer);
+ }
+
+ return NO_ERROR;
+ }
+
case ALLOC_BUFFER:
{
CHECK_INTERFACE(IOMX, data, reply);
diff --git a/media/libstagefright/AudioSource.cpp b/media/libstagefright/AudioSource.cpp
index 4c729e4..8d7ada3 100644
--- a/media/libstagefright/AudioSource.cpp
+++ b/media/libstagefright/AudioSource.cpp
@@ -72,6 +72,10 @@
return UNKNOWN_ERROR;
}
+ if (mInitCheck != OK) {
+ return NO_INIT;
+ }
+
char value[PROPERTY_VALUE_MAX];
if (property_get("media.stagefright.record-stats", value, NULL)
&& (!strcmp(value, "1") || !strcasecmp(value, "true"))) {
@@ -80,6 +84,7 @@
mTrackMaxAmplitude = false;
mMaxAmplitude = 0;
+ mInitialReadTimeUs = 0;
mStartTimeUs = 0;
int64_t startTimeUs;
if (params && params->findInt64(kKeyTime, &startTimeUs)) {
@@ -102,6 +107,10 @@
return UNKNOWN_ERROR;
}
+ if (mInitCheck != OK) {
+ return NO_INIT;
+ }
+
mRecord->stop();
delete mGroup;
@@ -118,6 +127,10 @@
}
sp<MetaData> AudioSource::getFormat() {
+ if (mInitCheck != OK) {
+ return 0;
+ }
+
sp<MetaData> meta = new MetaData;
meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
meta->setInt32(kKeySampleRate, mRecord->getSampleRate());
@@ -193,6 +206,12 @@
status_t AudioSource::read(
MediaBuffer **out, const ReadOptions *options) {
+
+ if (mInitCheck != OK) {
+ return NO_INIT;
+ }
+
+ int64_t readTimeUs = systemTime() / 1000;
*out = NULL;
MediaBuffer *buffer;
@@ -206,9 +225,10 @@
if (numFramesRecorded == 0 && mPrevSampleTimeUs == 0) {
+ mInitialReadTimeUs = readTimeUs;
// Initial delay
if (mStartTimeUs > 0) {
- mStartTimeUs = systemTime() / 1000 - mStartTimeUs;
+ mStartTimeUs = readTimeUs - mStartTimeUs;
} else {
// Assume latency is constant.
mStartTimeUs += mRecord->latency() * 1000;
@@ -254,7 +274,10 @@
}
memset(buffer->data(), 0, numLostBytes);
buffer->set_range(0, numLostBytes);
- buffer->meta_data()->setInt64(kKeyTime, mPrevSampleTimeUs);
+ if (numFramesRecorded == 0) {
+ buffer->meta_data()->setInt64(kKeyTime, mStartTimeUs);
+ }
+ buffer->meta_data()->setInt64(kKeyDriftTime, readTimeUs - mInitialReadTimeUs);
mPrevSampleTimeUs = timestampUs;
*out = buffer;
return OK;
@@ -292,12 +315,13 @@
trackMaxAmplitude((int16_t *) buffer->data(), n >> 1);
}
- buffer->meta_data()->setInt64(kKeyTime, mPrevSampleTimeUs);
- CHECK(timestampUs > mPrevSampleTimeUs);
- if (mTotalLostFrames == 0) {
- CHECK_EQ(mPrevSampleTimeUs,
- mStartTimeUs + (1000000LL * numFramesRecorded) / sampleRate);
+ if (numFramesRecorded == 0) {
+ buffer->meta_data()->setInt64(kKeyAnchorTime, mStartTimeUs);
}
+
+ buffer->meta_data()->setInt64(kKeyTime, mStartTimeUs + mPrevSampleTimeUs);
+ buffer->meta_data()->setInt64(kKeyDriftTime, readTimeUs - mInitialReadTimeUs);
+ CHECK(timestampUs > mPrevSampleTimeUs);
mPrevSampleTimeUs = timestampUs;
LOGV("initial delay: %lld, sample rate: %d, timestamp: %lld",
mStartTimeUs, sampleRate, timestampUs);
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index 085e92d..fd5f30b 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -50,6 +50,9 @@
namespace android {
+static int64_t kLowWaterMarkUs = 2000000ll; // 2secs
+static int64_t kHighWaterMarkUs = 10000000ll; // 10secs
+
struct AwesomeEvent : public TimedEventQueue::Event {
AwesomeEvent(
AwesomePlayer *player,
@@ -274,9 +277,13 @@
status_t AwesomePlayer::setDataSource(
int fd, int64_t offset, int64_t length) {
#if 0
+ // return setDataSource("httplive://qthttp.apple.com.edgesuite.net/1009qpeijrfn/sl.m3u8");
+ return setDataSource("httplive://qthttp.apple.com.edgesuite.net/1009qpeijrfn/0440.m3u8");
+ // return setDataSource("httplive://qthttp.apple.com.edgesuite.net/1009qpeijrfn/0640.m3u8");
+ // return setDataSource("httplive://qthttp.apple.com.edgesuite.net/1009qpeijrfn/1240_vod.m3u8");
// return setDataSource("httplive://iphoned5.akamai.com.edgesuite.net/mhbarron/nasatv/nasatv_96.m3u8");
// return setDataSource("httplive://iphoned5.akamai.com.edgesuite.net/mhbarron/nasatv/nasatv_1500.m3u8");
- return setDataSource("httplive://iphone.video.hsn.com/iPhone_high.m3u8");
+ // return setDataSource("httplive://iphone.video.hsn.com/iPhone_high.m3u8");
// return setDataSource("httplive://iphoned5.akamai.com.edgesuite.net/mhbarron/iphonewebcast/webcast090209_all/webcast090209_all.m3u8");
// return setDataSource("httplive://qthttp.akamai.com.edgesuite.net/iphone_demo/Video_Content/usat/tt_062209_iphone/hi/prog_index.m3u8");
// return setDataSource("httplive://qthttp.akamai.com.edgesuite.net/iphone_demo/Video_Content/usat/tt_googmaps/hi/prog_index.m3u8");
@@ -326,6 +333,13 @@
} else if (!haveAudio && !strncasecmp(mime, "audio/", 6)) {
setAudioSource(extractor->getTrack(i));
haveAudio = true;
+
+ sp<MetaData> fileMeta = extractor->getMetaData();
+ int32_t loop;
+ if (fileMeta != NULL
+ && fileMeta->findInt32(kKeyAutoLoop, &loop) && loop != 0) {
+ mFlags |= AUTO_LOOPING;
+ }
}
if (haveAudio && haveVideo) {
@@ -449,6 +463,25 @@
}
}
+// Returns true iff cached duration is available/applicable.
+bool AwesomePlayer::getCachedDuration_l(int64_t *durationUs, bool *eos) {
+ off_t totalSize;
+
+ if (mRTSPController != NULL) {
+ *durationUs = mRTSPController->getQueueDurationUs(eos);
+ return true;
+ } else if (mCachedSource != NULL && mDurationUs >= 0
+ && mCachedSource->getSize(&totalSize) == OK) {
+ int64_t bitrate = totalSize * 8000000ll / mDurationUs; // in bits/sec
+
+ size_t cachedDataRemaining = mCachedSource->approxDataRemaining(eos);
+ *durationUs = cachedDataRemaining * 8000000ll / bitrate;
+ return true;
+ }
+
+ return false;
+}
+
void AwesomePlayer::onBufferingUpdate() {
Mutex::Autolock autoLock(mLock);
if (!mBufferingEventPending) {
@@ -456,49 +489,80 @@
}
mBufferingEventPending = false;
- if (mCachedSource == NULL) {
- return;
- }
+ if (mCachedSource != NULL) {
+ bool eos;
+ size_t cachedDataRemaining = mCachedSource->approxDataRemaining(&eos);
- bool eos;
- size_t cachedDataRemaining = mCachedSource->approxDataRemaining(&eos);
+ if (eos) {
+ notifyListener_l(MEDIA_BUFFERING_UPDATE, 100);
+ } else {
+ off_t size;
+ if (mDurationUs >= 0 && mCachedSource->getSize(&size) == OK) {
+ int64_t bitrate = size * 8000000ll / mDurationUs; // in bits/sec
- size_t lowWatermark = 400000;
- size_t highWatermark = 1000000;
+ size_t cachedSize = mCachedSource->cachedSize();
+ int64_t cachedDurationUs = cachedSize * 8000000ll / bitrate;
- if (eos) {
- notifyListener_l(MEDIA_BUFFERING_UPDATE, 100);
- } else {
- off_t size;
- if (mDurationUs >= 0 && mCachedSource->getSize(&size) == OK) {
- int64_t bitrate = size * 8000000ll / mDurationUs; // in bits/sec
+ int percentage = 100.0 * (double)cachedDurationUs / mDurationUs;
+ if (percentage > 100) {
+ percentage = 100;
+ }
- size_t cachedSize = mCachedSource->cachedSize();
- int64_t cachedDurationUs = cachedSize * 8000000ll / bitrate;
+ notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage);
+ } else {
+ // We don't know the bitrate of the stream, use absolute size
+ // limits to maintain the cache.
- int percentage = 100.0 * (double)cachedDurationUs / mDurationUs;
- if (percentage > 100) {
- percentage = 100;
+ const size_t kLowWaterMarkBytes = 400000;
+ const size_t kHighWaterMarkBytes = 1000000;
+
+ if ((mFlags & PLAYING) && !eos
+ && (cachedDataRemaining < kLowWaterMarkBytes)) {
+ LOGI("cache is running low (< %d) , pausing.",
+ kLowWaterMarkBytes);
+ mFlags |= CACHE_UNDERRUN;
+ pause_l();
+ notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START);
+ } else if (eos || cachedDataRemaining > kHighWaterMarkBytes) {
+ if (mFlags & CACHE_UNDERRUN) {
+ LOGI("cache has filled up (> %d), resuming.",
+ kHighWaterMarkBytes);
+ mFlags &= ~CACHE_UNDERRUN;
+ play_l();
+ notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_END);
+ } else if (mFlags & PREPARING) {
+ LOGV("cache has filled up (> %d), prepare is done",
+ kHighWaterMarkBytes);
+ finishAsyncPrepare_l();
+ }
+ }
}
-
- notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage);
-
- lowWatermark = 2 * bitrate / 8; // 2 secs
- highWatermark = 10 * bitrate / 8; // 10 secs
}
}
- if ((mFlags & PLAYING) && !eos && (cachedDataRemaining < lowWatermark)) {
- LOGI("cache is running low (< %d) , pausing.", lowWatermark);
- mFlags |= CACHE_UNDERRUN;
- pause_l();
- notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START);
- } else if ((mFlags & CACHE_UNDERRUN)
- && (eos || cachedDataRemaining > highWatermark)) {
- LOGI("cache has filled up (> %d), resuming.", highWatermark);
- mFlags &= ~CACHE_UNDERRUN;
- play_l();
- notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_END);
+ int64_t cachedDurationUs;
+ bool eos;
+ if (getCachedDuration_l(&cachedDurationUs, &eos)) {
+ if ((mFlags & PLAYING) && !eos
+ && (cachedDurationUs < kLowWaterMarkUs)) {
+ LOGI("cache is running low (%.2f secs) , pausing.",
+ cachedDurationUs / 1E6);
+ mFlags |= CACHE_UNDERRUN;
+ pause_l();
+ notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START);
+ } else if (eos || cachedDurationUs > kHighWaterMarkUs) {
+ if (mFlags & CACHE_UNDERRUN) {
+ LOGI("cache has filled up (%.2f secs), resuming.",
+ cachedDurationUs / 1E6);
+ mFlags &= ~CACHE_UNDERRUN;
+ play_l();
+ notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_END);
+ } else if (mFlags & PREPARING) {
+ LOGV("cache has filled up (%.2f secs), prepare is done",
+ cachedDurationUs / 1E6);
+ finishAsyncPrepare_l();
+ }
+ }
}
postBufferingEvent_l();
@@ -533,7 +597,7 @@
return;
}
- if (mFlags & LOOPING) {
+ if (mFlags & (LOOPING | AUTO_LOOPING)) {
seekTo_l(0);
if (mVideoSource != NULL) {
@@ -1428,45 +1492,49 @@
}
void AwesomePlayer::onPrepareAsyncEvent() {
- {
- Mutex::Autolock autoLock(mLock);
+ Mutex::Autolock autoLock(mLock);
- if (mFlags & PREPARE_CANCELLED) {
- LOGI("prepare was cancelled before doing anything");
- abortPrepare(UNKNOWN_ERROR);
+ if (mFlags & PREPARE_CANCELLED) {
+ LOGI("prepare was cancelled before doing anything");
+ abortPrepare(UNKNOWN_ERROR);
+ return;
+ }
+
+ if (mUri.size() > 0) {
+ status_t err = finishSetDataSource_l();
+
+ if (err != OK) {
+ abortPrepare(err);
return;
}
-
- if (mUri.size() > 0) {
- status_t err = finishSetDataSource_l();
-
- if (err != OK) {
- abortPrepare(err);
- return;
- }
- }
-
- if (mVideoTrack != NULL && mVideoSource == NULL) {
- status_t err = initVideoDecoder();
-
- if (err != OK) {
- abortPrepare(err);
- return;
- }
- }
-
- if (mAudioTrack != NULL && mAudioSource == NULL) {
- status_t err = initAudioDecoder();
-
- if (err != OK) {
- abortPrepare(err);
- return;
- }
- }
}
- Mutex::Autolock autoLock(mLock);
+ if (mVideoTrack != NULL && mVideoSource == NULL) {
+ status_t err = initVideoDecoder();
+ if (err != OK) {
+ abortPrepare(err);
+ return;
+ }
+ }
+
+ if (mAudioTrack != NULL && mAudioSource == NULL) {
+ status_t err = initAudioDecoder();
+
+ if (err != OK) {
+ abortPrepare(err);
+ return;
+ }
+ }
+
+ if (mCachedSource != NULL || mRTSPController != NULL) {
+ postBufferingEvent_l();
+ } else {
+ finishAsyncPrepare_l();
+ }
+}
+
+void AwesomePlayer::finishAsyncPrepare_l() {
if (mIsAsyncPrepare) {
if (mVideoSource == NULL) {
notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0);
@@ -1482,8 +1550,6 @@
mFlags |= PREPARED;
mAsyncPrepareEvent = NULL;
mPreparedCondition.broadcast();
-
- postBufferingEvent_l();
}
status_t AwesomePlayer::suspend() {
@@ -1523,7 +1589,7 @@
state->mUriHeaders = mUriHeaders;
state->mFileSource = mFileSource;
- state->mFlags = mFlags & (PLAYING | LOOPING | AT_EOS);
+ state->mFlags = mFlags & (PLAYING | AUTO_LOOPING | LOOPING | AT_EOS);
getPosition(&state->mPositionUs);
if (mLastVideoBuffer) {
@@ -1584,7 +1650,7 @@
seekTo_l(state->mPositionUs);
- mFlags = state->mFlags & (LOOPING | AT_EOS);
+ mFlags = state->mFlags & (AUTO_LOOPING | LOOPING | AT_EOS);
if (state->mLastVideoFrame && (mSurface != NULL || mISurface != NULL)) {
mVideoRenderer =
diff --git a/media/libstagefright/MP3Extractor.cpp b/media/libstagefright/MP3Extractor.cpp
index 2e36968..82c0426 100644
--- a/media/libstagefright/MP3Extractor.cpp
+++ b/media/libstagefright/MP3Extractor.cpp
@@ -459,7 +459,8 @@
MP3Extractor::MP3Extractor(
const sp<DataSource> &source, const sp<AMessage> &meta)
- : mDataSource(source),
+ : mInitCheck(NO_INIT),
+ mDataSource(source),
mFirstFramePos(-1),
mFixedHeader(0),
mByteNumber(0) {
@@ -480,53 +481,54 @@
success = true;
} else {
success = Resync(mDataSource, 0, &pos, &header);
- CHECK(success);
}
- if (success) {
- mFirstFramePos = pos;
- mFixedHeader = header;
+ if (!success) {
+ // mInitCheck will remain NO_INIT
+ return;
+ }
- size_t frame_size;
- int sample_rate;
- int num_channels;
- int bitrate;
- get_mp3_frame_size(
- header, &frame_size, &sample_rate, &num_channels, &bitrate);
+ mFirstFramePos = pos;
+ mFixedHeader = header;
- mMeta = new MetaData;
+ size_t frame_size;
+ int sample_rate;
+ int num_channels;
+ int bitrate;
+ get_mp3_frame_size(
+ header, &frame_size, &sample_rate, &num_channels, &bitrate);
- mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG);
- mMeta->setInt32(kKeySampleRate, sample_rate);
- mMeta->setInt32(kKeyBitRate, bitrate * 1000);
- mMeta->setInt32(kKeyChannelCount, num_channels);
+ mMeta = new MetaData;
- int64_t duration;
- parse_xing_header(
- mDataSource, mFirstFramePos, NULL, &mByteNumber,
- mTableOfContents, NULL, &duration);
- if (duration > 0) {
- mMeta->setInt64(kKeyDuration, duration);
- } else {
- off_t fileSize;
- if (mDataSource->getSize(&fileSize) == OK) {
- mMeta->setInt64(
- kKeyDuration,
- 8000LL * (fileSize - mFirstFramePos) / bitrate);
- }
+ mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG);
+ mMeta->setInt32(kKeySampleRate, sample_rate);
+ mMeta->setInt32(kKeyBitRate, bitrate * 1000);
+ mMeta->setInt32(kKeyChannelCount, num_channels);
+
+ int64_t duration;
+ parse_xing_header(
+ mDataSource, mFirstFramePos, NULL, &mByteNumber,
+ mTableOfContents, NULL, &duration);
+ if (duration > 0) {
+ mMeta->setInt64(kKeyDuration, duration);
+ } else {
+ off_t fileSize;
+ if (mDataSource->getSize(&fileSize) == OK) {
+ mMeta->setInt64(
+ kKeyDuration,
+ 8000LL * (fileSize - mFirstFramePos) / bitrate);
}
}
-}
-MP3Extractor::~MP3Extractor() {
+ mInitCheck = OK;
}
size_t MP3Extractor::countTracks() {
- return (mFirstFramePos < 0) ? 0 : 1;
+ return mInitCheck != OK ? 0 : 1;
}
sp<MediaSource> MP3Extractor::getTrack(size_t index) {
- if (mFirstFramePos < 0 || index != 0) {
+ if (mInitCheck != OK || index != 0) {
return NULL;
}
@@ -536,7 +538,7 @@
}
sp<MetaData> MP3Extractor::getTrackMetaData(size_t index, uint32_t flags) {
- if (mFirstFramePos < 0 || index != 0) {
+ if (mInitCheck != OK || index != 0) {
return NULL;
}
@@ -713,7 +715,7 @@
sp<MetaData> MP3Extractor::getMetaData() {
sp<MetaData> meta = new MetaData;
- if (mFirstFramePos < 0) {
+ if (mInitCheck != OK) {
return meta;
}
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index ba90407..4bbc251 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -872,7 +872,11 @@
}
size_t max_size;
- CHECK_EQ(mLastTrack->sampleTable->getMaxSampleSize(&max_size), OK);
+ err = mLastTrack->sampleTable->getMaxSampleSize(&max_size);
+
+ if (err != OK) {
+ return err;
+ }
// Assume that a given buffer only contains at most 10 fragments,
// each fragment originally prefixed with a 2 byte length will
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index a15b84e..de4233d 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -32,12 +32,12 @@
#include <media/stagefright/MediaSource.h>
#include <media/stagefright/Utils.h>
#include <media/mediarecorder.h>
-#include <cutils/properties.h>
#include "include/ESDS.h"
namespace android {
+static const int64_t kMax32BitFileSize = 0x007fffffffLL;
static const uint8_t kNalUnitTypeSeqParamSet = 0x07;
static const uint8_t kNalUnitTypePicParamSet = 0x08;
@@ -59,7 +59,7 @@
bool isAvc() const { return mIsAvc; }
bool isAudio() const { return mIsAudio; }
bool isMPEG4() const { return mIsMPEG4; }
- void addChunkOffset(off_t offset) { mChunkOffsets.push_back(offset); }
+ void addChunkOffset(off_t offset);
status_t dump(int fd, const Vector<String16>& args) const;
private:
@@ -79,7 +79,7 @@
bool mIsRealTimeRecording;
int64_t mMaxTimeStampUs;
int64_t mEstimatedTrackSizeBytes;
- int64_t mMaxWriteTimeUs;
+ int64_t mMdatSizeBytes;
int32_t mTimeScale;
pthread_t mThread;
@@ -92,8 +92,11 @@
bool mSamplesHaveSameSize;
List<MediaBuffer *> mChunkSamples;
+
+ size_t mNumStcoTableEntries;
List<off_t> mChunkOffsets;
+ size_t mNumStscTableEntries;
struct StscTableEntry {
StscTableEntry(uint32_t chunk, uint32_t samples, uint32_t id)
@@ -107,9 +110,10 @@
};
List<StscTableEntry> mStscTableEntries;
+ size_t mNumStssTableEntries;
List<int32_t> mStssTableEntries;
- List<int64_t> mChunkDurations;
+ size_t mNumSttsTableEntries;
struct SttsTableEntry {
SttsTableEntry(uint32_t count, uint32_t durationUs)
@@ -161,12 +165,6 @@
void trackProgressStatus(int64_t timeUs, status_t err = OK);
void initTrackingProgressStatus(MetaData *params);
- // Utilities for collecting statistical data
- void logStatisticalData(bool isAudio);
- void findMinAvgMaxSampleDurationMs(
- int32_t *min, int32_t *avg, int32_t *max);
- void findMinMaxChunkDurations(int64_t *min, int64_t *max);
-
void getCodecSpecificDataFromInputFormatIfPossible();
// Determine the track time scale
@@ -178,14 +176,18 @@
// Simple validation on the codec specific data
status_t checkCodecSpecificData() const;
+ void updateTrackSizeEstimate();
+ void addOneStscTableEntry(size_t chunkId, size_t sampleId);
+ void addOneStssTableEntry(size_t sampleId);
+ void addOneSttsTableEntry(size_t sampleCount, int64_t durationUs);
+
Track(const Track &);
Track &operator=(const Track &);
};
-#define USE_NALLEN_FOUR 1
-
MPEG4Writer::MPEG4Writer(const char *filename)
: mFile(fopen(filename, "wb")),
+ mUse4ByteNalLength(true),
mUse32BitOffset(true),
mPaused(false),
mStarted(false),
@@ -198,6 +200,7 @@
MPEG4Writer::MPEG4Writer(int fd)
: mFile(fdopen(fd, "wb")),
+ mUse4ByteNalLength(true),
mUse32BitOffset(true),
mPaused(false),
mStarted(false),
@@ -211,9 +214,11 @@
MPEG4Writer::~MPEG4Writer() {
stop();
- for (List<Track *>::iterator it = mTracks.begin();
- it != mTracks.end(); ++it) {
+ while (!mTracks.empty()) {
+ List<Track *>::iterator it = mTracks.begin();
delete *it;
+ (*it) = NULL;
+ mTracks.erase(it);
}
mTracks.clear();
}
@@ -332,11 +337,27 @@
mUse32BitOffset = false;
}
- // System property can overwrite the file offset bits parameter
- char value[PROPERTY_VALUE_MAX];
- if (property_get("media.stagefright.record-64bits", value, NULL)
- && (!strcmp(value, "1") || !strcasecmp(value, "true"))) {
- mUse32BitOffset = false;
+ if (mUse32BitOffset) {
+ // Implicit 32 bit file size limit
+ if (mMaxFileSizeLimitBytes == 0) {
+ mMaxFileSizeLimitBytes = kMax32BitFileSize;
+ }
+
+ // If file size is set to be larger than the 32 bit file
+ // size limit, treat it as an error.
+ if (mMaxFileSizeLimitBytes > kMax32BitFileSize) {
+ LOGW("32-bi file size limit (%lld bytes) too big. "
+ "It is changed to %lld bytes",
+ mMaxFileSizeLimitBytes, kMax32BitFileSize);
+ mMaxFileSizeLimitBytes = kMax32BitFileSize;
+ }
+ }
+
+ int32_t use2ByteNalLength;
+ if (param &&
+ param->findInt32(kKey2ByteNalLength, &use2ByteNalLength) &&
+ use2ByteNalLength) {
+ mUse4ByteNalLength = false;
}
mStartTimestampUs = -1;
@@ -413,6 +434,10 @@
return OK;
}
+bool MPEG4Writer::use32BitFileOffset() const {
+ return mUse32BitOffset;
+}
+
status_t MPEG4Writer::pause() {
if (mFile == NULL) {
return OK;
@@ -607,32 +632,30 @@
size_t length = buffer->range_length();
-#if USE_NALLEN_FOUR
- uint8_t x = length >> 24;
- fwrite(&x, 1, 1, mFile);
- x = (length >> 16) & 0xff;
- fwrite(&x, 1, 1, mFile);
- x = (length >> 8) & 0xff;
- fwrite(&x, 1, 1, mFile);
- x = length & 0xff;
- fwrite(&x, 1, 1, mFile);
-#else
- CHECK(length < 65536);
+ if (mUse4ByteNalLength) {
+ uint8_t x = length >> 24;
+ fwrite(&x, 1, 1, mFile);
+ x = (length >> 16) & 0xff;
+ fwrite(&x, 1, 1, mFile);
+ x = (length >> 8) & 0xff;
+ fwrite(&x, 1, 1, mFile);
+ x = length & 0xff;
+ fwrite(&x, 1, 1, mFile);
- uint8_t x = length >> 8;
- fwrite(&x, 1, 1, mFile);
- x = length & 0xff;
- fwrite(&x, 1, 1, mFile);
-#endif
+ fwrite((const uint8_t *)buffer->data() + buffer->range_offset(),
+ 1, length, mFile);
+ mOffset += length + 4;
+ } else {
+ CHECK(length < 65536);
- fwrite((const uint8_t *)buffer->data() + buffer->range_offset(),
- 1, length, mFile);
-
-#if USE_NALLEN_FOUR
- mOffset += length + 4;
-#else
- mOffset += length + 2;
-#endif
+ uint8_t x = length >> 8;
+ fwrite(&x, 1, 1, mFile);
+ x = length & 0xff;
+ fwrite(&x, 1, 1, mFile);
+ fwrite((const uint8_t *)buffer->data() + buffer->range_offset(),
+ 1, length, mFile);
+ mOffset += length + 2;
+ }
return old_offset;
}
@@ -739,7 +762,8 @@
it != mTracks.end(); ++it) {
nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes();
}
- return (nTotalBytesEstimate >= mMaxFileSizeLimitBytes);
+
+ return (nTotalBytesEstimate + 1024 >= mMaxFileSizeLimitBytes);
}
bool MPEG4Writer::exceedsFileDurationLimit() {
@@ -819,6 +843,48 @@
setTimeScale();
}
+void MPEG4Writer::Track::updateTrackSizeEstimate() {
+
+ int64_t stcoBoxSizeBytes = mOwner->use32BitFileOffset()
+ ? mNumStcoTableEntries * 4
+ : mNumStcoTableEntries * 8;
+
+ int64_t stszBoxSizeBytes = mSamplesHaveSameSize? 4: (mNumSamples * 4);
+
+ mEstimatedTrackSizeBytes = mMdatSizeBytes + // media data size
+ mNumStscTableEntries * 12 + // stsc box size
+ mNumStssTableEntries * 4 + // stss box size
+ mNumSttsTableEntries * 8 + // stts box size
+ stcoBoxSizeBytes + // stco box size
+ stszBoxSizeBytes; // stsz box size
+}
+
+void MPEG4Writer::Track::addOneStscTableEntry(
+ size_t chunkId, size_t sampleId) {
+
+ StscTableEntry stscEntry(chunkId, sampleId, 1);
+ mStscTableEntries.push_back(stscEntry);
+ ++mNumStscTableEntries;
+}
+
+void MPEG4Writer::Track::addOneStssTableEntry(size_t sampleId) {
+ mStssTableEntries.push_back(sampleId);
+ ++mNumStssTableEntries;
+}
+
+void MPEG4Writer::Track::addOneSttsTableEntry(
+ size_t sampleCount, int64_t durationUs) {
+
+ SttsTableEntry sttsEntry(sampleCount, durationUs);
+ mSttsTableEntries.push_back(sttsEntry);
+ ++mNumSttsTableEntries;
+}
+
+void MPEG4Writer::Track::addChunkOffset(off_t offset) {
+ ++mNumStcoTableEntries;
+ mChunkOffsets.push_back(offset);
+}
+
void MPEG4Writer::Track::setTimeScale() {
LOGV("setTimeScale");
// Default time scale
@@ -1039,6 +1105,7 @@
return OK;
}
+
status_t MPEG4Writer::Track::start(MetaData *params) {
if (!mDone && mPaused) {
mPaused = false;
@@ -1077,6 +1144,11 @@
mTrackDurationUs = 0;
mReachedEOS = false;
mEstimatedTrackSizeBytes = 0;
+ mNumStcoTableEntries = 0;
+ mNumStssTableEntries = 0;
+ mNumStscTableEntries = 0;
+ mNumSttsTableEntries = 0;
+ mMdatSizeBytes = 0;
pthread_create(&mThread, &attr, ThreadWrapper, this);
pthread_attr_destroy(&attr);
@@ -1123,46 +1195,6 @@
return (void *) err;
}
-#include <ctype.h>
-static void hexdump(const void *_data, size_t size) {
- const uint8_t *data = (const uint8_t *)_data;
- size_t offset = 0;
- while (offset < size) {
- printf("0x%04x ", offset);
-
- size_t n = size - offset;
- if (n > 16) {
- n = 16;
- }
-
- for (size_t i = 0; i < 16; ++i) {
- if (i == 8) {
- printf(" ");
- }
-
- if (offset + i < size) {
- printf("%02x ", data[offset + i]);
- } else {
- printf(" ");
- }
- }
-
- printf(" ");
-
- for (size_t i = 0; i < n; ++i) {
- if (isprint(data[offset + i])) {
- printf("%c", data[offset + i]);
- } else {
- printf(".");
- }
- }
-
- printf("\n");
-
- offset += 16;
- }
-}
-
static void getNalUnitType(uint8_t byte, uint8_t* type) {
LOGV("getNalUnitType: %d", byte);
@@ -1334,7 +1366,6 @@
status_t MPEG4Writer::Track::makeAVCCodecSpecificData(
const uint8_t *data, size_t size) {
- // hexdump(data, size);
if (mCodecSpecificData != NULL) {
LOGE("Already have codec specific data");
@@ -1365,11 +1396,11 @@
header[3] = mLevelIdc;
// 6-bit '111111' followed by 2-bit to lengthSizeMinuusOne
-#if USE_NALLEN_FOUR
- header[4] = 0xfc | 3; // length size == 4 bytes
-#else
- header[4] = 0xfc | 1; // length size == 2 bytes
-#endif
+ if (mOwner->useNalLengthFour()) {
+ header[4] = 0xfc | 3; // length size == 4 bytes
+ } else {
+ header[4] = 0xfc | 1; // length size == 2 bytes
+ }
// 3-bit '111' followed by 5-bit numSequenceParameterSets
int nSequenceParamSets = mSeqParamSets.size();
@@ -1406,15 +1437,6 @@
return OK;
}
-static bool collectStatisticalData() {
- char value[PROPERTY_VALUE_MAX];
- if (property_get("media.stagefright.record-stats", value, NULL)
- && (!strcmp(value, "1") || !strcasecmp(value, "true"))) {
- return true;
- }
- return false;
-}
-
status_t MPEG4Writer::Track::threadEntry() {
int32_t count = 0;
const int64_t interleaveDurationUs = mOwner->interleaveDuration();
@@ -1430,14 +1452,9 @@
int64_t previousPausedDurationUs = 0;
int64_t timestampUs;
- int64_t wallClockTimeUs = 0;
- int64_t lastWallClockTimeUs = 0;
-
sp<MetaData> meta_data;
- bool collectStats = collectStatisticalData();
mNumSamples = 0;
- mMaxWriteTimeUs = 0;
status_t err = OK;
MediaBuffer *buffer;
while (!mDone && (err = mSource->read(&buffer)) == OK) {
@@ -1498,17 +1515,19 @@
if (mIsAvc) StripStartcode(copy);
- size_t sampleSize;
- sampleSize = mIsAvc
-#if USE_NALLEN_FOUR
- ? copy->range_length() + 4
-#else
- ? copy->range_length() + 2
-#endif
- : copy->range_length();
+ size_t sampleSize = copy->range_length();
+ if (mIsAvc) {
+ if (mOwner->useNalLengthFour()) {
+ sampleSize += 4;
+ } else {
+ sampleSize += 2;
+ }
+ }
// Max file size or duration handling
- mEstimatedTrackSizeBytes += sampleSize;
+ mMdatSizeBytes += sampleSize;
+ updateTrackSizeEstimate();
+
if (mOwner->exceedsFileSizeLimit()) {
mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0);
break;
@@ -1542,14 +1561,15 @@
// of neighboring samples. This in turn helps reduce the track header size,
// especially, the number of entries in the "stts" box.
if (mNumSamples > 1) {
- int64_t durationUs = timestampUs + mOwner->getDriftTimeUs() - lastTimestampUs;
+ int64_t currDriftTimeUs = mOwner->getDriftTimeUs();
+ int64_t durationUs = timestampUs + currDriftTimeUs - lastTimestampUs;
int64_t diffUs = (durationUs > lastDurationUs)
? durationUs - lastDurationUs
: lastDurationUs - durationUs;
if (diffUs <= 5000) { // XXX: Magic number 5ms
timestampUs = lastTimestampUs + lastDurationUs;
} else {
- timestampUs += mOwner->getDriftTimeUs();
+ timestampUs += currDriftTimeUs;
}
}
}
@@ -1557,12 +1577,6 @@
if (mNumSamples > 1) {
if (timestampUs <= lastTimestampUs) {
LOGW("Frame arrives too late!");
-#if 0
- // Drop the late frame.
- copy->release();
- copy = NULL;
- continue;
-#else
// Don't drop the late frame, since dropping a frame may cause
// problems later during playback
@@ -1573,7 +1587,6 @@
} else {
timestampUs = lastTimestampUs + (1000000LL + (mTimeScale >> 1)) / mTimeScale;
}
-#endif
}
}
@@ -1596,8 +1609,7 @@
(lastTimestampUs * mTimeScale + 500000LL) / 1000000LL);
if (currDurationTicks != lastDurationTicks) {
- SttsTableEntry sttsEntry(sampleCount, lastDurationUs);
- mSttsTableEntries.push_back(sttsEntry);
+ addOneSttsTableEntry(sampleCount, lastDurationUs);
sampleCount = 1;
} else {
++sampleCount;
@@ -1613,16 +1625,14 @@
lastDurationTicks = currDurationTicks;
lastTimestampUs = timestampUs;
if (mIsRealTimeRecording && mIsAudio) {
- wallClockTimeUs = systemTime() / 1000;
- int64_t wallClockDurationUs = wallClockTimeUs - lastWallClockTimeUs;
- if (mNumSamples > 2) {
- mOwner->addDriftTimeUs(lastDurationUs - wallClockDurationUs);
+ int64_t driftTimeUs = 0;
+ if (meta_data->findInt64(kKeyDriftTime, &driftTimeUs)) {
+ mOwner->setDriftTimeUs(driftTimeUs);
}
- lastWallClockTimeUs = wallClockTimeUs;
}
if (isSync != 0) {
- mStssTableEntries.push_back(mNumSamples);
+ addOneStssTableEntry(mNumSamples);
}
if (mTrackingProgressStatus) {
@@ -1635,7 +1645,7 @@
off_t offset = mIsAvc? mOwner->addLengthPrefixedSample_l(copy)
: mOwner->addSample_l(copy);
if (mChunkOffsets.empty()) {
- mChunkOffsets.push_back(offset);
+ addChunkOffset(offset);
}
copy->release();
copy = NULL;
@@ -1644,8 +1654,7 @@
mChunkSamples.push_back(copy);
if (interleaveDurationUs == 0) {
- StscTableEntry stscEntry(++nChunks, 1, 1);
- mStscTableEntries.push_back(stscEntry);
+ addOneStscTableEntry(++nChunks, 1);
bufferChunk(timestampUs);
} else {
if (chunkTimestampUs == 0) {
@@ -1653,15 +1662,10 @@
} else {
if (timestampUs - chunkTimestampUs > interleaveDurationUs) {
++nChunks;
- if (collectStats) {
- mChunkDurations.push_back(timestampUs - chunkTimestampUs);
- }
if (nChunks == 1 || // First chunk
(--(mStscTableEntries.end()))->samplesPerChunk !=
mChunkSamples.size()) {
- StscTableEntry stscEntry(nChunks,
- mChunkSamples.size(), 1);
- mStscTableEntries.push_back(stscEntry);
+ addOneStscTableEntry(nChunks, mChunkSamples.size());
}
bufferChunk(timestampUs);
chunkTimestampUs = timestampUs;
@@ -1680,12 +1684,9 @@
// Last chunk
if (mOwner->numTracks() == 1) {
- StscTableEntry stscEntry(1, mNumSamples, 1);
- mStscTableEntries.push_back(stscEntry);
+ addOneStscTableEntry(1, mNumSamples);
} else if (!mChunkSamples.empty()) {
- ++nChunks;
- StscTableEntry stscEntry(nChunks, mChunkSamples.size(), 1);
- mStscTableEntries.push_back(stscEntry);
+ addOneStscTableEntry(++nChunks, mChunkSamples.size());
bufferChunk(timestampUs);
}
@@ -1697,14 +1698,12 @@
} else {
++sampleCount; // Count for the last sample
}
- SttsTableEntry sttsEntry(sampleCount, lastDurationUs);
- mSttsTableEntries.push_back(sttsEntry);
+ addOneSttsTableEntry(sampleCount, lastDurationUs);
mTrackDurationUs += lastDurationUs;
mReachedEOS = true;
- LOGI("Received total/0-length (%d/%d) buffers and encoded %d frames. Max write time: %lld us - %s",
- count, nZeroLengthFrames, mNumSamples, mMaxWriteTimeUs, mIsAudio? "audio": "video");
+ LOGI("Received total/0-length (%d/%d) buffers and encoded %d frames. - %s",
+ count, nZeroLengthFrames, mNumSamples, mIsAudio? "audio": "video");
- logStatisticalData(mIsAudio);
if (err == ERROR_END_OF_STREAM) {
return OK;
}
@@ -1729,17 +1728,6 @@
CHECK(nTracks < 64); // Arbitrary number
int32_t trackNum = 0;
-#if 0
- // In the worst case, we can put the trackNum
- // along with MEDIA_RECORDER_INFO_COMPLETION_STATUS
- // to report the progress.
- for (List<Track *>::iterator it = mTracks.begin();
- it != mTracks.end(); ++it, ++trackNum) {
- if (track == (*it)) {
- break;
- }
- }
-#endif
CHECK(trackNum < nTracks);
trackNum <<= 16;
@@ -1766,95 +1754,10 @@
}
}
-void MPEG4Writer::Track::findMinAvgMaxSampleDurationMs(
- int32_t *min, int32_t *avg, int32_t *max) {
- CHECK(!mSampleSizes.empty());
- int32_t avgSampleDurationMs = mTrackDurationUs / 1000 / mNumSamples;
- int32_t minSampleDurationMs = 0x7FFFFFFF;
- int32_t maxSampleDurationMs = 0;
- for (List<SttsTableEntry>::iterator it = mSttsTableEntries.begin();
- it != mSttsTableEntries.end(); ++it) {
- int32_t sampleDurationMs =
- (static_cast<int32_t>(it->sampleDurationUs) + 500) / 1000;
- if (sampleDurationMs > maxSampleDurationMs) {
- maxSampleDurationMs = sampleDurationMs;
- } else if (sampleDurationMs < minSampleDurationMs) {
- minSampleDurationMs = sampleDurationMs;
- }
- LOGI("sample duration: %d ms", sampleDurationMs);
- }
- CHECK(minSampleDurationMs != 0);
- CHECK(avgSampleDurationMs != 0);
- CHECK(maxSampleDurationMs != 0);
- *min = minSampleDurationMs;
- *avg = avgSampleDurationMs;
- *max = maxSampleDurationMs;
-}
-
-// Don't count the last duration
-void MPEG4Writer::Track::findMinMaxChunkDurations(int64_t *min, int64_t *max) {
- int64_t duration = mOwner->interleaveDuration();
- int64_t minChunkDuration = duration;
- int64_t maxChunkDuration = duration;
- if (mChunkDurations.size() > 1) {
- for (List<int64_t>::iterator it = mChunkDurations.begin();
- it != --mChunkDurations.end(); ++it) {
- if (minChunkDuration > (*it)) {
- minChunkDuration = (*it);
- } else if (maxChunkDuration < (*it)) {
- maxChunkDuration = (*it);
- }
- }
- }
- *min = minChunkDuration;
- *max = maxChunkDuration;
-}
-
-void MPEG4Writer::Track::logStatisticalData(bool isAudio) {
- if (mTrackDurationUs <= 0 || mSampleSizes.empty()) {
- LOGI("nothing is recorded");
- return;
- }
-
- bool collectStats = collectStatisticalData();
-
- if (collectStats) {
- LOGI("%s track - duration %lld us, total %d frames",
- isAudio? "audio": "video", mTrackDurationUs,
- mNumSamples);
- int32_t min, avg, max;
- findMinAvgMaxSampleDurationMs(&min, &avg, &max);
- LOGI("min/avg/max sample duration (ms): %d/%d/%d", min, avg, max);
- if (!isAudio) {
- float avgFps = 1000.0 / avg;
- float minFps = 1000.0 / max;
- float maxFps = 1000.0 / min;
- LOGI("min/avg/max frame rate (fps): %.2f/%.2f/%.2f",
- minFps, avgFps, maxFps);
- }
-
- int64_t totalBytes = 0;
- for (List<size_t>::iterator it = mSampleSizes.begin();
- it != mSampleSizes.end(); ++it) {
- totalBytes += (*it);
- }
- float bitRate = (totalBytes * 8000000.0) / mTrackDurationUs;
- LOGI("avg bit rate (bps): %.2f", bitRate);
-
- int64_t duration = mOwner->interleaveDuration();
- if (duration != 0) { // If interleaving is enabled
- int64_t minChunk, maxChunk;
- findMinMaxChunkDurations(&minChunk, &maxChunk);
- LOGI("min/avg/max chunk duration (ms): %lld/%lld/%lld",
- minChunk, duration, maxChunk);
- }
- }
-}
-
-void MPEG4Writer::addDriftTimeUs(int64_t driftTimeUs) {
- LOGV("addDriftTimeUs: %lld us", driftTimeUs);
+void MPEG4Writer::setDriftTimeUs(int64_t driftTimeUs) {
+ LOGV("setDriftTimeUs: %lld us", driftTimeUs);
Mutex::Autolock autolock(mLock);
- mDriftTimeUs += driftTimeUs;
+ mDriftTimeUs = driftTimeUs;
}
int64_t MPEG4Writer::getDriftTimeUs() {
@@ -1863,17 +1766,16 @@
return mDriftTimeUs;
}
+bool MPEG4Writer::useNalLengthFour() {
+ return mUse4ByteNalLength;
+}
+
void MPEG4Writer::Track::bufferChunk(int64_t timestampUs) {
LOGV("bufferChunk");
- int64_t startTimeUs = systemTime() / 1000;
Chunk chunk(this, timestampUs, mChunkSamples);
mOwner->bufferChunk(chunk);
mChunkSamples.clear();
- int64_t endTimeUs = systemTime() / 1000;
- if (mMaxWriteTimeUs < endTimeUs - startTimeUs) {
- mMaxWriteTimeUs = endTimeUs - startTimeUs;
- }
}
int64_t MPEG4Writer::Track::getDurationUs() const {
@@ -2226,7 +2128,7 @@
mOwner->beginBox("stts");
mOwner->writeInt32(0); // version=0, flags=0
- mOwner->writeInt32(mSttsTableEntries.size());
+ mOwner->writeInt32(mNumSttsTableEntries);
int64_t prevTimestampUs = 0;
for (List<SttsTableEntry>::iterator it = mSttsTableEntries.begin();
it != mSttsTableEntries.end(); ++it) {
@@ -2246,7 +2148,7 @@
if (!mIsAudio) {
mOwner->beginBox("stss");
mOwner->writeInt32(0); // version=0, flags=0
- mOwner->writeInt32(mStssTableEntries.size()); // number of sync frames
+ mOwner->writeInt32(mNumStssTableEntries); // number of sync frames
for (List<int32_t>::iterator it = mStssTableEntries.begin();
it != mStssTableEntries.end(); ++it) {
mOwner->writeInt32(*it);
@@ -2273,7 +2175,7 @@
mOwner->beginBox("stsc");
mOwner->writeInt32(0); // version=0, flags=0
- mOwner->writeInt32(mStscTableEntries.size());
+ mOwner->writeInt32(mNumStscTableEntries);
for (List<StscTableEntry>::iterator it = mStscTableEntries.begin();
it != mStscTableEntries.end(); ++it) {
mOwner->writeInt32(it->firstChunk);
@@ -2283,7 +2185,7 @@
mOwner->endBox(); // stsc
mOwner->beginBox(use32BitOffset? "stco": "co64");
mOwner->writeInt32(0); // version=0, flags=0
- mOwner->writeInt32(mChunkOffsets.size());
+ mOwner->writeInt32(mNumStcoTableEntries);
for (List<off_t>::iterator it = mChunkOffsets.begin();
it != mChunkOffsets.end(); ++it) {
if (use32BitOffset) {
diff --git a/media/libstagefright/OggExtractor.cpp b/media/libstagefright/OggExtractor.cpp
index 2c1311a..7a8cf32 100644
--- a/media/libstagefright/OggExtractor.cpp
+++ b/media/libstagefright/OggExtractor.cpp
@@ -592,6 +592,7 @@
{ "DATE", kKeyDate },
{ "LYRICIST", kKeyWriter },
{ "METADATA_BLOCK_PICTURE", kKeyAlbumArt },
+ { "ANDROID_LOOP", kKeyAutoLoop },
};
for (int i = 0; i < mVc.comments; ++i) {
@@ -605,12 +606,15 @@
extractAlbumArt(
&comment[tagLen + 1],
mVc.comment_lengths[i] - tagLen - 1);
+ } else if (kMap[j].mKey == kKeyAutoLoop) {
+ if (!strcasecmp(&comment[tagLen + 1], "true")) {
+ mFileMeta->setInt32(kKeyAutoLoop, true);
+ }
} else {
mFileMeta->setCString(kMap[j].mKey, &comment[tagLen + 1]);
}
}
}
-
}
#if 0
diff --git a/media/libstagefright/TimedEventQueue.cpp b/media/libstagefright/TimedEventQueue.cpp
index 0dacb53..5a453e9 100644
--- a/media/libstagefright/TimedEventQueue.cpp
+++ b/media/libstagefright/TimedEventQueue.cpp
@@ -26,6 +26,8 @@
#include "include/TimedEventQueue.h"
+#include <cutils/sched_policy.h>
+
#include <sys/prctl.h>
#include <sys/time.h>
#include <sys/resource.h>
@@ -209,6 +211,8 @@
#endif
setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_FOREGROUND);
+ set_sched_policy(androidGetTid(), SP_FOREGROUND);
+
static_cast<TimedEventQueue *>(me)->threadEntry();
#ifdef ANDROID_SIMULATOR
diff --git a/media/libstagefright/codecs/aacenc/AACEncoder.cpp b/media/libstagefright/codecs/aacenc/AACEncoder.cpp
index 052c354..df9f107 100644
--- a/media/libstagefright/codecs/aacenc/AACEncoder.cpp
+++ b/media/libstagefright/codecs/aacenc/AACEncoder.cpp
@@ -208,6 +208,8 @@
MediaBuffer *buffer;
CHECK_EQ(mBufferGroup->acquire_buffer(&buffer), OK);
uint8_t *outPtr = (uint8_t *)buffer->data();
+ bool readFromSource = false;
+ int64_t wallClockTimeUs = -1;
if (mFrameCount == 0) {
memcpy(outPtr, mAudioSpecificConfigData, 2);
@@ -238,9 +240,15 @@
CHECK_EQ(align, 0);
int64_t timeUs;
- if (mInputBuffer->meta_data()->findInt64(kKeyTime, &timeUs)) {
+ if (mInputBuffer->meta_data()->findInt64(kKeyDriftTime, &timeUs)) {
+ wallClockTimeUs = timeUs;
+ }
+ if (mInputBuffer->meta_data()->findInt64(kKeyAnchorTime, &timeUs)) {
mAnchorTimeUs = timeUs;
}
+ readFromSource = true;
+ } else {
+ readFromSource = false;
}
size_t copy =
(kNumSamplesPerFrame - mNumInputSamples) * sizeof(int16_t);
@@ -288,9 +296,13 @@
CHECK(outputData.Length != 0);
buffer->set_range(0, outputData.Length);
- int64_t timestampUs = ((mFrameCount - 1) * 1000000LL * kNumSamplesPerFrame) / mSampleRate;
+ int64_t mediaTimeUs =
+ ((mFrameCount - 1) * 1000000LL * kNumSamplesPerFrame) / mSampleRate;
+ buffer->meta_data()->setInt64(kKeyTime, mAnchorTimeUs + mediaTimeUs);
+ if (readFromSource && wallClockTimeUs != -1) {
+ buffer->meta_data()->setInt64(kKeyDriftTime, mediaTimeUs - wallClockTimeUs);
+ }
++mFrameCount;
- buffer->meta_data()->setInt64(kKeyTime, timestampUs);
*out = buffer;
return OK;
diff --git a/media/libstagefright/codecs/amrnb/enc/AMRNBEncoder.cpp b/media/libstagefright/codecs/amrnb/enc/AMRNBEncoder.cpp
index c875426..94a79ab 100644
--- a/media/libstagefright/codecs/amrnb/enc/AMRNBEncoder.cpp
+++ b/media/libstagefright/codecs/amrnb/enc/AMRNBEncoder.cpp
@@ -147,6 +147,8 @@
int64_t seekTimeUs;
ReadOptions::SeekMode mode;
CHECK(options == NULL || !options->getSeekTo(&seekTimeUs, &mode));
+ bool readFromSource = false;
+ int64_t wallClockTimeUs = -1;
while (mNumInputSamples < kNumSamplesPerFrame) {
if (mInputBuffer == NULL) {
@@ -166,12 +168,17 @@
size_t align = mInputBuffer->range_length() % sizeof(int16_t);
CHECK_EQ(align, 0);
+ readFromSource = true;
int64_t timeUs;
- if (mInputBuffer->meta_data()->findInt64(kKeyTime, &timeUs)) {
- mAnchorTimeUs = timeUs;
- mNumFramesOutput = 0;
+ if (mInputBuffer->meta_data()->findInt64(kKeyDriftTime, &timeUs)) {
+ wallClockTimeUs = timeUs;
}
+ if (mInputBuffer->meta_data()->findInt64(kKeyAnchorTime, &timeUs)) {
+ mAnchorTimeUs = timeUs;
+ }
+ } else {
+ readFromSource = false;
}
size_t copy =
@@ -217,8 +224,14 @@
buffer->set_range(0, res);
// Each frame of 160 samples is 20ms long.
+ int64_t mediaTimeUs = mNumFramesOutput * 20000LL;
buffer->meta_data()->setInt64(
- kKeyTime, mAnchorTimeUs + mNumFramesOutput * 20000);
+ kKeyTime, mAnchorTimeUs + mediaTimeUs);
+
+ if (readFromSource && wallClockTimeUs != -1) {
+ buffer->meta_data()->setInt64(kKeyDriftTime,
+ mediaTimeUs - wallClockTimeUs);
+ }
++mNumFramesOutput;
diff --git a/media/libstagefright/codecs/amrwbenc/AMRWBEncoder.cpp b/media/libstagefright/codecs/amrwbenc/AMRWBEncoder.cpp
index 93304d0..002f055 100644
--- a/media/libstagefright/codecs/amrwbenc/AMRWBEncoder.cpp
+++ b/media/libstagefright/codecs/amrwbenc/AMRWBEncoder.cpp
@@ -198,6 +198,8 @@
int64_t seekTimeUs;
ReadOptions::SeekMode mode;
CHECK(options == NULL || !options->getSeekTo(&seekTimeUs, &mode));
+ bool readFromSource = false;
+ int64_t wallClockTimeUs = -1;
while (mNumInputSamples < kNumSamplesPerFrame) {
if (mInputBuffer == NULL) {
@@ -219,9 +221,15 @@
CHECK_EQ(align, 0);
int64_t timeUs;
- if (mInputBuffer->meta_data()->findInt64(kKeyTime, &timeUs)) {
+ if (mInputBuffer->meta_data()->findInt64(kKeyDriftTime, &timeUs)) {
+ wallClockTimeUs = timeUs;
+ }
+ if (mInputBuffer->meta_data()->findInt64(kKeyAnchorTime, &timeUs)) {
mAnchorTimeUs = timeUs;
}
+ readFromSource = true;
+ } else {
+ readFromSource = false;
}
size_t copy =
@@ -276,10 +284,11 @@
buffer->set_range(0, outputData.Length);
++mNumFramesOutput;
- // XXX: fix timestamp calculation
- int64_t timestampUs = mNumFramesOutput * 20000LL;
-
- buffer->meta_data()->setInt64(kKeyTime, timestampUs);
+ int64_t mediaTimeUs = mNumFramesOutput * 20000LL;
+ buffer->meta_data()->setInt64(kKeyTime, mAnchorTimeUs + mediaTimeUs);
+ if (readFromSource && wallClockTimeUs != -1) {
+ buffer->meta_data()->setInt64(kKeyDriftTime, mediaTimeUs - wallClockTimeUs);
+ }
*out = buffer;
return OK;
diff --git a/media/libstagefright/colorconversion/SoftwareRenderer.cpp b/media/libstagefright/colorconversion/SoftwareRenderer.cpp
index 507fa5a..c204a94 100644
--- a/media/libstagefright/colorconversion/SoftwareRenderer.cpp
+++ b/media/libstagefright/colorconversion/SoftwareRenderer.cpp
@@ -106,7 +106,12 @@
void SoftwareRenderer::render(
const void *data, size_t size, void *platformPrivate) {
android_native_buffer_t *buf;
- CHECK_EQ(0, mSurface->dequeueBuffer(mSurface.get(), &buf));
+ int err;
+ if ((err = mSurface->dequeueBuffer(mSurface.get(), &buf)) != 0) {
+ LOGW("Surface::dequeueBuffer returned error %d", err);
+ return;
+ }
+
CHECK_EQ(0, mSurface->lockBuffer(mSurface.get(), buf));
GraphicBufferMapper &mapper = GraphicBufferMapper::get();
@@ -186,7 +191,9 @@
CHECK_EQ(0, mapper.unlock(buf->handle));
- CHECK_EQ(0, mSurface->queueBuffer(mSurface.get(), buf));
+ if ((err = mSurface->queueBuffer(mSurface.get(), buf)) != 0) {
+ LOGW("Surface::queueBuffer returned error %d", err);
+ }
buf = NULL;
}
diff --git a/media/libstagefright/include/ARTSPController.h b/media/libstagefright/include/ARTSPController.h
index 7016880..300d8f7 100644
--- a/media/libstagefright/include/ARTSPController.h
+++ b/media/libstagefright/include/ARTSPController.h
@@ -42,6 +42,7 @@
size_t index, uint32_t flags);
int64_t getNormalPlayTimeUs();
+ int64_t getQueueDurationUs(bool *eos);
void onMessageReceived(const sp<AMessage> &msg);
diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h
index f34eb45..ea2f7d5 100644
--- a/media/libstagefright/include/AwesomePlayer.h
+++ b/media/libstagefright/include/AwesomePlayer.h
@@ -107,6 +107,7 @@
CACHE_UNDERRUN = 128,
AUDIO_AT_EOS = 256,
VIDEO_AT_EOS = 512,
+ AUTO_LOOPING = 1024,
};
mutable Mutex mLock;
@@ -241,6 +242,9 @@
void onCheckAudioStatus();
void onPrepareAsyncEvent();
void abortPrepare(status_t err);
+ void finishAsyncPrepare_l();
+
+ bool getCachedDuration_l(int64_t *durationUs, bool *eos);
status_t finishSetDataSource_l();
diff --git a/media/libstagefright/include/MP3Extractor.h b/media/libstagefright/include/MP3Extractor.h
index 0e6ccde..30136e7 100644
--- a/media/libstagefright/include/MP3Extractor.h
+++ b/media/libstagefright/include/MP3Extractor.h
@@ -37,10 +37,9 @@
virtual sp<MetaData> getMetaData();
-protected:
- virtual ~MP3Extractor();
-
private:
+ status_t mInitCheck;
+
sp<DataSource> mDataSource;
off_t mFirstFramePos;
sp<MetaData> mMeta;
diff --git a/media/libstagefright/include/OMX.h b/media/libstagefright/include/OMX.h
index c99da59..83b75ad 100644
--- a/media/libstagefright/include/OMX.h
+++ b/media/libstagefright/include/OMX.h
@@ -59,10 +59,17 @@
node_id node, OMX_INDEXTYPE index,
const void *params, size_t size);
+ virtual status_t enableGraphicBuffers(
+ node_id node, OMX_U32 port_index, OMX_BOOL enable);
+
virtual status_t useBuffer(
node_id node, OMX_U32 port_index, const sp<IMemory> ¶ms,
buffer_id *buffer);
+ virtual status_t useGraphicBuffer(
+ node_id node, OMX_U32 port_index,
+ const sp<GraphicBuffer> &graphicBuffer, buffer_id *buffer);
+
virtual status_t allocateBuffer(
node_id node, OMX_U32 port_index, size_t size,
buffer_id *buffer, void **buffer_data);
diff --git a/media/libstagefright/include/OMXNodeInstance.h b/media/libstagefright/include/OMXNodeInstance.h
index b5b31ac..8c7c562 100644
--- a/media/libstagefright/include/OMXNodeInstance.h
+++ b/media/libstagefright/include/OMXNodeInstance.h
@@ -49,10 +49,16 @@
status_t getConfig(OMX_INDEXTYPE index, void *params, size_t size);
status_t setConfig(OMX_INDEXTYPE index, const void *params, size_t size);
+ status_t enableGraphicBuffers(OMX_U32 portIndex, OMX_BOOL enable);
+
status_t useBuffer(
OMX_U32 portIndex, const sp<IMemory> ¶ms,
OMX::buffer_id *buffer);
+ status_t useGraphicBuffer(
+ OMX_U32 portIndex, const sp<GraphicBuffer> &graphicBuffer,
+ OMX::buffer_id *buffer);
+
status_t allocateBuffer(
OMX_U32 portIndex, size_t size, OMX::buffer_id *buffer,
void **buffer_data);
@@ -125,4 +131,3 @@
} // namespace android
#endif // OMX_NODE_INSTANCE_H_
-
diff --git a/media/libstagefright/mpeg2ts/ATSParser.cpp b/media/libstagefright/mpeg2ts/ATSParser.cpp
index 26a0fb3..72de8d7 100644
--- a/media/libstagefright/mpeg2ts/ATSParser.cpp
+++ b/media/libstagefright/mpeg2ts/ATSParser.cpp
@@ -78,6 +78,8 @@
unsigned PTS_DTS_flags, uint64_t PTS, uint64_t DTS,
const uint8_t *data, size_t size);
+ void extractAACFrames(const sp<ABuffer> &buffer);
+
DISALLOW_EVIL_CONSTRUCTORS(Stream);
};
@@ -226,7 +228,7 @@
ATSParser::Stream::Stream(unsigned elementaryPID, unsigned streamType)
: mElementaryPID(elementaryPID),
mStreamType(streamType),
- mBuffer(new ABuffer(65536)),
+ mBuffer(new ABuffer(128 * 1024)),
mPayloadStarted(false) {
mBuffer->setRange(0, 0);
}
@@ -662,7 +664,7 @@
csd->data()[sizeof(kStaticESDS) + 1] =
((sampling_freq_index << 7) & 0x80) | (channel_configuration << 3);
- hexdump(csd->data(), csd->size());
+ // hexdump(csd->data(), csd->size());
return csd;
}
@@ -727,13 +729,76 @@
buffer->meta()->setInt64("time", (PTS * 100) / 9);
if (mStreamType == 0x0f) {
- // WHY???
- buffer->setRange(7, buffer->size() - 7);
+ extractAACFrames(buffer);
}
mSource->queueAccessUnit(buffer);
}
+// Disassemble one or more ADTS frames into their constituent parts and
+// leave only the concatenated raw_data_blocks in the buffer.
+void ATSParser::Stream::extractAACFrames(const sp<ABuffer> &buffer) {
+ size_t dstOffset = 0;
+
+ size_t offset = 0;
+ while (offset < buffer->size()) {
+ CHECK_LE(offset + 7, buffer->size());
+
+ ABitReader bits(buffer->data() + offset, buffer->size() - offset);
+
+ // adts_fixed_header
+
+ CHECK_EQ(bits.getBits(12), 0xfffu);
+ bits.skipBits(3); // ID, layer
+ bool protection_absent = bits.getBits(1) != 0;
+
+ // profile_ObjectType, sampling_frequency_index, private_bits,
+ // channel_configuration, original_copy, home
+ bits.skipBits(12);
+
+ // adts_variable_header
+
+ // copyright_identification_bit, copyright_identification_start
+ bits.skipBits(2);
+
+ unsigned aac_frame_length = bits.getBits(13);
+
+ bits.skipBits(11); // adts_buffer_fullness
+
+ unsigned number_of_raw_data_blocks_in_frame = bits.getBits(2);
+
+ if (number_of_raw_data_blocks_in_frame == 0) {
+ size_t scan = offset + aac_frame_length;
+
+ offset += 7;
+ if (!protection_absent) {
+ offset += 2;
+ }
+
+ CHECK_LE(scan, buffer->size());
+
+ LOG(VERBOSE)
+ << "found aac raw data block at ["
+ << StringPrintf("0x%08x", offset)
+ << " ; "
+ << StringPrintf("0x%08x", scan)
+ << ")";
+
+ memmove(&buffer->data()[dstOffset], &buffer->data()[offset],
+ scan - offset);
+
+ dstOffset += scan - offset;
+ offset = scan;
+ } else {
+ // To be implemented.
+ TRESPASS();
+ }
+ }
+ CHECK_EQ(offset, buffer->size());
+
+ buffer->setRange(buffer->offset(), dstOffset);
+}
+
sp<MediaSource> ATSParser::Stream::getSource(SourceType type) {
if ((type == AVC_VIDEO && mStreamType == 0x1b)
|| (type == MPEG2ADTS_AUDIO && mStreamType == 0x0f)) {
diff --git a/media/libstagefright/omx/OMX.cpp b/media/libstagefright/omx/OMX.cpp
index 88b9605..37243ad 100644
--- a/media/libstagefright/omx/OMX.cpp
+++ b/media/libstagefright/omx/OMX.cpp
@@ -287,6 +287,11 @@
index, params, size);
}
+status_t OMX::enableGraphicBuffers(
+ node_id node, OMX_U32 port_index, OMX_BOOL enable) {
+ return findInstance(node)->enableGraphicBuffers(port_index, enable);
+}
+
status_t OMX::useBuffer(
node_id node, OMX_U32 port_index, const sp<IMemory> ¶ms,
buffer_id *buffer) {
@@ -294,6 +299,13 @@
port_index, params, buffer);
}
+status_t OMX::useGraphicBuffer(
+ node_id node, OMX_U32 port_index,
+ const sp<GraphicBuffer> &graphicBuffer, buffer_id *buffer) {
+ return findInstance(node)->useGraphicBuffer(
+ port_index, graphicBuffer, buffer);
+}
+
status_t OMX::allocateBuffer(
node_id node, OMX_U32 port_index, size_t size,
buffer_id *buffer, void **buffer_data) {
@@ -530,4 +542,3 @@
}
} // namespace android
-
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index 5db516e..ba4d765 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -24,6 +24,7 @@
#include <OMX_Component.h>
#include <binder/IMemory.h>
+#include <media/stagefright/HardwareAPI.h>
#include <media/stagefright/MediaDebug.h>
#include <media/stagefright/MediaErrors.h>
@@ -40,6 +41,11 @@
mIsBackup(false) {
}
+ BufferMeta(const sp<GraphicBuffer> &graphicBuffer)
+ : mGraphicBuffer(graphicBuffer),
+ mIsBackup(false) {
+ }
+
void CopyFromOMX(const OMX_BUFFERHEADERTYPE *header) {
if (!mIsBackup) {
return;
@@ -61,6 +67,7 @@
}
private:
+ sp<GraphicBuffer> mGraphicBuffer;
sp<IMemory> mMem;
size_t mSize;
bool mIsBackup;
@@ -240,6 +247,43 @@
return StatusFromOMXError(err);
}
+status_t OMXNodeInstance::enableGraphicBuffers(
+ OMX_U32 portIndex, OMX_BOOL enable) {
+ Mutex::Autolock autoLock(mLock);
+
+ OMX_INDEXTYPE index;
+ OMX_ERRORTYPE err = OMX_GetExtensionIndex(
+ mHandle,
+ const_cast<OMX_STRING>("OMX.google.android.index.enableAndroidNativeBuffers"),
+ &index);
+
+ if (err != OMX_ErrorNone) {
+ LOGE("OMX_GetExtensionIndex failed");
+
+ return StatusFromOMXError(err);
+ }
+
+ OMX_VERSIONTYPE ver;
+ ver.s.nVersionMajor = 1;
+ ver.s.nVersionMinor = 0;
+ ver.s.nRevision = 0;
+ ver.s.nStep = 0;
+ EnableAndroidNativeBuffersParams params = {
+ sizeof(EnableAndroidNativeBuffersParams), ver, portIndex, enable,
+ };
+
+ err = OMX_SetParameter(mHandle, index, ¶ms);
+
+ if (err != OMX_ErrorNone) {
+ LOGE("OMX_EnableAndroidNativeBuffers failed with error %d (0x%08x)",
+ err, err);
+
+ return UNKNOWN_ERROR;
+ }
+
+ return OK;
+}
+
status_t OMXNodeInstance::useBuffer(
OMX_U32 portIndex, const sp<IMemory> ¶ms,
OMX::buffer_id *buffer) {
@@ -273,6 +317,60 @@
return OK;
}
+status_t OMXNodeInstance::useGraphicBuffer(
+ OMX_U32 portIndex, const sp<GraphicBuffer>& graphicBuffer,
+ OMX::buffer_id *buffer) {
+ Mutex::Autolock autoLock(mLock);
+
+ OMX_INDEXTYPE index;
+ OMX_ERRORTYPE err = OMX_GetExtensionIndex(
+ mHandle,
+ const_cast<OMX_STRING>("OMX.google.android.index.useAndroidNativeBuffer"),
+ &index);
+
+ if (err != OMX_ErrorNone) {
+ LOGE("OMX_GetExtensionIndex failed");
+
+ return StatusFromOMXError(err);
+ }
+
+ BufferMeta *bufferMeta = new BufferMeta(graphicBuffer);
+
+ OMX_BUFFERHEADERTYPE *header;
+
+ OMX_VERSIONTYPE ver;
+ ver.s.nVersionMajor = 1;
+ ver.s.nVersionMinor = 0;
+ ver.s.nRevision = 0;
+ ver.s.nStep = 0;
+ UseAndroidNativeBufferParams params = {
+ sizeof(UseAndroidNativeBufferParams), ver, portIndex, bufferMeta,
+ &header, graphicBuffer,
+ };
+
+ err = OMX_SetParameter(mHandle, index, ¶ms);
+
+ if (err != OMX_ErrorNone) {
+ LOGE("OMX_UseAndroidNativeBuffer failed with error %d (0x%08x)", err,
+ err);
+
+ delete bufferMeta;
+ bufferMeta = NULL;
+
+ *buffer = 0;
+
+ return UNKNOWN_ERROR;
+ }
+
+ CHECK_EQ(header->pAppPrivate, bufferMeta);
+
+ *buffer = header;
+
+ addActiveBuffer(portIndex, *buffer);
+
+ return OK;
+}
+
status_t OMXNodeInstance::allocateBuffer(
OMX_U32 portIndex, size_t size, OMX::buffer_id *buffer,
void **buffer_data) {
@@ -498,4 +596,3 @@
}
} // namespace android
-
diff --git a/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.cpp b/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.cpp
index 7dd3e3f..f68a35b 100644
--- a/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.cpp
+++ b/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.cpp
@@ -18,29 +18,160 @@
#include "ARTPSource.h"
+#include <media/stagefright/foundation/ABitReader.h>
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/foundation/hexdump.h>
+#include <media/stagefright/Utils.h>
+#include <ctype.h>
#include <stdint.h>
#define BE_VERBOSE 0
namespace android {
+static bool GetAttribute(const char *s, const char *key, AString *value) {
+ value->clear();
+
+ size_t keyLen = strlen(key);
+
+ for (;;) {
+ while (isspace(*s)) {
+ ++s;
+ }
+
+ const char *colonPos = strchr(s, ';');
+
+ size_t len =
+ (colonPos == NULL) ? strlen(s) : colonPos - s;
+
+ if (len >= keyLen + 1 && s[keyLen] == '='
+ && !strncasecmp(s, key, keyLen)) {
+ value->setTo(&s[keyLen + 1], len - keyLen - 1);
+ return true;
+ }
+
+ if (colonPos == NULL) {
+ return false;
+ }
+
+ s = colonPos + 1;
+ }
+}
+
+static bool GetIntegerAttribute(
+ const char *s, const char *key, unsigned *x) {
+ *x = 0;
+
+ AString val;
+ if (!GetAttribute(s, key, &val)) {
+ return false;
+ }
+
+ s = val.c_str();
+ char *end;
+ unsigned y = strtoul(s, &end, 10);
+
+ if (end == s || *end != '\0') {
+ return false;
+ }
+
+ *x = y;
+
+ return true;
+}
+
// static
-AMPEG4ElementaryAssembler::AMPEG4ElementaryAssembler(const sp<AMessage> ¬ify)
+AMPEG4ElementaryAssembler::AMPEG4ElementaryAssembler(
+ const sp<AMessage> ¬ify, const AString &desc, const AString ¶ms)
: mNotifyMsg(notify),
+ mIsGeneric(false),
+ mParams(params),
+ mSizeLength(0),
+ mIndexLength(0),
+ mIndexDeltaLength(0),
+ mCTSDeltaLength(0),
+ mDTSDeltaLength(0),
+ mRandomAccessIndication(false),
+ mStreamStateIndication(0),
+ mAuxiliaryDataSizeLength(0),
+ mHasAUHeader(false),
mAccessUnitRTPTime(0),
mNextExpectedSeqNoValid(false),
mNextExpectedSeqNo(0),
mAccessUnitDamaged(false) {
+ mIsGeneric = desc.startsWith("mpeg4-generic/");
+
+ if (mIsGeneric) {
+ AString value;
+ CHECK(GetAttribute(params.c_str(), "mode", &value));
+
+ if (!GetIntegerAttribute(params.c_str(), "sizeLength", &mSizeLength)) {
+ mSizeLength = 0;
+ }
+
+ if (!GetIntegerAttribute(
+ params.c_str(), "indexLength", &mIndexLength)) {
+ mIndexLength = 0;
+ }
+
+ if (!GetIntegerAttribute(
+ params.c_str(), "indexDeltaLength", &mIndexDeltaLength)) {
+ mIndexDeltaLength = 0;
+ }
+
+ if (!GetIntegerAttribute(
+ params.c_str(), "CTSDeltaLength", &mCTSDeltaLength)) {
+ mCTSDeltaLength = 0;
+ }
+
+ if (!GetIntegerAttribute(
+ params.c_str(), "DTSDeltaLength", &mDTSDeltaLength)) {
+ mDTSDeltaLength = 0;
+ }
+
+ unsigned x;
+ if (!GetIntegerAttribute(
+ params.c_str(), "randomAccessIndication", &x)) {
+ mRandomAccessIndication = false;
+ } else {
+ CHECK(x == 0 || x == 1);
+ mRandomAccessIndication = (x != 0);
+ }
+
+ if (!GetIntegerAttribute(
+ params.c_str(), "streamStateIndication",
+ &mStreamStateIndication)) {
+ mStreamStateIndication = 0;
+ }
+
+ if (!GetIntegerAttribute(
+ params.c_str(), "auxiliaryDataSizeLength",
+ &mAuxiliaryDataSizeLength)) {
+ mAuxiliaryDataSizeLength = 0;
+ }
+
+ mHasAUHeader =
+ mSizeLength > 0
+ || mIndexLength > 0
+ || mIndexDeltaLength > 0
+ || mCTSDeltaLength > 0
+ || mDTSDeltaLength > 0
+ || mRandomAccessIndication
+ || mStreamStateIndication > 0;
+ }
}
AMPEG4ElementaryAssembler::~AMPEG4ElementaryAssembler() {
}
+struct AUHeader {
+ unsigned mSize;
+ unsigned mSerial;
+};
+
ARTPAssembler::AssemblyStatus AMPEG4ElementaryAssembler::addPacket(
const sp<ARTPSource> &source) {
List<sp<ABuffer> > *queue = source->queue();
@@ -85,8 +216,116 @@
}
mAccessUnitRTPTime = rtpTime;
- mPackets.push_back(buffer);
- // hexdump(buffer->data(), buffer->size());
+ if (!mIsGeneric) {
+ mPackets.push_back(buffer);
+ } else {
+ // hexdump(buffer->data(), buffer->size());
+
+ CHECK_GE(buffer->size(), 2u);
+ unsigned AU_headers_length = U16_AT(buffer->data()); // in bits
+
+ CHECK_GE(buffer->size(), 2 + (AU_headers_length + 7) / 8);
+
+ List<AUHeader> headers;
+
+ ABitReader bits(buffer->data() + 2, buffer->size() - 2);
+ unsigned numBitsLeft = AU_headers_length;
+
+ unsigned AU_serial = 0;
+ for (;;) {
+ if (numBitsLeft < mSizeLength) { break; }
+
+ unsigned AU_size = bits.getBits(mSizeLength);
+ numBitsLeft -= mSizeLength;
+
+ size_t n = headers.empty() ? mIndexLength : mIndexDeltaLength;
+ if (numBitsLeft < n) { break; }
+
+ unsigned AU_index = bits.getBits(n);
+ numBitsLeft -= n;
+
+ if (headers.empty()) {
+ AU_serial = AU_index;
+ } else {
+ AU_serial += 1 + AU_index;
+ }
+
+ if (mCTSDeltaLength > 0) {
+ if (numBitsLeft < 1) {
+ break;
+ }
+ --numBitsLeft;
+ if (bits.getBits(1)) {
+ if (numBitsLeft < mCTSDeltaLength) {
+ break;
+ }
+ bits.skipBits(mCTSDeltaLength);
+ numBitsLeft -= mCTSDeltaLength;
+ }
+ }
+
+ if (mDTSDeltaLength > 0) {
+ if (numBitsLeft < 1) {
+ break;
+ }
+ --numBitsLeft;
+ if (bits.getBits(1)) {
+ if (numBitsLeft < mDTSDeltaLength) {
+ break;
+ }
+ bits.skipBits(mDTSDeltaLength);
+ numBitsLeft -= mDTSDeltaLength;
+ }
+ }
+
+ if (mRandomAccessIndication) {
+ if (numBitsLeft < 1) {
+ break;
+ }
+ bits.skipBits(1);
+ --numBitsLeft;
+ }
+
+ if (mStreamStateIndication > 0) {
+ if (numBitsLeft < mStreamStateIndication) {
+ break;
+ }
+ bits.skipBits(mStreamStateIndication);
+ }
+
+ AUHeader header;
+ header.mSize = AU_size;
+ header.mSerial = AU_serial;
+ headers.push_back(header);
+ }
+
+ size_t offset = 2 + (AU_headers_length + 7) / 8;
+
+ if (mAuxiliaryDataSizeLength > 0) {
+ ABitReader bits(buffer->data() + offset, buffer->size() - offset);
+
+ unsigned auxSize = bits.getBits(mAuxiliaryDataSizeLength);
+
+ offset += (mAuxiliaryDataSizeLength + auxSize + 7) / 8;
+ }
+
+ for (List<AUHeader>::iterator it = headers.begin();
+ it != headers.end(); ++it) {
+ const AUHeader &header = *it;
+
+ CHECK_LE(offset + header.mSize, buffer->size());
+
+ sp<ABuffer> accessUnit = new ABuffer(header.mSize);
+ memcpy(accessUnit->data(), buffer->data() + offset, header.mSize);
+
+ offset += header.mSize;
+
+ CopyTimes(accessUnit, buffer);
+ mPackets.push_back(accessUnit);
+ }
+
+ CHECK_EQ(offset, buffer->size());
+ }
queue->erase(queue->begin());
++mNextExpectedSeqNo;
diff --git a/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.h b/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.h
index 1566d00..794bbcc 100644
--- a/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.h
+++ b/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.h
@@ -20,6 +20,8 @@
#include "ARTPAssembler.h"
+#include <media/stagefright/foundation/AString.h>
+
#include <utils/List.h>
#include <utils/RefBase.h>
@@ -29,7 +31,9 @@
struct AMessage;
struct AMPEG4ElementaryAssembler : public ARTPAssembler {
- AMPEG4ElementaryAssembler(const sp<AMessage> ¬ify);
+ AMPEG4ElementaryAssembler(
+ const sp<AMessage> ¬ify, const AString &desc,
+ const AString ¶ms);
protected:
virtual ~AMPEG4ElementaryAssembler();
@@ -40,6 +44,18 @@
private:
sp<AMessage> mNotifyMsg;
+ bool mIsGeneric;
+ AString mParams;
+
+ unsigned mSizeLength;
+ unsigned mIndexLength;
+ unsigned mIndexDeltaLength;
+ unsigned mCTSDeltaLength;
+ unsigned mDTSDeltaLength;
+ bool mRandomAccessIndication;
+ unsigned mStreamStateIndication;
+ unsigned mAuxiliaryDataSizeLength;
+ bool mHasAUHeader;
uint32_t mAccessUnitRTPTime;
bool mNextExpectedSeqNoValid;
diff --git a/media/libstagefright/rtsp/APacketSource.cpp b/media/libstagefright/rtsp/APacketSource.cpp
index 2d7738b..b63798f 100644
--- a/media/libstagefright/rtsp/APacketSource.cpp
+++ b/media/libstagefright/rtsp/APacketSource.cpp
@@ -247,6 +247,65 @@
return csd;
}
+// From mpeg4-generic configuration data.
+sp<ABuffer> MakeAACCodecSpecificData2(const char *params) {
+ AString val;
+ unsigned long objectType;
+ if (GetAttribute(params, "objectType", &val)) {
+ const char *s = val.c_str();
+ char *end;
+ objectType = strtoul(s, &end, 10);
+ CHECK(end > s && *end == '\0');
+ } else {
+ objectType = 0x40; // Audio ISO/IEC 14496-3
+ }
+
+ CHECK(GetAttribute(params, "config", &val));
+
+ sp<ABuffer> config = decodeHex(val);
+ CHECK(config != NULL);
+
+ // Make sure size fits into a single byte and doesn't have to
+ // be encoded.
+ CHECK_LT(20 + config->size(), 128u);
+
+ const uint8_t *data = config->data();
+
+ static const uint8_t kStaticESDS[] = {
+ 0x03, 22,
+ 0x00, 0x00, // ES_ID
+ 0x00, // streamDependenceFlag, URL_Flag, OCRstreamFlag
+
+ 0x04, 17,
+ 0x40, // Audio ISO/IEC 14496-3
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+
+ 0x05, 2,
+ // AudioSpecificInfo follows
+ };
+
+ sp<ABuffer> csd = new ABuffer(sizeof(kStaticESDS) + config->size());
+ uint8_t *dst = csd->data();
+ *dst++ = 0x03;
+ *dst++ = 20 + config->size();
+ *dst++ = 0x00; // ES_ID
+ *dst++ = 0x00;
+ *dst++ = 0x00; // streamDependenceFlag, URL_Flag, OCRstreamFlag
+ *dst++ = 0x04;
+ *dst++ = 15 + config->size();
+ *dst++ = objectType;
+ for (int i = 0; i < 12; ++i) { *dst++ = 0x00; }
+ *dst++ = 0x05;
+ *dst++ = config->size();
+ memcpy(dst, config->data(), config->size());
+
+ // hexdump(csd->data(), csd->size());
+
+ return csd;
+}
+
static size_t GetSizeWidth(size_t x) {
size_t n = 1;
while (x > 127) {
@@ -560,6 +619,30 @@
mFormat->setInt32(kKeyWidth, width);
mFormat->setInt32(kKeyHeight, height);
+ } else if (!strncmp(desc.c_str(), "mpeg4-generic/", 14)) {
+ AString val;
+ if (!GetAttribute(params.c_str(), "mode", &val)
+ || (strcasecmp(val.c_str(), "AAC-lbr")
+ && strcasecmp(val.c_str(), "AAC-hbr"))) {
+ mInitCheck = ERROR_UNSUPPORTED;
+ return;
+ }
+
+ mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC);
+
+ int32_t sampleRate, numChannels;
+ ASessionDescription::ParseFormatDesc(
+ desc.c_str(), &sampleRate, &numChannels);
+
+ mFormat->setInt32(kKeySampleRate, sampleRate);
+ mFormat->setInt32(kKeyChannelCount, numChannels);
+
+ sp<ABuffer> codecSpecificData =
+ MakeAACCodecSpecificData2(params.c_str());
+
+ mFormat->setData(
+ kKeyESDS, 0,
+ codecSpecificData->data(), codecSpecificData->size());
} else {
mInitCheck = ERROR_UNSUPPORTED;
}
@@ -663,4 +746,27 @@
mNormalPlayTimeBaseUs = normalPlayTimeUs;
}
+int64_t APacketSource::getQueueDurationUs(bool *eos) {
+ Mutex::Autolock autoLock(mLock);
+
+ *eos = (mEOSResult != OK);
+
+ if (mBuffers.size() < 2) {
+ return 0;
+ }
+
+ const sp<ABuffer> first = *mBuffers.begin();
+ const sp<ABuffer> last = *--mBuffers.end();
+
+ int64_t firstTimeUs;
+ CHECK(first->meta()->findInt64("timeUs", &firstTimeUs));
+
+ int64_t lastTimeUs;
+ CHECK(last->meta()->findInt64("timeUs", &lastTimeUs));
+
+ CHECK_GE(lastTimeUs, firstTimeUs);
+
+ return lastTimeUs - firstTimeUs;
+}
+
} // namespace android
diff --git a/media/libstagefright/rtsp/APacketSource.h b/media/libstagefright/rtsp/APacketSource.h
index 3833ab1..076ddc4 100644
--- a/media/libstagefright/rtsp/APacketSource.h
+++ b/media/libstagefright/rtsp/APacketSource.h
@@ -50,6 +50,8 @@
void setNormalPlayTimeMapping(
uint32_t rtpTime, int64_t normalPlayTimeUs);
+ int64_t getQueueDurationUs(bool *eos);
+
protected:
virtual ~APacketSource();
diff --git a/media/libstagefright/rtsp/ARTPConnection.cpp b/media/libstagefright/rtsp/ARTPConnection.cpp
index 12f8f32..10c9e02 100644
--- a/media/libstagefright/rtsp/ARTPConnection.cpp
+++ b/media/libstagefright/rtsp/ARTPConnection.cpp
@@ -362,7 +362,6 @@
if (receiveRTP) {
err = parseRTP(s, buffer);
} else {
- ++s->mNumRTCPPacketsReceived;
err = parseRTCP(s, buffer);
}
@@ -456,6 +455,12 @@
}
status_t ARTPConnection::parseRTCP(StreamInfo *s, const sp<ABuffer> &buffer) {
+ if (s->mNumRTCPPacketsReceived++ == 0) {
+ sp<AMessage> notify = s->mNotifyMsg->dup();
+ notify->setInt32("first-rtcp", true);
+ notify->post();
+ }
+
const uint8_t *data = buffer->data();
size_t size = buffer->size();
@@ -626,7 +631,6 @@
if (it->mRTPSocket == index) {
err = parseRTP(s, buffer);
} else {
- ++s->mNumRTCPPacketsReceived;
err = parseRTCP(s, buffer);
}
}
diff --git a/media/libstagefright/rtsp/ARTPSession.cpp b/media/libstagefright/rtsp/ARTPSession.cpp
index f60c1a9..8ce93b7 100644
--- a/media/libstagefright/rtsp/ARTPSession.cpp
+++ b/media/libstagefright/rtsp/ARTPSession.cpp
@@ -125,6 +125,14 @@
switch (msg->what()) {
case kWhatAccessUnitComplete:
{
+ int32_t firstRTCP;
+ if (msg->findInt32("first-rtcp", &firstRTCP)) {
+ // There won't be an access unit here, it's just a notification
+ // that the data communication worked since we got the first
+ // rtcp packet.
+ break;
+ }
+
size_t trackIndex;
CHECK(msg->findSize("track-index", &trackIndex));
diff --git a/media/libstagefright/rtsp/ARTPSource.cpp b/media/libstagefright/rtsp/ARTPSource.cpp
index 775c4ee..9656ba2 100644
--- a/media/libstagefright/rtsp/ARTPSource.cpp
+++ b/media/libstagefright/rtsp/ARTPSource.cpp
@@ -64,8 +64,9 @@
mAssembler = new AAMRAssembler(notify, false /* isWide */, params);
} else if (!strncmp(desc.c_str(), "AMR-WB/", 7)) {
mAssembler = new AAMRAssembler(notify, true /* isWide */, params);
- } else if (!strncmp(desc.c_str(), "MP4V-ES/", 8)) {
- mAssembler = new AMPEG4ElementaryAssembler(notify);
+ } else if (!strncmp(desc.c_str(), "MP4V-ES/", 8)
+ || !strncmp(desc.c_str(), "mpeg4-generic/", 14)) {
+ mAssembler = new AMPEG4ElementaryAssembler(notify, desc, params);
mIssueFIRRequests = true;
} else {
TRESPASS();
diff --git a/media/libstagefright/rtsp/ARTSPController.cpp b/media/libstagefright/rtsp/ARTSPController.cpp
index a89946b..4c53639 100644
--- a/media/libstagefright/rtsp/ARTSPController.cpp
+++ b/media/libstagefright/rtsp/ARTSPController.cpp
@@ -143,4 +143,26 @@
return mHandler->getNormalPlayTimeUs();
}
+int64_t ARTSPController::getQueueDurationUs(bool *eos) {
+ *eos = true;
+
+ int64_t minQueuedDurationUs = 0;
+ for (size_t i = 0; i < mHandler->countTracks(); ++i) {
+ sp<APacketSource> source = mHandler->getPacketSource(i);
+
+ bool newEOS;
+ int64_t queuedDurationUs = source->getQueueDurationUs(&newEOS);
+
+ if (!newEOS) {
+ *eos = false;
+ }
+
+ if (i == 0 || queuedDurationUs < minQueuedDurationUs) {
+ minQueuedDurationUs = queuedDurationUs;
+ }
+ }
+
+ return minQueuedDurationUs;
+}
+
} // namespace android
diff --git a/media/libstagefright/rtsp/MyHandler.h b/media/libstagefright/rtsp/MyHandler.h
index 3d8d86b..0aefd58 100644
--- a/media/libstagefright/rtsp/MyHandler.h
+++ b/media/libstagefright/rtsp/MyHandler.h
@@ -82,7 +82,8 @@
mFirstAccessUnitNTP(0),
mNumAccessUnitsReceived(0),
mCheckPending(false),
- mTryTCPInterleaving(false) {
+ mTryTCPInterleaving(false),
+ mReceivedFirstRTCPPacket(false) {
mNetLooper->setName("rtsp net");
mNetLooper->start(false /* runOnCallingThread */,
false /* canCallJava */,
@@ -199,31 +200,35 @@
break;
}
- CHECK_EQ(response->mStatusCode, 200u);
-
- mSessionDesc = new ASessionDescription;
-
- mSessionDesc->setTo(
- response->mContent->data(),
- response->mContent->size());
-
- CHECK(mSessionDesc->isValid());
-
- ssize_t i = response->mHeaders.indexOfKey("content-base");
- if (i >= 0) {
- mBaseURL = response->mHeaders.valueAt(i);
+ if (response->mStatusCode != 200) {
+ result = UNKNOWN_ERROR;
} else {
- i = response->mHeaders.indexOfKey("content-location");
+ mSessionDesc = new ASessionDescription;
+
+ mSessionDesc->setTo(
+ response->mContent->data(),
+ response->mContent->size());
+
+ CHECK(mSessionDesc->isValid());
+
+ ssize_t i = response->mHeaders.indexOfKey("content-base");
if (i >= 0) {
mBaseURL = response->mHeaders.valueAt(i);
} else {
- mBaseURL = mSessionURL;
+ i = response->mHeaders.indexOfKey("content-location");
+ if (i >= 0) {
+ mBaseURL = response->mHeaders.valueAt(i);
+ } else {
+ mBaseURL = mSessionURL;
+ }
}
- }
- CHECK_GT(mSessionDesc->countTracks(), 1u);
- setupTrack(1);
- } else {
+ CHECK_GT(mSessionDesc->countTracks(), 1u);
+ setupTrack(1);
+ }
+ }
+
+ if (result != OK) {
sp<AMessage> reply = new AMessage('disc', id());
mConn->disconnect(reply);
}
@@ -247,6 +252,39 @@
LOG(INFO) << "SETUP(" << index << ") completed with result "
<< result << " (" << strerror(-result) << ")";
+ if (result == OK) {
+ CHECK(track != NULL);
+
+ sp<RefBase> obj;
+ CHECK(msg->findObject("response", &obj));
+ sp<ARTSPResponse> response =
+ static_cast<ARTSPResponse *>(obj.get());
+
+ if (response->mStatusCode != 200) {
+ result = UNKNOWN_ERROR;
+ } else {
+ ssize_t i = response->mHeaders.indexOfKey("session");
+ CHECK_GE(i, 0);
+
+ mSessionID = response->mHeaders.valueAt(i);
+ i = mSessionID.find(";");
+ if (i >= 0) {
+ // Remove options, i.e. ";timeout=90"
+ mSessionID.erase(i, mSessionID.size() - i);
+ }
+
+ sp<AMessage> notify = new AMessage('accu', id());
+ notify->setSize("track-index", trackIndex);
+
+ mRTPConn->addStream(
+ track->mRTPSocket, track->mRTCPSocket,
+ mSessionDesc, index,
+ notify, track->mUsingInterleavedTCP);
+
+ mSetupTracksSuccessful = true;
+ }
+ }
+
if (result != OK) {
if (track) {
if (!track->mUsingInterleavedTCP) {
@@ -256,37 +294,6 @@
mTracks.removeItemsAt(trackIndex);
}
- } else {
- CHECK(track != NULL);
-
- sp<RefBase> obj;
- CHECK(msg->findObject("response", &obj));
- sp<ARTSPResponse> response =
- static_cast<ARTSPResponse *>(obj.get());
-
- CHECK_EQ(response->mStatusCode, 200u);
-
- ssize_t i = response->mHeaders.indexOfKey("session");
- CHECK_GE(i, 0);
-
- if (index == 1) {
- mSessionID = response->mHeaders.valueAt(i);
- i = mSessionID.find(";");
- if (i >= 0) {
- // Remove options, i.e. ";timeout=90"
- mSessionID.erase(i, mSessionID.size() - i);
- }
- }
-
- sp<AMessage> notify = new AMessage('accu', id());
- notify->setSize("track-index", trackIndex);
-
- mRTPConn->addStream(
- track->mRTPSocket, track->mRTCPSocket,
- mSessionDesc, index,
- notify, track->mUsingInterleavedTCP);
-
- mSetupTracksSuccessful = true;
}
++index;
@@ -355,6 +362,12 @@
}
}
mTracks.clear();
+ mSetupTracksSuccessful = false;
+ mSeekPending = false;
+ mFirstAccessUnit = true;
+ mFirstAccessUnitNTP = 0;
+ mNumAccessUnitsReceived = 0;
+ mReceivedFirstRTCPPacket = false;
sp<AMessage> reply = new AMessage('tear', id());
@@ -424,6 +437,12 @@
case 'accu':
{
+ int32_t firstRTCP;
+ if (msg->findInt32("first-rtcp", &firstRTCP)) {
+ mReceivedFirstRTCPPacket = true;
+ break;
+ }
+
++mNumAccessUnitsReceived;
if (!mCheckPending) {
@@ -612,7 +631,7 @@
case 'tiou':
{
- if (mFirstAccessUnit) {
+ if (!mReceivedFirstRTCPPacket) {
if (mTryTCPInterleaving) {
LOG(WARNING) << "Never received any data, disconnecting.";
(new AMessage('abor', id()))->post();
@@ -747,6 +766,7 @@
int64_t mNumAccessUnitsReceived;
bool mCheckPending;
bool mTryTCPInterleaving;
+ bool mReceivedFirstRTCPPacket;
struct TrackInfo {
AString mURL;
diff --git a/media/mtp/MtpDatabase.h b/media/mtp/MtpDatabase.h
index 899b34a..c8cb016 100644
--- a/media/mtp/MtpDatabase.h
+++ b/media/mtp/MtpDatabase.h
@@ -93,6 +93,10 @@
MtpObjectFormat format) = 0;
virtual MtpProperty* getDevicePropertyDesc(MtpDeviceProperty property) = 0;
+
+ virtual void sessionStarted() = 0;
+
+ virtual void sessionEnded() = 0;
};
}; // namespace android
diff --git a/media/mtp/MtpDevice.cpp b/media/mtp/MtpDevice.cpp
index bd68f75..fca0142 100644
--- a/media/mtp/MtpDevice.cpp
+++ b/media/mtp/MtpDevice.cpp
@@ -342,7 +342,7 @@
MtpResponseCode ret = readResponse();
if (ret == MTP_RESPONSE_OK) {
MtpProperty* property = new MtpProperty;
- property->read(mData, true);
+ property->read(mData);
return property;
}
return NULL;
diff --git a/media/mtp/MtpProperty.cpp b/media/mtp/MtpProperty.cpp
index 932ad6a..c7a91d6 100644
--- a/media/mtp/MtpProperty.cpp
+++ b/media/mtp/MtpProperty.cpp
@@ -120,7 +120,7 @@
delete[] mEnumValues;
}
-void MtpProperty::read(MtpDataPacket& packet, bool deviceProp) {
+void MtpProperty::read(MtpDataPacket& packet) {
mCode = packet.getUInt16();
mType = packet.getUInt16();
@@ -141,7 +141,7 @@
break;
default:
readValue(packet, mDefaultValue);
- if (deviceProp)
+ if (isDeviceProperty())
readValue(packet, mCurrentValue);
}
mGroupCode = packet.getUInt32();
@@ -159,7 +159,6 @@
}
}
-// FIXME - only works for object properties
void MtpProperty::write(MtpDataPacket& packet) {
packet.putUInt16(mCode);
packet.putUInt16(mType);
diff --git a/media/mtp/MtpProperty.h b/media/mtp/MtpProperty.h
index c5b4e28..64cfb93 100644
--- a/media/mtp/MtpProperty.h
+++ b/media/mtp/MtpProperty.h
@@ -65,16 +65,22 @@
inline MtpPropertyCode getPropertyCode() const { return mCode; }
- void read(MtpDataPacket& packet, bool deviceProp);
+ void read(MtpDataPacket& packet);
void write(MtpDataPacket& packet);
void print();
+ inline bool isDeviceProperty() const {
+ return ( ((mCode & 0xF000) == 0x5000)
+ || ((mCode & 0xF800) == 0xD000));
+ }
+
private:
void readValue(MtpDataPacket& packet, MtpPropertyValue& value);
void writeValue(MtpDataPacket& packet, MtpPropertyValue& value);
MtpPropertyValue* readArrayValues(MtpDataPacket& packet, int& length);
- void writeArrayValues(MtpDataPacket& packet, MtpPropertyValue* values, int length);
+ void writeArrayValues(MtpDataPacket& packet,
+ MtpPropertyValue* values, int length);
};
}; // namespace android
diff --git a/media/mtp/MtpServer.cpp b/media/mtp/MtpServer.cpp
index 1e64e4f..3d3bd62 100644
--- a/media/mtp/MtpServer.cpp
+++ b/media/mtp/MtpServer.cpp
@@ -55,7 +55,7 @@
// MTP_OPERATION_SELF_TEST,
// MTP_OPERATION_SET_OBJECT_PROTECTION,
// MTP_OPERATION_POWER_DOWN,
-// MTP_OPERATION_GET_DEVICE_PROP_DESC,
+ MTP_OPERATION_GET_DEVICE_PROP_DESC,
MTP_OPERATION_GET_DEVICE_PROP_VALUE,
MTP_OPERATION_SET_DEVICE_PROP_VALUE,
MTP_OPERATION_RESET_DEVICE_PROP_VALUE,
@@ -185,6 +185,9 @@
LOGV("skipping response\n");
}
}
+
+ if (mSessionOpen)
+ mDatabase->sessionEnded();
}
void MtpServer::sendObjectAdded(MtpObjectHandle handle) {
@@ -285,6 +288,9 @@
case MTP_OPERATION_GET_OBJECT_PROP_DESC:
response = doGetObjectPropDesc();
break;
+ case MTP_OPERATION_GET_DEVICE_PROP_DESC:
+ response = doGetDevicePropDesc();
+ break;
default:
response = MTP_RESPONSE_OPERATION_NOT_SUPPORTED;
break;
@@ -346,6 +352,9 @@
}
mSessionID = mRequest.getParameter(1);
mSessionOpen = true;
+
+ mDatabase->sessionStarted();
+
return MTP_RESPONSE_OK;
}
@@ -354,6 +363,7 @@
return MTP_RESPONSE_SESSION_NOT_OPEN;
mSessionID = 0;
mSessionOpen = false;
+ mDatabase->sessionEnded();
return MTP_RESPONSE_OK;
}
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index ff31470..3770b55 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -1781,6 +1781,14 @@
if (chain != 0 && chain->setVolume_l(&vl, &vr)) {
// Do not ramp volume is volume is controlled by effect
param = AudioMixer::VOLUME;
+ track->mHasVolumeController = true;
+ } else {
+ // force no volume ramp when volume controller was just disabled or removed
+ // from effect chain to avoid volume spike
+ if (track->mHasVolumeController) {
+ param = AudioMixer::VOLUME;
+ }
+ track->mHasVolumeController = false;
}
// Convert volumes from 8.24 to 4.12 format
@@ -2901,7 +2909,8 @@
const sp<IMemory>& sharedBuffer,
int sessionId)
: TrackBase(thread, client, sampleRate, format, channelCount, frameCount, 0, sharedBuffer, sessionId),
- mMute(false), mSharedBuffer(sharedBuffer), mName(-1), mMainBuffer(NULL), mAuxBuffer(NULL), mAuxEffectId(0)
+ mMute(false), mSharedBuffer(sharedBuffer), mName(-1), mMainBuffer(NULL), mAuxBuffer(NULL),
+ mAuxEffectId(0), mHasVolumeController(false)
{
if (mCblk != NULL) {
sp<ThreadBase> baseThread = thread.promote();
@@ -5371,7 +5380,7 @@
return;
}
- if (mState == ACTIVE || mState == STOPPING || mState == STOPPED || mState == RESTART) {
+ if (isProcessEnabled()) {
// do 32 bit to 16 bit conversion for auxiliary effect input buffer
if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
AudioMixer::ditherAndClamp(mConfig.inputCfg.buffer.s32,
@@ -5600,6 +5609,8 @@
// going from enabled to disabled
case RESTART:
+ mState = STOPPED;
+ break;
case STARTING:
mState = IDLE;
break;
@@ -5632,6 +5643,21 @@
}
}
+bool AudioFlinger::EffectModule::isProcessEnabled()
+{
+ switch (mState) {
+ case RESTART:
+ case ACTIVE:
+ case STOPPING:
+ case STOPPED:
+ return true;
+ case IDLE:
+ case STARTING:
+ default:
+ return false;
+ }
+}
+
status_t AudioFlinger::EffectModule::setVolume(uint32_t *left, uint32_t *right, bool controller)
{
Mutex::Autolock _l(mLock);
@@ -5639,7 +5665,7 @@
// Send volume indication if EFFECT_FLAG_VOLUME_IND is set and read back altered volume
// if controller flag is set (Note that controller == TRUE => EFFECT_FLAG_VOLUME_CTRL set)
- if ((mState >= ACTIVE) &&
+ if (isProcessEnabled() &&
((mDescriptor.flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_CTRL ||
(mDescriptor.flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_IND)) {
status_t cmdStatus;
@@ -5966,12 +5992,14 @@
p,
&rsize,
&reply);
- if (ret == NO_ERROR) {
- if (reply != NO_ERROR) {
- status = reply;
- }
- } else {
+ // stop at first error encountered
+ if (ret != NO_ERROR) {
status = ret;
+ *(int *)pReplyData = reply;
+ break;
+ } else if (reply != NO_ERROR) {
+ *(int *)pReplyData = reply;
+ break;
}
mCblk->serverIndex += size;
}
@@ -5979,8 +6007,10 @@
mCblk->clientIndex = 0;
return status;
} else if (cmdCode == EFFECT_CMD_ENABLE) {
+ *(int *)pReplyData = NO_ERROR;
return enable();
} else if (cmdCode == EFFECT_CMD_DISABLE) {
+ *(int *)pReplyData = NO_ERROR;
return disable();
}
@@ -6288,7 +6318,7 @@
// first update volume controller
for (size_t i = size; i > 0; i--) {
- if ((mEffects[i - 1]->state() >= EffectModule::ACTIVE) &&
+ if (mEffects[i - 1]->isProcessEnabled() &&
(mEffects[i - 1]->desc().flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_CTRL) {
ctrlIdx = i - 1;
hasControl = true;
@@ -6304,9 +6334,6 @@
return hasControl;
}
- if (mVolumeCtrlIdx != -1) {
- hasControl = true;
- }
mVolumeCtrlIdx = ctrlIdx;
mLeftVolume = newLeft;
mRightVolume = newRight;
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 51881f0..5917632 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -514,6 +514,7 @@
int16_t *mMainBuffer;
int32_t *mAuxBuffer;
int mAuxEffectId;
+ bool mHasVolumeController;
}; // end of Track
@@ -965,6 +966,7 @@
}
status_t setEnabled(bool enabled);
bool isEnabled();
+ bool isProcessEnabled();
void setInBuffer(int16_t *buffer) { mConfig.inputCfg.buffer.s16 = buffer; }
int16_t *inBuffer() { return mConfig.inputCfg.buffer.s16; }
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index c6a9909..e5889bf 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -336,11 +336,6 @@
int callingPid = getCallingPid();
LOG1("Client::~Client E (pid %d, this %p)", callingPid, this);
- // Clean up the ANativeWindow
- if (mSurface != 0) {
- setPreviewDisplay(0);
- }
-
// set mClientPid to let disconnet() tear down the hardware
mClientPid = callingPid;
disconnect();
@@ -572,16 +567,10 @@
if (checkPidAndHardware() != NO_ERROR) return;
mPreviewCallbackFlag = callback_flag;
-
- // If we don't use overlay, we always need the preview frame for display.
- // If we do use overlay, we only need the preview frame if the user
- // wants the data.
- if (mUseOverlay) {
- if(mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_ENABLE_MASK) {
- enableMsgType(CAMERA_MSG_PREVIEW_FRAME);
- } else {
- disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
- }
+ if (mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_ENABLE_MASK) {
+ enableMsgType(CAMERA_MSG_PREVIEW_FRAME);
+ } else {
+ disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
}
}
@@ -641,7 +630,6 @@
} else {
// XXX: Set the orientation of the ANativeWindow.
mHardware->setPreviewWindow(mPreviewWindow);
- enableMsgType(CAMERA_MSG_PREVIEW_FRAME);
result = mHardware->startPreview();
}
return result;
@@ -1030,9 +1018,7 @@
mPreviewCallbackFlag &= ~(FRAME_CALLBACK_FLAG_ONE_SHOT_MASK |
FRAME_CALLBACK_FLAG_COPY_OUT_MASK |
FRAME_CALLBACK_FLAG_ENABLE_MASK);
- if (mUseOverlay) {
- disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
- }
+ disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
}
if (c != 0) {