| /* |
| * 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 <android-base/logging.h> |
| |
| #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<hidl_string *>(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; |
| } |
| |
| #define DEFINE_ALLOC_VECTOR_METHODS(Suffix,Type,NewType) \ |
| const hidl_vec<Type> *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<Type>)); \ |
| \ |
| hidl_vec<Type> *vec = new (vecPtr) hidl_vec<Type>; \ |
| vec->setToExternal(const_cast<Type *>(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; \ |
| } |
| |
| 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<hidl_string *>(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) |
| |
| default: |
| CHECK(!"Should not be here"); |
| } |
| } |
| |
| mItems.clear(); |
| } |
| |
| } // namespace android |
| |