/*
* 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/DrmMetadata.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
#define MAX_BINDER_TRANSACTION_SIZE ((1*1024*1024)-(4096*2))
using namespace android;
static void writeDecryptHandleToParcelData(
const DecryptHandle* handle, Parcel* data) {
data->writeInt32(handle->decryptId);
data->writeString8(handle->mimeType);
data->writeInt32(handle->decryptApiType);
data->writeInt32(handle->status);
int size = handle->copyControlVector.size();
data->writeInt32(size);
for (int i = 0; i < size; i++) {
data->writeInt32(handle->copyControlVector.keyAt(i));
data->writeInt32(handle->copyControlVector.valueAt(i));
}
size = handle->extendedData.size();
data->writeInt32(size);
for (int i = 0; i < size; i++) {
data->writeString8(handle->extendedData.keyAt(i));
data->writeString8(handle->extendedData.valueAt(i));
}
if (NULL != handle->decryptInfo) {
data->writeInt32(handle->decryptInfo->decryptBufferLength);
} else {
data->writeInt32(INVALID_BUFFER_LENGTH);
}
}
static void readDecryptHandleFromParcelData(
DecryptHandle* handle, const Parcel& data) {
if (0 == data.dataAvail()) {
return;
}
handle->decryptId = data.readInt32();
handle->mimeType = data.readString8();
handle->decryptApiType = data.readInt32();
handle->status = data.readInt32();
int size = data.readInt32();
for (int i = 0; i < size; i++) {
DrmCopyControl key = (DrmCopyControl)data.readInt32();
int value = data.readInt32();
handle->copyControlVector.add(key, value);
}
size = data.readInt32();
for (int i = 0; i < size; i++) {
String8 key = data.readString8();
String8 value = data.readString8();
handle->extendedData.add(key, value);
}
handle->decryptInfo = NULL;
const int bufferLen = data.readInt32();
if (INVALID_BUFFER_LENGTH != bufferLen) {
handle->decryptInfo = new DecryptInfo();
handle->decryptInfo->decryptBufferLength = bufferLen;
}
}
static void clearDecryptHandle(DecryptHandle* handle) {
if (handle == NULL) {
return;
}
if (handle->decryptInfo) {
delete handle->decryptInfo;
handle->decryptInfo = NULL;
}
handle->copyControlVector.clear();
handle->extendedData.clear();
}
int BpDrmManagerService::addUniqueId(bool isNative) {
ALOGV("add uniqueid");
Parcel data, reply;
data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
data.writeInt32(isNative);
remote()->transact(ADD_UNIQUEID, data, &reply);
return reply.readInt32();
}
void BpDrmManagerService::removeUniqueId(int uniqueId) {
ALOGV("remove uniqueid");
Parcel data, reply;
data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
data.writeInt32(uniqueId);
remote()->transact(REMOVE_UNIQUEID, data, &reply);
}
void BpDrmManagerService::addClient(int uniqueId) {
Parcel data, reply;
data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
data.writeInt32(uniqueId);
remote()->transact(ADD_CLIENT, data, &reply);
}
void BpDrmManagerService::removeClient(int uniqueId) {
Parcel data, reply;
data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
data.writeInt32(uniqueId);
remote()->transact(REMOVE_CLIENT, data, &reply);
}
status_t BpDrmManagerService::setDrmServiceListener(
int uniqueId, const sp<IDrmServiceListener>& drmServiceListener) {
ALOGV("setDrmServiceListener");
Parcel data, reply;
data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
data.writeInt32(uniqueId);
data.writeStrongBinder(IInterface::asBinder(drmServiceListener));
remote()->transact(SET_DRM_SERVICE_LISTENER, data, &reply);
return reply.readInt32();
}
DrmConstraints* BpDrmManagerService::getConstraints(
int uniqueId, const String8* path, const int action) {
ALOGV("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);
delete[] data;
}
}
}
return drmConstraints;
}
DrmMetadata* BpDrmManagerService::getMetadata(int uniqueId, const String8* path) {
ALOGV("Get Metadata");
Parcel data, reply;
data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
data.writeInt32(uniqueId);
DrmMetadata* drmMetadata = NULL;
data.writeString8(*path);
remote()->transact(GET_METADATA_FROM_CONTENT, data, &reply);
if (0 != reply.dataAvail()) {
//Filling Drm Metadata
drmMetadata = new DrmMetadata();
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);
drmMetadata->put(&key, data);
delete[] data;
}
}
}
return drmMetadata;
}
bool BpDrmManagerService::canHandle(int uniqueId, const String8& path, const String8& mimeType) {
ALOGV("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) {
ALOGV("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 int infoType = 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, infoType, drmBuffer, mimeType);
}
return drmInfoStatus;
}
DrmInfo* BpDrmManagerService::acquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInforequest) {
ALOGV("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);
if (key == String8("FileDescriptorKey")) {
int fd = -1;
sscanf(value.string(), "FileDescriptor[%d]", &fd);
data.writeFileDescriptor(fd);
} else {
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;
}
status_t BpDrmManagerService::saveRights(
int uniqueId, const DrmRights& drmRights,
const String8& rightsPath, const String8& contentPath) {
ALOGV("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);
return reply.readInt32();
}
String8 BpDrmManagerService::getOriginalMimeType(int uniqueId, const String8& path, int fd) {
ALOGV("Get Original MimeType");
Parcel data, reply;
data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
data.writeInt32(uniqueId);
data.writeString8(path);
int32_t isFdValid = (fd >= 0);
data.writeInt32(isFdValid);
if (isFdValid) {
data.writeFileDescriptor(fd);
}
remote()->transact(GET_ORIGINAL_MIMETYPE, data, &reply);
return reply.readString8();
}
int BpDrmManagerService::getDrmObjectType(
int uniqueId, const String8& path, const String8& mimeType) {
ALOGV("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) {
ALOGV("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();
}
status_t BpDrmManagerService::consumeRights(
int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve) {
ALOGV("consumeRights");
Parcel data, reply;
data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
data.writeInt32(uniqueId);
writeDecryptHandleToParcelData(decryptHandle, &data);
data.writeInt32(action);
data.writeInt32(static_cast< int>(reserve));
remote()->transact(CONSUME_RIGHTS, data, &reply);
return reply.readInt32();
}
status_t BpDrmManagerService::setPlaybackStatus(
int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int64_t position) {
ALOGV("setPlaybackStatus");
Parcel data, reply;
data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
data.writeInt32(uniqueId);
writeDecryptHandleToParcelData(decryptHandle, &data);
data.writeInt32(playbackStatus);
data.writeInt64(position);
remote()->transact(SET_PLAYBACK_STATUS, data, &reply);
return reply.readInt32();
}
bool BpDrmManagerService::validateAction(
int uniqueId, const String8& path,
int action, const ActionDescription& description) {
ALOGV("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());
}
status_t BpDrmManagerService::removeRights(int uniqueId, const String8& path) {
ALOGV("removeRights");
Parcel data, reply;
data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
data.writeInt32(uniqueId);
data.writeString8(path);
remote()->transact(REMOVE_RIGHTS, data, &reply);
return reply.readInt32();
}
status_t BpDrmManagerService::removeAllRights(int uniqueId) {
ALOGV("removeAllRights");
Parcel data, reply;
data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
data.writeInt32(uniqueId);
remote()->transact(REMOVE_ALL_RIGHTS, data, &reply);
return reply.readInt32();
}
int BpDrmManagerService::openConvertSession(int uniqueId, const String8& mimeType) {
ALOGV("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) {
ALOGV("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 off64_t offset = reply.readInt64();
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) {
ALOGV("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 off64_t offset = reply.readInt64();
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) {
ALOGV("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, off64_t offset, off64_t length, const char* mime) {
ALOGV("Entering BpDrmManagerService::openDecryptSession");
Parcel data, reply;
data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
data.writeInt32(uniqueId);
data.writeFileDescriptor(fd);
data.writeInt64(offset);
data.writeInt64(length);
String8 mimeType;
if (mime) {
mimeType = mime;
}
data.writeString8(mimeType);
remote()->transact(OPEN_DECRYPT_SESSION, data, &reply);
DecryptHandle* handle = NULL;
if (0 != reply.dataAvail()) {
handle = new DecryptHandle();
readDecryptHandleFromParcelData(handle, reply);
}
return handle;
}
DecryptHandle* BpDrmManagerService::openDecryptSession(
int uniqueId, const char* uri, const char* mime) {
ALOGV("Entering BpDrmManagerService::openDecryptSession: mime=%s", mime? mime: "NULL");
Parcel data, reply;
data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
data.writeInt32(uniqueId);
data.writeString8(String8(uri));
String8 mimeType;
if (mime) {
mimeType = mime;
}
data.writeString8(mimeType);
remote()->transact(OPEN_DECRYPT_SESSION_FROM_URI, data, &reply);
DecryptHandle* handle = NULL;
if (0 != reply.dataAvail()) {
handle = new DecryptHandle();
readDecryptHandleFromParcelData(handle, reply);
} else {
ALOGV("no decryptHandle is generated in service side");
}
return handle;
}
DecryptHandle* BpDrmManagerService::openDecryptSession(
int uniqueId, const DrmBuffer& buf, const String8& mimeType) {
ALOGV("Entering BpDrmManagerService::openDecryptSession");
Parcel data, reply;
data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
data.writeInt32(uniqueId);
if (buf.data != NULL && buf.length > 0) {
data.writeInt32(buf.length);
data.write(buf.data, buf.length);
} else {
data.writeInt32(0);
}
data.writeString8(mimeType);
remote()->transact(OPEN_DECRYPT_SESSION_FOR_STREAMING, data, &reply);
DecryptHandle* handle = NULL;
if (0 != reply.dataAvail()) {
handle = new DecryptHandle();
readDecryptHandleFromParcelData(handle, reply);
} else {
ALOGV("no decryptHandle is generated in service side");
}
return handle;
}
status_t BpDrmManagerService::closeDecryptSession(int uniqueId, DecryptHandle* decryptHandle) {
ALOGV("closeDecryptSession");
Parcel data, reply;
data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
data.writeInt32(uniqueId);
writeDecryptHandleToParcelData(decryptHandle, &data);
remote()->transact(CLOSE_DECRYPT_SESSION, data, &reply);
return reply.readInt32();
}
status_t BpDrmManagerService::initializeDecryptUnit(
int uniqueId, DecryptHandle* decryptHandle,
int decryptUnitId, const DrmBuffer* headerInfo) {
ALOGV("initializeDecryptUnit");
Parcel data, reply;
data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
data.writeInt32(uniqueId);
writeDecryptHandleToParcelData(decryptHandle, &data);
data.writeInt32(decryptUnitId);
data.writeInt32(headerInfo->length);
data.write(headerInfo->data, headerInfo->length);
remote()->transact(INITIALIZE_DECRYPT_UNIT, data, &reply);
return reply.readInt32();
}
status_t BpDrmManagerService::decrypt(
int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId,
const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV) {
ALOGV("decrypt");
Parcel data, reply;
data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
data.writeInt32(uniqueId);
writeDecryptHandleToParcelData(decryptHandle, &data);
data.writeInt32(decryptUnitId);
data.writeInt32((*decBuffer)->length);
data.writeInt32(encBuffer->length);
data.write(encBuffer->data, encBuffer->length);
if (NULL != IV) {
data.writeInt32(IV->length);
data.write(IV->data, IV->length);
}
remote()->transact(DECRYPT, data, &reply);
const status_t status = reply.readInt32();
ALOGV("Return value of decrypt() is %d", status);
if (status == NO_ERROR) {
const int size = reply.readInt32();
(*decBuffer)->length = size;
reply.read((void *)(*decBuffer)->data, size);
}
return status;
}
status_t BpDrmManagerService::finalizeDecryptUnit(
int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId) {
ALOGV("finalizeDecryptUnit");
Parcel data, reply;
data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
data.writeInt32(uniqueId);
writeDecryptHandleToParcelData(decryptHandle, &data);
data.writeInt32(decryptUnitId);
remote()->transact(FINALIZE_DECRYPT_UNIT, data, &reply);
return reply.readInt32();
}
ssize_t BpDrmManagerService::pread(
int uniqueId, DecryptHandle* decryptHandle, void* buffer,
ssize_t numBytes, off64_t offset) {
ALOGV("read");
Parcel data, reply;
int result;
data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
data.writeInt32(uniqueId);
writeDecryptHandleToParcelData(decryptHandle, &data);
data.writeInt32(numBytes);
data.writeInt64(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) {
ALOGV("Entering BnDrmManagerService::onTransact with code %d", code);
switch (code) {
case ADD_UNIQUEID:
{
ALOGV("BnDrmManagerService::onTransact :ADD_UNIQUEID");
CHECK_INTERFACE(IDrmManagerService, data, reply);
int uniqueId = addUniqueId(data.readInt32());
reply->writeInt32(uniqueId);
return DRM_NO_ERROR;
}
case REMOVE_UNIQUEID:
{
ALOGV("BnDrmManagerService::onTransact :REMOVE_UNIQUEID");
CHECK_INTERFACE(IDrmManagerService, data, reply);
removeUniqueId(data.readInt32());
return DRM_NO_ERROR;
}
case ADD_CLIENT:
{
ALOGV("BnDrmManagerService::onTransact :ADD_CLIENT");
CHECK_INTERFACE(IDrmManagerService, data, reply);
addClient(data.readInt32());
return DRM_NO_ERROR;
}
case REMOVE_CLIENT:
{
ALOGV("BnDrmManagerService::onTransact :REMOVE_CLIENT");
CHECK_INTERFACE(IDrmManagerService, data, reply);
removeClient(data.readInt32());
return DRM_NO_ERROR;
}
case SET_DRM_SERVICE_LISTENER:
{
ALOGV("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 GET_CONSTRAINTS_FROM_CONTENT:
{
ALOGV("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);
} else {
reply->writeInt32(0);
}
}
}
delete drmConstraints; drmConstraints = NULL;
return DRM_NO_ERROR;
}
case GET_METADATA_FROM_CONTENT:
{
ALOGV("BnDrmManagerService::onTransact :GET_METADATA_FROM_CONTENT");
CHECK_INTERFACE(IDrmManagerService, data, reply);
const int uniqueId = data.readInt32();
const String8 path = data.readString8();
DrmMetadata* drmMetadata = getMetadata(uniqueId, &path);
if (NULL != drmMetadata) {
//Filling DRM Metadata contents
reply->writeInt32(drmMetadata->getCount());
DrmMetadata::KeyIterator keyIt = drmMetadata->keyIterator();
while (keyIt.hasNext()) {
const String8 key = keyIt.next();
reply->writeString8(key);
const char* value = drmMetadata->getAsByteArray(&key);
int bufferSize = 0;
if (NULL != value) {
bufferSize = strlen(value);
reply->writeInt32(bufferSize + 1);
reply->write(value, bufferSize + 1);
} else {
reply->writeInt32(0);
}
}
}
delete drmMetadata; drmMetadata = NULL;
return NO_ERROR;
}
case CAN_HANDLE:
{
ALOGV("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:
{
ALOGV("BnDrmManagerService::onTransact :PROCESS_DRM_INFO");
CHECK_INTERFACE(IDrmManagerService, data, reply);
const int uniqueId = data.readInt32();
//Filling DRM info
const int infoType = data.readInt32();
const uint32_t bufferSize = data.readInt32();
if (bufferSize > data.dataAvail()) {
return BAD_VALUE;
}
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->writeInt32(drmInfoStatus->infoType);
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:
{
ALOGV("BnDrmManagerService::onTransact :ACQUIRE_DRM_INFO");
CHECK_INTERFACE(IDrmManagerService, data, reply);
const int uniqueId = data.readInt32();
//Filling DRM info Request
const int infoType = data.readInt32();
const String8 mimeType = data.readString8();
DrmInfoRequest* drmInfoRequest = new DrmInfoRequest(infoType, mimeType);
const int size = data.readInt32();
for (int index = 0; index < size; ++index) {
if (!data.dataAvail()) {
break;
}
const String8 key(data.readString8());
if (key == String8("FileDescriptorKey")) {
char buffer[16];
int fd = data.readFileDescriptor();
sprintf(buffer, "%lu", (unsigned long)fd);
drmInfoRequest->put(key, String8(buffer));
} else {
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:
{
ALOGV("BnDrmManagerService::onTransact :SAVE_RIGHTS");
CHECK_INTERFACE(IDrmManagerService, data, reply);
const int uniqueId = data.readInt32();
//Filling DRM Rights
const uint32_t bufferSize = data.readInt32();
if (bufferSize > data.dataAvail()) {
reply->writeInt32(BAD_VALUE);
return DRM_NO_ERROR;
}
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));
const status_t status = saveRights(uniqueId, drmRights,
((rightsPath == String8("NULL")) ? String8("") : rightsPath),
((contentPath == String8("NULL")) ? String8("") : contentPath));
reply->writeInt32(status);
return DRM_NO_ERROR;
}
case GET_ORIGINAL_MIMETYPE:
{
ALOGV("BnDrmManagerService::onTransact :GET_ORIGINAL_MIMETYPE");
CHECK_INTERFACE(IDrmManagerService, data, reply);
const int uniqueId = data.readInt32();
const String8 path = data.readString8();
const int32_t isFdValid = data.readInt32();
int fd = -1;
if (isFdValid) {
fd = data.readFileDescriptor();
}
const String8 originalMimeType = getOriginalMimeType(uniqueId, path, fd);
reply->writeString8(originalMimeType);
return DRM_NO_ERROR;
}
case GET_DRM_OBJECT_TYPE:
{
ALOGV("BnDrmManagerService::onTransact :GET_DRM_OBJECT_TYPE");
CHECK_INTERFACE(IDrmManagerService, data, reply);
const int uniqueId = data.readInt32();
const String8 path = data.readString8();
const String8 mimeType = data.readString8();
const int drmObjectType = getDrmObjectType(uniqueId, path, mimeType);
reply->writeInt32(drmObjectType);
return DRM_NO_ERROR;
}
case CHECK_RIGHTS_STATUS:
{
ALOGV("BnDrmManagerService::onTransact :CHECK_RIGHTS_STATUS");
CHECK_INTERFACE(IDrmManagerService, data, reply);
const int uniqueId = data.readInt32();
const String8 path = data.readString8();
const int action = data.readInt32();
const int result = checkRightsStatus(uniqueId, path, action);
reply->writeInt32(result);
return DRM_NO_ERROR;
}
case CONSUME_RIGHTS:
{
ALOGV("BnDrmManagerService::onTransact :CONSUME_RIGHTS");
CHECK_INTERFACE(IDrmManagerService, data, reply);
const int uniqueId = data.readInt32();
DecryptHandle handle;
readDecryptHandleFromParcelData(&handle, data);
const int action = data.readInt32();
const bool reserve = static_cast<bool>(data.readInt32());
const status_t status
= consumeRights(uniqueId, &handle, action, reserve);
reply->writeInt32(status);
clearDecryptHandle(&handle);
return DRM_NO_ERROR;
}
case SET_PLAYBACK_STATUS:
{
ALOGV("BnDrmManagerService::onTransact :SET_PLAYBACK_STATUS");
CHECK_INTERFACE(IDrmManagerService, data, reply);
const int uniqueId = data.readInt32();
DecryptHandle handle;
readDecryptHandleFromParcelData(&handle, data);
const int playbackStatus = data.readInt32();
const int64_t position = data.readInt64();
const status_t status
= setPlaybackStatus(uniqueId, &handle, playbackStatus, position);
reply->writeInt32(status);
clearDecryptHandle(&handle);
return DRM_NO_ERROR;
}
case VALIDATE_ACTION:
{
ALOGV("BnDrmManagerService::onTransact :VALIDATE_ACTION");
CHECK_INTERFACE(IDrmManagerService, data, reply);
const int uniqueId = data.readInt32();
const String8 path = data.readString8();
const int action = data.readInt32();
const int outputType = data.readInt32();
const int configuration = data.readInt32();
bool result = validateAction(uniqueId, path, action,
ActionDescription(outputType, configuration));
reply->writeInt32(result);
return DRM_NO_ERROR;
}
case REMOVE_RIGHTS:
{
ALOGV("BnDrmManagerService::onTransact :REMOVE_RIGHTS");
CHECK_INTERFACE(IDrmManagerService, data, reply);
int uniqueId = data.readInt32();
String8 path = data.readString8();
const status_t status = removeRights(uniqueId, path);
reply->writeInt32(status);
return DRM_NO_ERROR;
}
case REMOVE_ALL_RIGHTS:
{
ALOGV("BnDrmManagerService::onTransact :REMOVE_ALL_RIGHTS");
CHECK_INTERFACE(IDrmManagerService, data, reply);
const status_t status = removeAllRights(data.readInt32());
reply->writeInt32(status);
return DRM_NO_ERROR;
}
case OPEN_CONVERT_SESSION:
{
ALOGV("BnDrmManagerService::onTransact :OPEN_CONVERT_SESSION");
CHECK_INTERFACE(IDrmManagerService, data, reply);
const int uniqueId = data.readInt32();
const String8 mimeType = data.readString8();
const int convertId = openConvertSession(uniqueId, mimeType);
reply->writeInt32(convertId);
return DRM_NO_ERROR;
}
case CONVERT_DATA:
{
ALOGV("BnDrmManagerService::onTransact :CONVERT_DATA");
CHECK_INTERFACE(IDrmManagerService, data, reply);
const int uniqueId = data.readInt32();
const int convertId = data.readInt32();
//Filling input data
const uint32_t bufferSize = data.readInt32();
if (bufferSize > data.dataAvail()) {
return BAD_VALUE;
}
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->writeInt64(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:
{
ALOGV("BnDrmManagerService::onTransact :CLOSE_CONVERT_SESSION");
CHECK_INTERFACE(IDrmManagerService, data, reply);
const int uniqueId = data.readInt32();
const int convertId = data.readInt32();
DrmConvertedStatus* drmConvertedStatus
= closeConvertSession(uniqueId, convertId);
if (NULL != drmConvertedStatus) {
//Filling Drm Converted Ststus
reply->writeInt32(drmConvertedStatus->statusCode);
reply->writeInt64(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:
{
ALOGV("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:
{
ALOGV("BnDrmManagerService::onTransact :OPEN_DECRYPT_SESSION");
CHECK_INTERFACE(IDrmManagerService, data, reply);
const int uniqueId = data.readInt32();
const int fd = data.readFileDescriptor();
const off64_t offset = data.readInt64();
const off64_t length = data.readInt64();
const String8 mime = data.readString8();
DecryptHandle* handle
= openDecryptSession(uniqueId, fd, offset, length, mime.string());
if (NULL != handle) {
writeDecryptHandleToParcelData(handle, reply);
clearDecryptHandle(handle);
delete handle; handle = NULL;
}
return DRM_NO_ERROR;
}
case OPEN_DECRYPT_SESSION_FROM_URI:
{
ALOGV("BnDrmManagerService::onTransact :OPEN_DECRYPT_SESSION_FROM_URI");
CHECK_INTERFACE(IDrmManagerService, data, reply);
const int uniqueId = data.readInt32();
const String8 uri = data.readString8();
const String8 mime = data.readString8();
DecryptHandle* handle = openDecryptSession(uniqueId, uri.string(), mime.string());
if (NULL != handle) {
writeDecryptHandleToParcelData(handle, reply);
clearDecryptHandle(handle);
delete handle; handle = NULL;
} else {
ALOGV("NULL decryptHandle is returned");
}
return DRM_NO_ERROR;
}
case OPEN_DECRYPT_SESSION_FOR_STREAMING:
{
ALOGV("BnDrmManagerService::onTransact :OPEN_DECRYPT_SESSION_FOR_STREAMING");
CHECK_INTERFACE(IDrmManagerService, data, reply);
const int uniqueId = data.readInt32();
const int bufferSize = data.readInt32();
DrmBuffer buf((bufferSize > 0) ? (char *)data.readInplace(bufferSize) : NULL,
bufferSize);
const String8 mimeType(data.readString8());
DecryptHandle* handle = openDecryptSession(uniqueId, buf, mimeType);
if (handle != NULL) {
writeDecryptHandleToParcelData(handle, reply);
clearDecryptHandle(handle);
delete handle;
handle = NULL;
} else {
ALOGV("NULL decryptHandle is returned");
}
return DRM_NO_ERROR;
}
case CLOSE_DECRYPT_SESSION:
{
ALOGV("BnDrmManagerService::onTransact :CLOSE_DECRYPT_SESSION");
CHECK_INTERFACE(IDrmManagerService, data, reply);
const int uniqueId = data.readInt32();
DecryptHandle* handle = new DecryptHandle();
readDecryptHandleFromParcelData(handle, data);
const status_t status = closeDecryptSession(uniqueId, handle);
reply->writeInt32(status);
return DRM_NO_ERROR;
}
case INITIALIZE_DECRYPT_UNIT:
{
ALOGV("BnDrmManagerService::onTransact :INITIALIZE_DECRYPT_UNIT");
CHECK_INTERFACE(IDrmManagerService, data, reply);
const int uniqueId = data.readInt32();
DecryptHandle handle;
readDecryptHandleFromParcelData(&handle, data);
const int decryptUnitId = data.readInt32();
//Filling Header info
const uint32_t bufferSize = data.readInt32();
if (bufferSize > data.dataAvail()) {
reply->writeInt32(BAD_VALUE);
clearDecryptHandle(&handle);
return DRM_NO_ERROR;
}
DrmBuffer* headerInfo = NULL;
headerInfo = new DrmBuffer((char *)data.readInplace(bufferSize), bufferSize);
const status_t status
= initializeDecryptUnit(uniqueId, &handle, decryptUnitId, headerInfo);
reply->writeInt32(status);
clearDecryptHandle(&handle);
delete headerInfo; headerInfo = NULL;
return DRM_NO_ERROR;
}
case DECRYPT:
{
ALOGV("BnDrmManagerService::onTransact :DECRYPT");
CHECK_INTERFACE(IDrmManagerService, data, reply);
const int uniqueId = data.readInt32();
DecryptHandle handle;
readDecryptHandleFromParcelData(&handle, data);
const int decryptUnitId = data.readInt32();
const uint32_t decBufferSize = data.readInt32();
const uint32_t encBufferSize = data.readInt32();
if (encBufferSize > data.dataAvail() ||
decBufferSize > MAX_BINDER_TRANSACTION_SIZE) {
reply->writeInt32(BAD_VALUE);
reply->writeInt32(0);
clearDecryptHandle(&handle);
return DRM_NO_ERROR;
}
DrmBuffer* encBuffer
= new DrmBuffer((char *)data.readInplace(encBufferSize), encBufferSize);
char* buffer = NULL;
buffer = new char[decBufferSize];
DrmBuffer* decBuffer = new DrmBuffer(buffer, decBufferSize);
DrmBuffer* IV = NULL;
if (0 != data.dataAvail()) {
const uint32_t ivBufferlength = data.readInt32();
if (ivBufferlength <= data.dataAvail()) {
IV = new DrmBuffer((char *)data.readInplace(ivBufferlength), ivBufferlength);
}
}
const status_t status
= decrypt(uniqueId, &handle, decryptUnitId, encBuffer, &decBuffer, IV);
reply->writeInt32(status);
if (status == NO_ERROR) {
const int size = decBuffer->length;
reply->writeInt32(size);
reply->write(decBuffer->data, size);
}
clearDecryptHandle(&handle);
delete encBuffer; encBuffer = NULL;
delete decBuffer; decBuffer = NULL;
delete [] buffer; buffer = NULL;
delete IV; IV = NULL;
return DRM_NO_ERROR;
}
case FINALIZE_DECRYPT_UNIT:
{
ALOGV("BnDrmManagerService::onTransact :FINALIZE_DECRYPT_UNIT");
CHECK_INTERFACE(IDrmManagerService, data, reply);
const int uniqueId = data.readInt32();
DecryptHandle handle;
readDecryptHandleFromParcelData(&handle, data);
const status_t status = finalizeDecryptUnit(uniqueId, &handle, data.readInt32());
reply->writeInt32(status);
clearDecryptHandle(&handle);
return DRM_NO_ERROR;
}
case PREAD:
{
ALOGV("BnDrmManagerService::onTransact :READ");
CHECK_INTERFACE(IDrmManagerService, data, reply);
const int uniqueId = data.readInt32();
DecryptHandle handle;
readDecryptHandleFromParcelData(&handle, data);
const uint32_t numBytes = data.readInt32();
if (numBytes > MAX_BINDER_TRANSACTION_SIZE) {
reply->writeInt32(BAD_VALUE);
return DRM_NO_ERROR;
}
char* buffer = new char[numBytes];
const off64_t offset = data.readInt64();
ssize_t result = pread(uniqueId, &handle, buffer, numBytes, offset);
reply->writeInt32(result);
if (0 < result) {
reply->write(buffer, result);
}
clearDecryptHandle(&handle);
delete [] buffer, buffer = NULL;
return DRM_NO_ERROR;
}
default:
return BBinder::onTransact(code, data, reply, flags);
}
}