android_media_MediaDescrambler.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469
  1. /*
  2. * Copyright 2017, The Android Open Source Project
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. //#define LOG_NDEBUG 0
  17. #define LOG_TAG "MediaDescrambler-JNI"
  18. #include <utils/Log.h>
  19. #include "android_media_MediaDescrambler.h"
  20. #include "android_runtime/AndroidRuntime.h"
  21. #include "android_os_HwRemoteBinder.h"
  22. #include <nativehelper/JNIHelp.h>
  23. #include <android/hardware/cas/native/1.0/BpHwDescrambler.h>
  24. #include <android/hardware/cas/native/1.0/BnHwDescrambler.h>
  25. #include <android/hardware/cas/native/1.0/IDescrambler.h>
  26. #include <binder/MemoryDealer.h>
  27. #include <hidl/HidlSupport.h>
  28. #include <hidlmemory/FrameworkUtils.h>
  29. #include <media/stagefright/foundation/ADebug.h>
  30. #include <media/cas/DescramblerAPI.h>
  31. #include <nativehelper/ScopedLocalRef.h>
  32. namespace android {
  33. class IMemory;
  34. class MemoryDealer;
  35. namespace hardware {
  36. class HidlMemory;
  37. };
  38. using hardware::fromHeap;
  39. using hardware::HidlMemory;
  40. using hardware::hidl_string;
  41. using hardware::hidl_vec;
  42. using namespace hardware::cas::V1_0;
  43. using namespace hardware::cas::native::V1_0;
  44. struct JDescrambler : public RefBase {
  45. JDescrambler(JNIEnv *env, jobject descramberBinderObj);
  46. status_t descramble(
  47. uint32_t key,
  48. ssize_t totalLength,
  49. const hidl_vec<SubSample>& subSamples,
  50. const void *srcPtr,
  51. jint srcOffset,
  52. void *dstPtr,
  53. jint dstOffset,
  54. Status *status,
  55. uint32_t *bytesWritten,
  56. hidl_string *detailedError);
  57. protected:
  58. virtual ~JDescrambler();
  59. private:
  60. sp<IDescrambler> mDescrambler;
  61. sp<IMemory> mMem;
  62. sp<MemoryDealer> mDealer;
  63. sp<HidlMemory> mHidlMemory;
  64. SharedBuffer mDescramblerSrcBuffer;
  65. Mutex mSharedMemLock;
  66. bool ensureBufferCapacity(size_t neededSize);
  67. DISALLOW_EVIL_CONSTRUCTORS(JDescrambler);
  68. };
  69. struct fields_t {
  70. jfieldID context;
  71. jbyte flagPesHeader;
  72. };
  73. static fields_t gFields;
  74. static sp<JDescrambler> getDescrambler(JNIEnv *env, jobject thiz) {
  75. return (JDescrambler *)env->GetLongField(thiz, gFields.context);
  76. }
  77. static void setDescrambler(
  78. JNIEnv *env, jobject thiz, const sp<JDescrambler> &descrambler) {
  79. sp<JDescrambler> old = (JDescrambler *)env->GetLongField(thiz, gFields.context);
  80. if (descrambler != NULL) {
  81. descrambler->incStrong(thiz);
  82. }
  83. if (old != NULL) {
  84. old->decStrong(thiz);
  85. }
  86. env->SetLongField(thiz, gFields.context, (jlong)descrambler.get());
  87. }
  88. static status_t getBufferAndSize(
  89. JNIEnv *env, jobject byteBuf, jint offset, jint limit, size_t length,
  90. void **outPtr, jbyteArray *outByteArray) {
  91. void *ptr = env->GetDirectBufferAddress(byteBuf);
  92. jbyteArray byteArray = NULL;
  93. ScopedLocalRef<jclass> byteBufClass(env, env->FindClass("java/nio/ByteBuffer"));
  94. CHECK(byteBufClass.get() != NULL);
  95. if (ptr == NULL) {
  96. jmethodID arrayID =
  97. env->GetMethodID(byteBufClass.get(), "array", "()[B");
  98. CHECK(arrayID != NULL);
  99. byteArray =
  100. (jbyteArray)env->CallObjectMethod(byteBuf, arrayID);
  101. if (byteArray == NULL) {
  102. return INVALID_OPERATION;
  103. }
  104. jboolean isCopy;
  105. ptr = env->GetByteArrayElements(byteArray, &isCopy);
  106. }
  107. if ((jint)length + offset > limit) {
  108. if (byteArray != NULL) {
  109. env->ReleaseByteArrayElements(byteArray, (jbyte *)ptr, 0);
  110. }
  111. return -ERANGE;
  112. }
  113. *outPtr = ptr;
  114. *outByteArray = byteArray;
  115. return OK;
  116. }
  117. JDescrambler::JDescrambler(JNIEnv *env, jobject descramblerBinderObj) {
  118. mDescrambler = GetDescrambler(env, descramblerBinderObj);
  119. if (mDescrambler == NULL) {
  120. jniThrowException(env, "java/lang/NullPointerException", NULL);
  121. }
  122. }
  123. JDescrambler::~JDescrambler() {
  124. // Don't call release() here, it's called by Java class
  125. mDescrambler.clear();
  126. mMem.clear();
  127. mDealer.clear();
  128. }
  129. sp<IDescrambler> GetDescrambler(JNIEnv *env, jobject obj) {
  130. if (obj != NULL) {
  131. sp<hardware::IBinder> hwBinder =
  132. JHwRemoteBinder::GetNativeContext(env, obj)->getBinder();
  133. if (hwBinder != NULL) {
  134. return hardware::fromBinder<
  135. IDescrambler, BpHwDescrambler, BnHwDescrambler>(hwBinder);
  136. }
  137. }
  138. return NULL;
  139. }
  140. bool JDescrambler::ensureBufferCapacity(size_t neededSize) {
  141. if (mMem != NULL && mMem->size() >= neededSize) {
  142. return true;
  143. }
  144. ALOGV("ensureBufferCapacity: current size %zu, new size %zu",
  145. mMem == NULL ? 0 : mMem->size(), neededSize);
  146. size_t alignment = MemoryDealer::getAllocationAlignment();
  147. neededSize = (neededSize + (alignment - 1)) & ~(alignment - 1);
  148. // Align to multiples of 64K.
  149. neededSize = (neededSize + 65535) & ~65535;
  150. mDealer = new MemoryDealer(neededSize, "JDescrambler");
  151. mMem = mDealer->allocate(neededSize);
  152. ssize_t offset;
  153. size_t size;
  154. sp<IMemoryHeap> heap = mMem->getMemory(&offset, &size);
  155. if (heap == NULL) {
  156. return false;
  157. }
  158. mHidlMemory = fromHeap(heap);
  159. mDescramblerSrcBuffer.heapBase = *mHidlMemory;
  160. mDescramblerSrcBuffer.offset = (uint64_t) offset;
  161. mDescramblerSrcBuffer.size = (uint64_t) size;
  162. return true;
  163. }
  164. status_t JDescrambler::descramble(
  165. uint32_t key,
  166. ssize_t totalLength,
  167. const hidl_vec<SubSample>& subSamples,
  168. const void *srcPtr,
  169. jint srcOffset,
  170. void *dstPtr,
  171. jint dstOffset,
  172. Status *status,
  173. uint32_t *bytesWritten,
  174. hidl_string *detailedError) {
  175. // TODO: IDescrambler::descramble() is re-entrant, however because we
  176. // only have 1 shared mem buffer, we can only do 1 descramble at a time.
  177. // Concurrency might be improved by allowing on-demand allocation of up
  178. // to 2 shared mem buffers.
  179. Mutex::Autolock autolock(mSharedMemLock);
  180. if (!ensureBufferCapacity(totalLength)) {
  181. return NO_MEMORY;
  182. }
  183. memcpy(mMem->pointer(),
  184. (const void*)((const uint8_t*)srcPtr + srcOffset), totalLength);
  185. DestinationBuffer dstBuffer;
  186. dstBuffer.type = BufferType::SHARED_MEMORY;
  187. dstBuffer.nonsecureMemory = mDescramblerSrcBuffer;
  188. auto err = mDescrambler->descramble(
  189. (ScramblingControl) key,
  190. subSamples,
  191. mDescramblerSrcBuffer,
  192. 0,
  193. dstBuffer,
  194. 0,
  195. [&status, &bytesWritten, &detailedError] (
  196. Status _status, uint32_t _bytesWritten,
  197. const hidl_string& _detailedError) {
  198. *status = _status;
  199. *bytesWritten = _bytesWritten;
  200. *detailedError = _detailedError;
  201. });
  202. if (!err.isOk()) {
  203. return FAILED_TRANSACTION;
  204. }
  205. if (*status == Status::OK) {
  206. if (*bytesWritten > 0 && (ssize_t) *bytesWritten <= totalLength) {
  207. memcpy((void*)((uint8_t*)dstPtr + dstOffset), mMem->pointer(), *bytesWritten);
  208. } else {
  209. // status seems OK but bytesWritten is invalid, we really
  210. // have no idea what is wrong.
  211. *status = Status::ERROR_CAS_UNKNOWN;
  212. }
  213. }
  214. return OK;
  215. }
  216. } // namespace android
  217. using namespace android;
  218. static void android_media_MediaDescrambler_native_release(JNIEnv *env, jobject thiz) {
  219. setDescrambler(env, thiz, NULL);
  220. }
  221. static void android_media_MediaDescrambler_native_init(JNIEnv *env) {
  222. ScopedLocalRef<jclass> clazz(
  223. env, env->FindClass("android/media/MediaDescrambler"));
  224. CHECK(clazz.get() != NULL);
  225. gFields.context = env->GetFieldID(clazz.get(), "mNativeContext", "J");
  226. CHECK(gFields.context != NULL);
  227. jfieldID fieldPesHeader = env->GetStaticFieldID(
  228. clazz.get(), "SCRAMBLE_FLAG_PES_HEADER", "B");
  229. CHECK(fieldPesHeader != NULL);
  230. gFields.flagPesHeader = env->GetStaticByteField(clazz.get(), fieldPesHeader);
  231. }
  232. static void android_media_MediaDescrambler_native_setup(
  233. JNIEnv *env, jobject thiz, jobject descramblerBinderObj) {
  234. setDescrambler(env, thiz, new JDescrambler(env, descramblerBinderObj));
  235. }
  236. static ssize_t getSubSampleInfo(JNIEnv *env, jint numSubSamples,
  237. jintArray numBytesOfClearDataObj, jintArray numBytesOfEncryptedDataObj,
  238. hidl_vec<SubSample> *outSubSamples) {
  239. if (numSubSamples <= 0 ||
  240. numSubSamples >= (signed)(INT32_MAX / sizeof(SubSample))) {
  241. // subSamples array may silently overflow if number of samples are
  242. // too large. Use INT32_MAX as maximum allocation size may be less
  243. // than SIZE_MAX on some platforms.
  244. ALOGE("numSubSamples is invalid!");
  245. return -1;
  246. }
  247. jboolean isCopy;
  248. ssize_t totalSize = 0;
  249. jint *numBytesOfClearData =
  250. (numBytesOfClearDataObj == NULL)
  251. ? NULL
  252. : env->GetIntArrayElements(numBytesOfClearDataObj, &isCopy);
  253. jint *numBytesOfEncryptedData =
  254. (numBytesOfEncryptedDataObj == NULL)
  255. ? NULL
  256. : env->GetIntArrayElements(numBytesOfEncryptedDataObj, &isCopy);
  257. outSubSamples->resize(numSubSamples);
  258. SubSample *subSamples = outSubSamples->data();
  259. if (subSamples == NULL) {
  260. ALOGE("Failed to allocate SubSample array!");
  261. return -1;
  262. }
  263. for (jint i = 0; i < numSubSamples; ++i) {
  264. subSamples[i].numBytesOfClearData =
  265. (numBytesOfClearData == NULL) ? 0 : numBytesOfClearData[i];
  266. subSamples[i].numBytesOfEncryptedData =
  267. (numBytesOfEncryptedData == NULL)
  268. ? 0 : numBytesOfEncryptedData[i];
  269. totalSize += subSamples[i].numBytesOfClearData +
  270. subSamples[i].numBytesOfEncryptedData;
  271. }
  272. if (numBytesOfEncryptedData != NULL) {
  273. env->ReleaseIntArrayElements(
  274. numBytesOfEncryptedDataObj, numBytesOfEncryptedData, 0);
  275. numBytesOfEncryptedData = NULL;
  276. }
  277. if (numBytesOfClearData != NULL) {
  278. env->ReleaseIntArrayElements(
  279. numBytesOfClearDataObj, numBytesOfClearData, 0);
  280. numBytesOfClearData = NULL;
  281. }
  282. if (totalSize < 0) {
  283. return -1;
  284. }
  285. return totalSize;
  286. }
  287. static jthrowable createServiceSpecificException(
  288. JNIEnv *env, int serviceSpecificError, const char *msg) {
  289. if (env->ExceptionCheck()) {
  290. ALOGW("Discarding pending exception");
  291. env->ExceptionDescribe();
  292. env->ExceptionClear();
  293. }
  294. ScopedLocalRef<jclass> clazz(
  295. env, env->FindClass("android/os/ServiceSpecificException"));
  296. CHECK(clazz.get() != NULL);
  297. const jmethodID ctor = env->GetMethodID(clazz.get(), "<init>", "(ILjava/lang/String;)V");
  298. CHECK(ctor != NULL);
  299. ScopedLocalRef<jstring> msgObj(
  300. env, env->NewStringUTF(msg != NULL ?
  301. msg : String8::format("Error %#x", serviceSpecificError)));
  302. return (jthrowable)env->NewObject(
  303. clazz.get(), ctor, serviceSpecificError, msgObj.get());
  304. }
  305. static jint android_media_MediaDescrambler_native_descramble(
  306. JNIEnv *env, jobject thiz, jbyte key, jbyte flags, jint numSubSamples,
  307. jintArray numBytesOfClearDataObj, jintArray numBytesOfEncryptedDataObj,
  308. jobject srcBuf, jint srcOffset, jint srcLimit,
  309. jobject dstBuf, jint dstOffset, jint dstLimit) {
  310. sp<JDescrambler> descrambler = getDescrambler(env, thiz);
  311. if (descrambler == NULL) {
  312. jniThrowException(env, "java/lang/IllegalStateException",
  313. "Invalid descrambler object!");
  314. return -1;
  315. }
  316. hidl_vec<SubSample> subSamples;
  317. ssize_t totalLength = getSubSampleInfo(
  318. env, numSubSamples, numBytesOfClearDataObj,
  319. numBytesOfEncryptedDataObj, &subSamples);
  320. if (totalLength < 0) {
  321. jniThrowException(env, "java/lang/IllegalArgumentException",
  322. "Invalid subsample info!");
  323. return -1;
  324. }
  325. void *srcPtr = NULL, *dstPtr = NULL;
  326. jbyteArray srcArray = NULL, dstArray = NULL;
  327. status_t err = getBufferAndSize(
  328. env, srcBuf, srcOffset, srcLimit, totalLength, &srcPtr, &srcArray);
  329. if (err == OK) {
  330. if (dstBuf == NULL) {
  331. dstPtr = srcPtr;
  332. } else {
  333. err = getBufferAndSize(
  334. env, dstBuf, dstOffset, dstLimit, totalLength, &dstPtr, &dstArray);
  335. }
  336. }
  337. if (err != OK) {
  338. jniThrowException(env, "java/lang/IllegalArgumentException",
  339. "Invalid buffer offset and/or size for subsamples!");
  340. return -1;
  341. }
  342. uint32_t scramblingControl = (uint32_t)key;
  343. if (flags & gFields.flagPesHeader) {
  344. scramblingControl |= DescramblerPlugin::kScrambling_Flag_PesHeader;
  345. }
  346. Status status;
  347. uint32_t bytesWritten;
  348. hidl_string detailedError;
  349. err = descrambler->descramble(
  350. scramblingControl, totalLength, subSamples,
  351. srcPtr, srcOffset, dstPtr, dstOffset,
  352. &status, &bytesWritten, &detailedError);
  353. // Release byte array before throwing
  354. if (srcArray != NULL) {
  355. env->ReleaseByteArrayElements(srcArray, (jbyte *)srcPtr, 0);
  356. }
  357. if (dstArray != NULL) {
  358. env->ReleaseByteArrayElements(dstArray, (jbyte *)dstPtr, 0);
  359. }
  360. if (err == NO_MEMORY) {
  361. jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
  362. } else if (err == FAILED_TRANSACTION) {
  363. jniThrowException(env, "android/os/RemoteException", NULL);
  364. } else if (status != Status::OK) {
  365. // Throw ServiceSpecific with cas error code and detailed msg,
  366. // which will be re-thrown as MediaCasStateException.
  367. env->Throw(createServiceSpecificException(
  368. env, (int) status, detailedError.c_str()));
  369. }
  370. return bytesWritten;
  371. }
  372. static const JNINativeMethod gMethods[] = {
  373. { "native_release", "()V",
  374. (void *)android_media_MediaDescrambler_native_release },
  375. { "native_init", "()V",
  376. (void *)android_media_MediaDescrambler_native_init },
  377. { "native_setup", "(Landroid/os/IHwBinder;)V",
  378. (void *)android_media_MediaDescrambler_native_setup },
  379. { "native_descramble", "(BBI[I[ILjava/nio/ByteBuffer;IILjava/nio/ByteBuffer;II)I",
  380. (void *)android_media_MediaDescrambler_native_descramble },
  381. };
  382. int register_android_media_Descrambler(JNIEnv *env) {
  383. return AndroidRuntime::registerNativeMethods(env,
  384. "android/media/MediaDescrambler", gMethods, NELEM(gMethods));
  385. }