/* * Copyright (C) 2016 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_TAG "EphemeralStorage" //#define LOG_NDEBUG 0 #include #include "EphemeralStorage.h" using ::android::hardware::hidl_string; using ::android::hardware::hidl_vec; namespace android { EphemeralStorage::EphemeralStorage() { } EphemeralStorage::~EphemeralStorage() { CHECK(mItems.empty()) << "All item storage should have been released by now."; } hidl_string *EphemeralStorage::allocStringArray(size_t size) { Item item; item.mType = TYPE_STRING_ARRAY; item.mObj = NULL; item.mPtr = new hidl_string[size]; mItems.push_back(item); return static_cast(item.mPtr); } void *EphemeralStorage::allocTemporaryStorage(size_t size) { Item item; item.mType = TYPE_STORAGE; item.mObj = NULL; item.mPtr = malloc(size); mItems.push_back(item); return item.mPtr; } const hidl_string *EphemeralStorage::allocTemporaryString( JNIEnv *env, jstring stringObj) { jstring obj = (jstring)env->NewGlobalRef(stringObj); const char *val = env->GetStringUTFChars(obj, NULL); Item item; item.mType = TYPE_STRING; item.mObj = obj; item.mPtr = (void *)val; mItems.push_back(item); hidl_string *s = allocStringArray(1 /* size */); s->setToExternal((char *)val, strlen(val)); return s; } native_handle_t *EphemeralStorage::allocTemporaryNativeHandle( int numFds, int numInts) { Item item; item.mType = TYPE_NATIVE_HANDLE; item.mObj = nullptr; item.mPtr = native_handle_create(numFds, numInts); mItems.push_back(item); return static_cast(item.mPtr); } #define DEFINE_ALLOC_VECTOR_METHODS(Suffix,Type,NewType) \ const hidl_vec *EphemeralStorage::allocTemporary ## Suffix ## Vector( \ JNIEnv *env, Type ## Array arrayObj) { \ Type ## Array obj = (Type ## Array)env->NewGlobalRef(arrayObj); \ jsize len = env->GetArrayLength(obj); \ const Type *val = env->Get ## NewType ## ArrayElements(obj, NULL); \ \ Item item; \ item.mType = TYPE_ ## Suffix ## _ARRAY; \ item.mObj = obj; \ item.mPtr = (void *)val; \ mItems.push_back(item); \ \ void *vecPtr = allocTemporaryStorage(sizeof(hidl_vec)); \ \ hidl_vec *vec = new (vecPtr) hidl_vec; \ vec->setToExternal(const_cast(val), len); \ \ return vec; \ } DEFINE_ALLOC_VECTOR_METHODS(Int8,jbyte,Byte) DEFINE_ALLOC_VECTOR_METHODS(Int16,jshort,Short) DEFINE_ALLOC_VECTOR_METHODS(Int32,jint,Int) DEFINE_ALLOC_VECTOR_METHODS(Int64,jlong,Long) DEFINE_ALLOC_VECTOR_METHODS(Float,jfloat,Float) DEFINE_ALLOC_VECTOR_METHODS(Double,jdouble,Double) #define DEFINE_RELEASE_ARRAY_CASE(Suffix,Type,NewType) \ case TYPE_ ## Suffix ## _ARRAY: \ { \ env->Release ## NewType ## ArrayElements( \ (Type ## Array)item.mObj, \ (Type *)item.mPtr, \ 0 /* mode */); \ \ env->DeleteGlobalRef(item.mObj); \ break; \ } __attribute__((no_sanitize("unsigned-integer-overflow"))) void EphemeralStorage::release(JNIEnv *env) { for (size_t i = mItems.size(); i--;) { const Item &item = mItems[i]; switch (item.mType) { case TYPE_STRING_ARRAY: { delete[] static_cast(item.mPtr); break; } case TYPE_STORAGE: { free(item.mPtr); break; } case TYPE_STRING: { env->ReleaseStringUTFChars( (jstring)item.mObj, (const char *)item.mPtr); env->DeleteGlobalRef(item.mObj); break; } DEFINE_RELEASE_ARRAY_CASE(Int8,jbyte,Byte) DEFINE_RELEASE_ARRAY_CASE(Int16,jshort,Short) DEFINE_RELEASE_ARRAY_CASE(Int32,jint,Int) DEFINE_RELEASE_ARRAY_CASE(Int64,jlong,Long) DEFINE_RELEASE_ARRAY_CASE(Float,jfloat,Float) DEFINE_RELEASE_ARRAY_CASE(Double,jdouble,Double) case TYPE_NATIVE_HANDLE: { int err = native_handle_delete(static_cast(item.mPtr)); CHECK(err == 0); break; } default: CHECK(!"Should not be here"); } } mItems.clear(); } } // namespace android