14eaa2938084353a54dc259466172909329a048ccChris Watkins/* 24eaa2938084353a54dc259466172909329a048ccChris Watkins * Copyright 2015, The Android Open Source Project 34eaa2938084353a54dc259466172909329a048ccChris Watkins * 44eaa2938084353a54dc259466172909329a048ccChris Watkins * Licensed under the Apache License, Version 2.0 (the "License"); 54eaa2938084353a54dc259466172909329a048ccChris Watkins * you may not use this file except in compliance with the License. 64eaa2938084353a54dc259466172909329a048ccChris Watkins * You may obtain a copy of the License at 74eaa2938084353a54dc259466172909329a048ccChris Watkins * 84eaa2938084353a54dc259466172909329a048ccChris Watkins * http://www.apache.org/licenses/LICENSE-2.0 94eaa2938084353a54dc259466172909329a048ccChris Watkins * 104eaa2938084353a54dc259466172909329a048ccChris Watkins * Unless required by applicable law or agreed to in writing, software 114eaa2938084353a54dc259466172909329a048ccChris Watkins * distributed under the License is distributed on an "AS IS" BASIS, 124eaa2938084353a54dc259466172909329a048ccChris Watkins * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 134eaa2938084353a54dc259466172909329a048ccChris Watkins * See the License for the specific language governing permissions and 144eaa2938084353a54dc259466172909329a048ccChris Watkins * limitations under the License. 154eaa2938084353a54dc259466172909329a048ccChris Watkins */ 164eaa2938084353a54dc259466172909329a048ccChris Watkins 174eaa2938084353a54dc259466172909329a048ccChris Watkins//#define LOG_NDEBUG 0 184eaa2938084353a54dc259466172909329a048ccChris Watkins#define LOG_TAG "JMediaDataSource-JNI" 194eaa2938084353a54dc259466172909329a048ccChris Watkins#include <utils/Log.h> 204eaa2938084353a54dc259466172909329a048ccChris Watkins 214eaa2938084353a54dc259466172909329a048ccChris Watkins#include "android_media_MediaDataSource.h" 224eaa2938084353a54dc259466172909329a048ccChris Watkins 234eaa2938084353a54dc259466172909329a048ccChris Watkins#include "android_runtime/AndroidRuntime.h" 244eaa2938084353a54dc259466172909329a048ccChris Watkins#include "android_runtime/Log.h" 254eaa2938084353a54dc259466172909329a048ccChris Watkins#include "jni.h" 264eaa2938084353a54dc259466172909329a048ccChris Watkins#include "JNIHelp.h" 274eaa2938084353a54dc259466172909329a048ccChris Watkins 284eaa2938084353a54dc259466172909329a048ccChris Watkins#include <binder/MemoryDealer.h> 29cad52fe423734c12aea2b8e90a2c15952777b536Wei Jia#include <drm/drm_framework_common.h> 304eaa2938084353a54dc259466172909329a048ccChris Watkins#include <media/stagefright/foundation/ADebug.h> 314eaa2938084353a54dc259466172909329a048ccChris Watkins#include <nativehelper/ScopedLocalRef.h> 324eaa2938084353a54dc259466172909329a048ccChris Watkins 334eaa2938084353a54dc259466172909329a048ccChris Watkinsnamespace android { 344eaa2938084353a54dc259466172909329a048ccChris Watkins 354eaa2938084353a54dc259466172909329a048ccChris WatkinsJMediaDataSource::JMediaDataSource(JNIEnv* env, jobject source) 364eaa2938084353a54dc259466172909329a048ccChris Watkins : mJavaObjStatus(OK), mSizeIsCached(false), mCachedSize(0), mMemory(NULL) { 374eaa2938084353a54dc259466172909329a048ccChris Watkins mMediaDataSourceObj = env->NewGlobalRef(source); 384eaa2938084353a54dc259466172909329a048ccChris Watkins CHECK(mMediaDataSourceObj != NULL); 394eaa2938084353a54dc259466172909329a048ccChris Watkins 404eaa2938084353a54dc259466172909329a048ccChris Watkins ScopedLocalRef<jclass> mediaDataSourceClass(env, env->GetObjectClass(mMediaDataSourceObj)); 414eaa2938084353a54dc259466172909329a048ccChris Watkins CHECK(mediaDataSourceClass.get() != NULL); 424eaa2938084353a54dc259466172909329a048ccChris Watkins 43bc10185fa1669a151568feb72277785d323fc344Chong Zhang mReadMethod = env->GetMethodID(mediaDataSourceClass.get(), "readAt", "(J[BII)I"); 444eaa2938084353a54dc259466172909329a048ccChris Watkins CHECK(mReadMethod != NULL); 454eaa2938084353a54dc259466172909329a048ccChris Watkins mGetSizeMethod = env->GetMethodID(mediaDataSourceClass.get(), "getSize", "()J"); 464eaa2938084353a54dc259466172909329a048ccChris Watkins CHECK(mGetSizeMethod != NULL); 474eaa2938084353a54dc259466172909329a048ccChris Watkins mCloseMethod = env->GetMethodID(mediaDataSourceClass.get(), "close", "()V"); 484eaa2938084353a54dc259466172909329a048ccChris Watkins CHECK(mCloseMethod != NULL); 494eaa2938084353a54dc259466172909329a048ccChris Watkins 504eaa2938084353a54dc259466172909329a048ccChris Watkins ScopedLocalRef<jbyteArray> tmp(env, env->NewByteArray(kBufferSize)); 514eaa2938084353a54dc259466172909329a048ccChris Watkins mByteArrayObj = (jbyteArray)env->NewGlobalRef(tmp.get()); 524eaa2938084353a54dc259466172909329a048ccChris Watkins CHECK(mByteArrayObj != NULL); 534eaa2938084353a54dc259466172909329a048ccChris Watkins 544eaa2938084353a54dc259466172909329a048ccChris Watkins sp<MemoryDealer> memoryDealer = new MemoryDealer(kBufferSize, "JMediaDataSource"); 554eaa2938084353a54dc259466172909329a048ccChris Watkins mMemory = memoryDealer->allocate(kBufferSize); 564eaa2938084353a54dc259466172909329a048ccChris Watkins if (mMemory == NULL) { 574eaa2938084353a54dc259466172909329a048ccChris Watkins ALOGE("Failed to allocate memory!"); 584eaa2938084353a54dc259466172909329a048ccChris Watkins } 594eaa2938084353a54dc259466172909329a048ccChris Watkins} 604eaa2938084353a54dc259466172909329a048ccChris Watkins 614eaa2938084353a54dc259466172909329a048ccChris WatkinsJMediaDataSource::~JMediaDataSource() { 624eaa2938084353a54dc259466172909329a048ccChris Watkins JNIEnv* env = AndroidRuntime::getJNIEnv(); 634eaa2938084353a54dc259466172909329a048ccChris Watkins env->DeleteGlobalRef(mMediaDataSourceObj); 644eaa2938084353a54dc259466172909329a048ccChris Watkins env->DeleteGlobalRef(mByteArrayObj); 654eaa2938084353a54dc259466172909329a048ccChris Watkins} 664eaa2938084353a54dc259466172909329a048ccChris Watkins 674eaa2938084353a54dc259466172909329a048ccChris Watkinssp<IMemory> JMediaDataSource::getIMemory() { 684eaa2938084353a54dc259466172909329a048ccChris Watkins Mutex::Autolock lock(mLock); 694eaa2938084353a54dc259466172909329a048ccChris Watkins return mMemory; 704eaa2938084353a54dc259466172909329a048ccChris Watkins} 714eaa2938084353a54dc259466172909329a048ccChris Watkins 724eaa2938084353a54dc259466172909329a048ccChris Watkinsssize_t JMediaDataSource::readAt(off64_t offset, size_t size) { 734eaa2938084353a54dc259466172909329a048ccChris Watkins Mutex::Autolock lock(mLock); 744eaa2938084353a54dc259466172909329a048ccChris Watkins 754eaa2938084353a54dc259466172909329a048ccChris Watkins if (mJavaObjStatus != OK || mMemory == NULL) { 764eaa2938084353a54dc259466172909329a048ccChris Watkins return -1; 774eaa2938084353a54dc259466172909329a048ccChris Watkins } 784eaa2938084353a54dc259466172909329a048ccChris Watkins if (size > kBufferSize) { 794eaa2938084353a54dc259466172909329a048ccChris Watkins size = kBufferSize; 804eaa2938084353a54dc259466172909329a048ccChris Watkins } 814eaa2938084353a54dc259466172909329a048ccChris Watkins 824eaa2938084353a54dc259466172909329a048ccChris Watkins JNIEnv* env = AndroidRuntime::getJNIEnv(); 834eaa2938084353a54dc259466172909329a048ccChris Watkins jint numread = env->CallIntMethod(mMediaDataSourceObj, mReadMethod, 84bc10185fa1669a151568feb72277785d323fc344Chong Zhang (jlong)offset, mByteArrayObj, (jint)0, (jint)size); 854eaa2938084353a54dc259466172909329a048ccChris Watkins if (env->ExceptionCheck()) { 864eaa2938084353a54dc259466172909329a048ccChris Watkins ALOGW("An exception occurred in readAt()"); 874eaa2938084353a54dc259466172909329a048ccChris Watkins LOGW_EX(env); 884eaa2938084353a54dc259466172909329a048ccChris Watkins env->ExceptionClear(); 894eaa2938084353a54dc259466172909329a048ccChris Watkins mJavaObjStatus = UNKNOWN_ERROR; 904eaa2938084353a54dc259466172909329a048ccChris Watkins return -1; 914eaa2938084353a54dc259466172909329a048ccChris Watkins } 924eaa2938084353a54dc259466172909329a048ccChris Watkins if (numread < 0) { 93bc10185fa1669a151568feb72277785d323fc344Chong Zhang if (numread != -1) { 94bc10185fa1669a151568feb72277785d323fc344Chong Zhang ALOGW("An error occurred in readAt()"); 95bc10185fa1669a151568feb72277785d323fc344Chong Zhang mJavaObjStatus = UNKNOWN_ERROR; 96bc10185fa1669a151568feb72277785d323fc344Chong Zhang return -1; 97bc10185fa1669a151568feb72277785d323fc344Chong Zhang } else { 98bc10185fa1669a151568feb72277785d323fc344Chong Zhang // numread == -1 indicates EOF 99bc10185fa1669a151568feb72277785d323fc344Chong Zhang return 0; 100bc10185fa1669a151568feb72277785d323fc344Chong Zhang } 1014eaa2938084353a54dc259466172909329a048ccChris Watkins } 1024eaa2938084353a54dc259466172909329a048ccChris Watkins if ((size_t)numread > size) { 1034eaa2938084353a54dc259466172909329a048ccChris Watkins ALOGE("readAt read too many bytes."); 1044eaa2938084353a54dc259466172909329a048ccChris Watkins mJavaObjStatus = UNKNOWN_ERROR; 1054eaa2938084353a54dc259466172909329a048ccChris Watkins return -1; 1064eaa2938084353a54dc259466172909329a048ccChris Watkins } 1074eaa2938084353a54dc259466172909329a048ccChris Watkins 1084eaa2938084353a54dc259466172909329a048ccChris Watkins ALOGV("readAt %lld / %zu => %d.", (long long)offset, size, numread); 1094eaa2938084353a54dc259466172909329a048ccChris Watkins env->GetByteArrayRegion(mByteArrayObj, 0, numread, (jbyte*)mMemory->pointer()); 1104eaa2938084353a54dc259466172909329a048ccChris Watkins return numread; 1114eaa2938084353a54dc259466172909329a048ccChris Watkins} 1124eaa2938084353a54dc259466172909329a048ccChris Watkins 1134eaa2938084353a54dc259466172909329a048ccChris Watkinsstatus_t JMediaDataSource::getSize(off64_t* size) { 1144eaa2938084353a54dc259466172909329a048ccChris Watkins Mutex::Autolock lock(mLock); 1154eaa2938084353a54dc259466172909329a048ccChris Watkins 1164eaa2938084353a54dc259466172909329a048ccChris Watkins if (mJavaObjStatus != OK) { 1174eaa2938084353a54dc259466172909329a048ccChris Watkins return UNKNOWN_ERROR; 1184eaa2938084353a54dc259466172909329a048ccChris Watkins } 1194eaa2938084353a54dc259466172909329a048ccChris Watkins if (mSizeIsCached) { 1207c7fef1585b7ec36d181b0f797f2713cb2dde291Lajos Molnar *size = mCachedSize; 1217c7fef1585b7ec36d181b0f797f2713cb2dde291Lajos Molnar return OK; 1224eaa2938084353a54dc259466172909329a048ccChris Watkins } 1234eaa2938084353a54dc259466172909329a048ccChris Watkins 1244eaa2938084353a54dc259466172909329a048ccChris Watkins JNIEnv* env = AndroidRuntime::getJNIEnv(); 1254eaa2938084353a54dc259466172909329a048ccChris Watkins *size = env->CallLongMethod(mMediaDataSourceObj, mGetSizeMethod); 1264eaa2938084353a54dc259466172909329a048ccChris Watkins if (env->ExceptionCheck()) { 1274eaa2938084353a54dc259466172909329a048ccChris Watkins ALOGW("An exception occurred in getSize()"); 1284eaa2938084353a54dc259466172909329a048ccChris Watkins LOGW_EX(env); 1294eaa2938084353a54dc259466172909329a048ccChris Watkins env->ExceptionClear(); 1304eaa2938084353a54dc259466172909329a048ccChris Watkins // After returning an error, size shouldn't be used by callers. 1314eaa2938084353a54dc259466172909329a048ccChris Watkins *size = UNKNOWN_ERROR; 1324eaa2938084353a54dc259466172909329a048ccChris Watkins mJavaObjStatus = UNKNOWN_ERROR; 1334eaa2938084353a54dc259466172909329a048ccChris Watkins return UNKNOWN_ERROR; 1344eaa2938084353a54dc259466172909329a048ccChris Watkins } 1354eaa2938084353a54dc259466172909329a048ccChris Watkins 1364eaa2938084353a54dc259466172909329a048ccChris Watkins // The minimum size should be -1, which indicates unknown size. 1374eaa2938084353a54dc259466172909329a048ccChris Watkins if (*size < 0) { 1384eaa2938084353a54dc259466172909329a048ccChris Watkins *size = -1; 1394eaa2938084353a54dc259466172909329a048ccChris Watkins } 1404eaa2938084353a54dc259466172909329a048ccChris Watkins 1414eaa2938084353a54dc259466172909329a048ccChris Watkins mCachedSize = *size; 1424eaa2938084353a54dc259466172909329a048ccChris Watkins mSizeIsCached = true; 1434eaa2938084353a54dc259466172909329a048ccChris Watkins return OK; 1444eaa2938084353a54dc259466172909329a048ccChris Watkins} 1454eaa2938084353a54dc259466172909329a048ccChris Watkins 1464eaa2938084353a54dc259466172909329a048ccChris Watkinsvoid JMediaDataSource::close() { 1474eaa2938084353a54dc259466172909329a048ccChris Watkins Mutex::Autolock lock(mLock); 1484eaa2938084353a54dc259466172909329a048ccChris Watkins 1494eaa2938084353a54dc259466172909329a048ccChris Watkins JNIEnv* env = AndroidRuntime::getJNIEnv(); 1504eaa2938084353a54dc259466172909329a048ccChris Watkins env->CallVoidMethod(mMediaDataSourceObj, mCloseMethod); 1514eaa2938084353a54dc259466172909329a048ccChris Watkins // The closed state is effectively the same as an error state. 1524eaa2938084353a54dc259466172909329a048ccChris Watkins mJavaObjStatus = UNKNOWN_ERROR; 1534eaa2938084353a54dc259466172909329a048ccChris Watkins} 1544eaa2938084353a54dc259466172909329a048ccChris Watkins 155fbc164ba3c2105265b031503bdfebdbcd7256fbeWei Jiauint32_t JMediaDataSource::getFlags() { 156fbc164ba3c2105265b031503bdfebdbcd7256fbeWei Jia return 0; 157fbc164ba3c2105265b031503bdfebdbcd7256fbeWei Jia} 158fbc164ba3c2105265b031503bdfebdbcd7256fbeWei Jia 15973c74698d094e57af60d55afc790a72a966ae263Marco NelissenString8 JMediaDataSource::toString() { 16073c74698d094e57af60d55afc790a72a966ae263Marco Nelissen return String8::format("JMediaDataSource(pid %d, uid %d)", getpid(), getuid()); 16173c74698d094e57af60d55afc790a72a966ae263Marco Nelissen} 16273c74698d094e57af60d55afc790a72a966ae263Marco Nelissen 163cad52fe423734c12aea2b8e90a2c15952777b536Wei Jiasp<DecryptHandle> JMediaDataSource::DrmInitialization(const char * /* mime */) { 164cad52fe423734c12aea2b8e90a2c15952777b536Wei Jia return NULL; 165cad52fe423734c12aea2b8e90a2c15952777b536Wei Jia} 166cad52fe423734c12aea2b8e90a2c15952777b536Wei Jia 1674eaa2938084353a54dc259466172909329a048ccChris Watkins} // namespace android 168