19266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber/* 29266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber * Copyright (C) 2016 The Android Open Source Project 39266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber * 49266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber * Licensed under the Apache License, Version 2.0 (the "License"); 59266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber * you may not use this file except in compliance with the License. 69266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber * You may obtain a copy of the License at 79266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber * 89266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber * http://www.apache.org/licenses/LICENSE-2.0 99266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber * 109266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber * Unless required by applicable law or agreed to in writing, software 119266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber * distributed under the License is distributed on an "AS IS" BASIS, 129266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber * See the License for the specific language governing permissions and 149266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber * limitations under the License. 159266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber */ 169266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 179266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber//#define LOG_NDEBUG 0 189266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber#define LOG_TAG "android_os_HwBlob" 199266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber#include <android-base/logging.h> 209266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 219266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber#include "android_os_HwBlob.h" 229266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 239266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber#include "android_os_HwParcel.h" 249266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 259266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber#include <JNIHelp.h> 269266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber#include <android_runtime/AndroidRuntime.h> 27aa2c32f92b199cb40b808554ced67af1edaffef5Martijn Coenen#include <hidl/Status.h> 289266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber#include <nativehelper/ScopedLocalRef.h> 299266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 309266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber#include "core_jni_helpers.h" 319266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 329266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huberusing android::AndroidRuntime; 339266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huberusing android::hardware::hidl_string; 349266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 359266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber#define PACKAGE_PATH "android/os" 369266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber#define CLASS_NAME "HwBlob" 379266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber#define CLASS_PATH PACKAGE_PATH "/" CLASS_NAME 389266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 399266f9928d5b3431982cd04f4d6946b70f40766aAndreas Hubernamespace android { 409266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 419266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huberstatic struct fields_t { 429266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber jfieldID contextID; 439266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber jmethodID constructID; 449266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 459266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber} gFields; 469266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 479266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber// static 489266f9928d5b3431982cd04f4d6946b70f40766aAndreas Hubervoid JHwBlob::InitClass(JNIEnv *env) { 499266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber ScopedLocalRef<jclass> clazz( 509266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber env, FindClassOrDie(env, CLASS_PATH)); 519266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 529266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber gFields.contextID = 539266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber GetFieldIDOrDie(env, clazz.get(), "mNativeContext", "J"); 549266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 559266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber gFields.constructID = GetMethodIDOrDie(env, clazz.get(), "<init>", "(I)V"); 569266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber} 579266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 589266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber// static 599266f9928d5b3431982cd04f4d6946b70f40766aAndreas Hubersp<JHwBlob> JHwBlob::SetNativeContext( 609266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber JNIEnv *env, jobject thiz, const sp<JHwBlob> &context) { 619266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber sp<JHwBlob> old = (JHwBlob *)env->GetLongField(thiz, gFields.contextID); 629266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 639266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber if (context != NULL) { 649266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber context->incStrong(NULL /* id */); 659266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber } 669266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 679266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber if (old != NULL) { 689266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber old->decStrong(NULL /* id */); 699266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber } 709266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 719266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber env->SetLongField(thiz, gFields.contextID, (long)context.get()); 729266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 739266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber return old; 749266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber} 759266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 769266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber// static 779266f9928d5b3431982cd04f4d6946b70f40766aAndreas Hubersp<JHwBlob> JHwBlob::GetNativeContext(JNIEnv *env, jobject thiz) { 789266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber return (JHwBlob *)env->GetLongField(thiz, gFields.contextID); 799266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber} 809266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 819266f9928d5b3431982cd04f4d6946b70f40766aAndreas HuberJHwBlob::JHwBlob(JNIEnv *env, jobject thiz, size_t size) 829266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber : mBuffer(nullptr), 839266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber mSize(size), 849266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber mOwnsBuffer(true), 859266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber mHandle(0) { 869266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber jclass clazz = env->GetObjectClass(thiz); 879266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber CHECK(clazz != NULL); 889266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 899266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber mClass = (jclass)env->NewGlobalRef(clazz); 909266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber mObject = env->NewWeakGlobalRef(thiz); 919266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 929266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber if (size > 0) { 939266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber mBuffer = malloc(size); 949266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber } 959266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber} 969266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 979266f9928d5b3431982cd04f4d6946b70f40766aAndreas HuberJHwBlob::~JHwBlob() { 989266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber if (mOwnsBuffer) { 999266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber free(mBuffer); 1009266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber mBuffer = nullptr; 1019266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber } 1029266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 1039266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber JNIEnv *env = AndroidRuntime::getJNIEnv(); 1049266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 1059266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber env->DeleteWeakGlobalRef(mObject); 1069266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber mObject = NULL; 1079266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 1089266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber env->DeleteGlobalRef(mClass); 1099266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber mClass = NULL; 1109266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber} 1119266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 1129266f9928d5b3431982cd04f4d6946b70f40766aAndreas Hubervoid JHwBlob::setTo(const void *ptr, size_t handle) { 1139266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber CHECK_EQ(mSize, 0u); 1149266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber CHECK(mBuffer == nullptr); 1159266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 1169266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber mBuffer = const_cast<void *>(ptr); 1179266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber mSize = SIZE_MAX; // XXX 1189266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber mOwnsBuffer = false; 1199266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber mHandle = handle; 1209266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber} 1219266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 1229266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huberstatus_t JHwBlob::getHandle(size_t *handle) const { 1239266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber if (mOwnsBuffer) { 1249266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber return INVALID_OPERATION; 1259266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber } 1269266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 1279266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber *handle = mHandle; 1289266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 1299266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber return OK; 1309266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber} 1319266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 1329266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huberstatus_t JHwBlob::read(size_t offset, void *data, size_t size) const { 1339266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber if (offset + size > mSize) { 1349266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber return -ERANGE; 1359266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber } 1369266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 1379266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber memcpy(data, (const uint8_t *)mBuffer + offset, size); 1389266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 1399266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber return OK; 1409266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber} 1419266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 1429266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huberstatus_t JHwBlob::write(size_t offset, const void *data, size_t size) { 1439266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber if (offset + size > mSize) { 1449266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber return -ERANGE; 1459266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber } 1469266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 1479266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber memcpy((uint8_t *)mBuffer + offset, data, size); 1489266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 1499266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber return OK; 1509266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber} 1519266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 1529266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huberstatus_t JHwBlob::getString(size_t offset, const hidl_string **s) const { 1539266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber if ((offset + sizeof(hidl_string)) > mSize) { 1549266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber return -ERANGE; 1559266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber } 1569266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 1579266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber *s = reinterpret_cast<const hidl_string *>( 1589266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber (const uint8_t *)mBuffer + offset); 1599266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 1609266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber return OK; 1619266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber} 1629266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 1639266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huberconst void *JHwBlob::data() const { 1649266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber return mBuffer; 1659266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber} 1669266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 1679266f9928d5b3431982cd04f4d6946b70f40766aAndreas Hubersize_t JHwBlob::size() const { 1689266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber return mSize; 1699266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber} 1709266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 1719266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huberstatus_t JHwBlob::putBlob(size_t offset, const sp<JHwBlob> &blob) { 1729266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber size_t index = mSubBlobs.add(); 1739266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber BlobInfo *info = &mSubBlobs.editItemAt(index); 1749266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 1759266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber info->mOffset = offset; 1769266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber info->mBlob = blob; 1779266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 1789266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber const void *data = blob->data(); 1799266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 1809266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber return write(offset, &data, sizeof(data)); 1819266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber} 1829266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 1839266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huberstatus_t JHwBlob::writeToParcel(hardware::Parcel *parcel) const { 1849266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber size_t handle; 1859266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber status_t err = parcel->writeBuffer(data(), size(), &handle); 1869266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 1879266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber if (err != OK) { 1889266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber return err; 1899266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber } 1909266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 1919266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber for (size_t i = 0; i < mSubBlobs.size(); ++i) { 1929266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber const BlobInfo &info = mSubBlobs[i]; 1939266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 1949266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber err = info.mBlob->writeEmbeddedToParcel(parcel, handle, info.mOffset); 1959266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 1969266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber if (err != OK) { 1979266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber return err; 1989266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber } 1999266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber } 2009266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 2019266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber return OK; 2029266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber} 2039266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 2049266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huberstatus_t JHwBlob::writeEmbeddedToParcel( 2059266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber hardware::Parcel *parcel, 2069266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber size_t parentHandle, 2079266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber size_t parentOffset) const { 2089266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber size_t handle; 2099266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber status_t err = parcel->writeEmbeddedBuffer( 2109266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber data(), size(), &handle, parentHandle, parentOffset); 2119266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 2129266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber if (err != OK) { 2139266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber return err; 2149266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber } 2159266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 2169266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber for (size_t i = 0; i < mSubBlobs.size(); ++i) { 2179266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber const BlobInfo &info = mSubBlobs[i]; 2189266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 2199266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber err = info.mBlob->writeEmbeddedToParcel(parcel, handle, info.mOffset); 2209266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 2219266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber if (err != OK) { 2229266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber return err; 2239266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber } 2249266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber } 2259266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 2269266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber return OK; 2279266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber} 2289266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 2299266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber// static 2309266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huberjobject JHwBlob::NewObject(JNIEnv *env, const void *ptr, size_t handle) { 2319266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber jobject obj = JHwBlob::NewObject(env, 0 /* size */); 2329266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber JHwBlob::GetNativeContext(env, obj)->setTo(ptr, handle); 2339266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 2349266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber return obj; 2359266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber} 2369266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 2379266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber// static 2389266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huberjobject JHwBlob::NewObject(JNIEnv *env, size_t size) { 2399266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber ScopedLocalRef<jclass> clazz(env, FindClassOrDie(env, CLASS_PATH)); 2409266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 2419266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber jmethodID constructID = 2429266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber GetMethodIDOrDie(env, clazz.get(), "<init>", "(I)V"); 2439266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 2449266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber // XXX Again cannot refer to gFields.constructID because InitClass may 2459266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber // not have been called yet. 2469266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 2479266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber return env->NewObject(clazz.get(), constructID, size); 2489266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber} 2499266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 2509266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber} // namespace android 2519266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 2529266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber//////////////////////////////////////////////////////////////////////////////// 2539266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 2549266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huberusing namespace android; 2559266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 2569266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huberstatic void releaseNativeContext(void *nativeContext) { 2579266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber sp<JHwBlob> parcel = (JHwBlob *)nativeContext; 2589266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 2599266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber if (parcel != NULL) { 2609266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber parcel->decStrong(NULL /* id */); 2619266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber } 2629266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber} 2639266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 2649266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huberstatic jlong JHwBlob_native_init(JNIEnv *env) { 2659266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber JHwBlob::InitClass(env); 2669266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 2679266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber return reinterpret_cast<jlong>(&releaseNativeContext); 2689266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber} 2699266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 2709266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huberstatic void JHwBlob_native_setup( 2719266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber JNIEnv *env, jobject thiz, jint size) { 2729266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber sp<JHwBlob> context = new JHwBlob(env, thiz, size); 2739266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 2749266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber JHwBlob::SetNativeContext(env, thiz, context); 2759266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber} 2769266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 2779266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber#define DEFINE_BLOB_GETTER(Suffix,Type) \ 2789266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huberstatic Type JHwBlob_native_get ## Suffix( \ 2799266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber JNIEnv *env, jobject thiz, jlong offset) { \ 2809266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber sp<JHwBlob> blob = JHwBlob::GetNativeContext(env, thiz); \ 2819266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber \ 2829266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber Type x; \ 2839266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber status_t err = blob->read(offset, &x, sizeof(x)); \ 2849266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber \ 2859266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber if (err != OK) { \ 2869266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber signalExceptionForError(env, err); \ 2879266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber return 0; \ 2889266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber } \ 2899266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber \ 2909266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber return x; \ 2919266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber} 2929266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 2939266f9928d5b3431982cd04f4d6946b70f40766aAndreas HuberDEFINE_BLOB_GETTER(Int8,jbyte) 2949266f9928d5b3431982cd04f4d6946b70f40766aAndreas HuberDEFINE_BLOB_GETTER(Int16,jshort) 2959266f9928d5b3431982cd04f4d6946b70f40766aAndreas HuberDEFINE_BLOB_GETTER(Int32,jint) 2969266f9928d5b3431982cd04f4d6946b70f40766aAndreas HuberDEFINE_BLOB_GETTER(Int64,jlong) 2979266f9928d5b3431982cd04f4d6946b70f40766aAndreas HuberDEFINE_BLOB_GETTER(Float,jfloat) 2989266f9928d5b3431982cd04f4d6946b70f40766aAndreas HuberDEFINE_BLOB_GETTER(Double,jdouble) 2999266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 3009266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huberstatic jboolean JHwBlob_native_getBool( 3019266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber JNIEnv *env, jobject thiz, jlong offset) { 3029266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber sp<JHwBlob> blob = JHwBlob::GetNativeContext(env, thiz); 3039266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 3049266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber bool x; 3059266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber status_t err = blob->read(offset, &x, sizeof(x)); 3069266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 3079266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber if (err != OK) { 3089266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber signalExceptionForError(env, err); 3099266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber return 0; 3109266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber } 3119266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 3129266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber return (jboolean)x; 3139266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber} 3149266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 3159266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huberstatic jstring JHwBlob_native_getString( 3169266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber JNIEnv *env, jobject thiz, jlong offset) { 3179266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber sp<JHwBlob> blob = JHwBlob::GetNativeContext(env, thiz); 3189266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 3199266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber const hidl_string *s; 3209266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber status_t err = blob->getString(offset, &s); 3219266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 3229266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber if (err != OK) { 3239266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber signalExceptionForError(env, err); 3249266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber return nullptr; 3259266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber } 3269266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 3279266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber return env->NewStringUTF(s->c_str()); 3289266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber} 3299266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 3309266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber#define DEFINE_BLOB_PUTTER(Suffix,Type) \ 3319266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huberstatic void JHwBlob_native_put ## Suffix( \ 3329266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber JNIEnv *env, jobject thiz, jlong offset, Type x) { \ 3339266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber \ 3349266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber sp<JHwBlob> blob = JHwBlob::GetNativeContext(env, thiz); \ 3359266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber \ 3369266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber status_t err = blob->write(offset, &x, sizeof(x)); \ 3379266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber \ 3389266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber if (err != OK) { \ 3399266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber signalExceptionForError(env, err); \ 3409266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber } \ 3419266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber} 3429266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 3439266f9928d5b3431982cd04f4d6946b70f40766aAndreas HuberDEFINE_BLOB_PUTTER(Int8,jbyte) 3449266f9928d5b3431982cd04f4d6946b70f40766aAndreas HuberDEFINE_BLOB_PUTTER(Int16,jshort) 3459266f9928d5b3431982cd04f4d6946b70f40766aAndreas HuberDEFINE_BLOB_PUTTER(Int32,jint) 3469266f9928d5b3431982cd04f4d6946b70f40766aAndreas HuberDEFINE_BLOB_PUTTER(Int64,jlong) 3479266f9928d5b3431982cd04f4d6946b70f40766aAndreas HuberDEFINE_BLOB_PUTTER(Float,jfloat) 3489266f9928d5b3431982cd04f4d6946b70f40766aAndreas HuberDEFINE_BLOB_PUTTER(Double,jdouble) 3499266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 3509266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huberstatic void JHwBlob_native_putBool( 3519266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber JNIEnv *env, jobject thiz, jlong offset, jboolean x) { 3529266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 3539266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber sp<JHwBlob> blob = JHwBlob::GetNativeContext(env, thiz); 3549266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 3559266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber bool b = (bool)x; 3569266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber status_t err = blob->write(offset, &b, sizeof(b)); 3579266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 3589266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber if (err != OK) { 3599266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber signalExceptionForError(env, err); 3609266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber } 3619266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber} 3629266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 3639266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huberstatic void JHwBlob_native_putString( 3649266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber JNIEnv *env, jobject thiz, jlong offset, jstring stringObj) { 3659266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber if (stringObj == nullptr) { 3669266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber jniThrowException(env, "java/lang/NullPointerException", nullptr); 3679266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber return; 3689266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber } 3699266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 3709266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber const char *s = env->GetStringUTFChars(stringObj, nullptr); 3719266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 3729266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber if (s == nullptr) { 3739266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber return; 3749266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber } 3759266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 3769266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber size_t size = strlen(s) + 1; 3779266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber ScopedLocalRef<jobject> subBlobObj(env, JHwBlob::NewObject(env, size)); 3789266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber sp<JHwBlob> subBlob = JHwBlob::GetNativeContext(env, subBlobObj.get()); 3799266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber subBlob->write(0 /* offset */, s, size); 3809266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 3819266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber env->ReleaseStringUTFChars(stringObj, s); 3829266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber s = nullptr; 3839266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 3849266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber hidl_string tmp; 3857e6031116248237303ce361bea4db96f2ee4ff4cAndreas Huber tmp.setToExternal(static_cast<const char *>(subBlob->data()), size - 1); 3869266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 3879266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber sp<JHwBlob> blob = JHwBlob::GetNativeContext(env, thiz); 3889266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber blob->write(offset, &tmp, sizeof(tmp)); 3899266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber blob->putBlob(offset + hidl_string::kOffsetOfBuffer, subBlob); 3909266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber} 3919266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 3929266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huberstatic void JHwBlob_native_putBlob( 3939266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber JNIEnv *env, jobject thiz, jlong offset, jobject blobObj) { 3949266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber if (blobObj == nullptr) { 3959266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber jniThrowException(env, "java/lang/NullPointerException", nullptr); 3969266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber return; 3979266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber } 3989266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 3999266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber sp<JHwBlob> blob = JHwBlob::GetNativeContext(env, thiz); 4009266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber sp<JHwBlob> subBlob = JHwBlob::GetNativeContext(env, blobObj); 4019266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 4029266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber blob->putBlob(offset, subBlob); 4039266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber} 4049266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 4059266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huberstatic jlong JHwBlob_native_handle(JNIEnv *env, jobject thiz) { 4069266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber size_t handle; 4079266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber status_t err = JHwBlob::GetNativeContext(env, thiz)->getHandle(&handle); 4089266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 4099266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber if (err != OK) { 4109266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber signalExceptionForError(env, err); 4119266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber return 0; 4129266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber } 4139266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 4149266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber return handle; 4159266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber} 4169266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 4179266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huberstatic JNINativeMethod gMethods[] = { 4189266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber { "native_init", "()J", (void *)JHwBlob_native_init }, 4199266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber { "native_setup", "(I)V", (void *)JHwBlob_native_setup }, 4209266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 4219266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber { "getBool", "(J)Z", (void *)JHwBlob_native_getBool }, 4229266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber { "getInt8", "(J)B", (void *)JHwBlob_native_getInt8 }, 4239266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber { "getInt16", "(J)S", (void *)JHwBlob_native_getInt16 }, 4249266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber { "getInt32", "(J)I", (void *)JHwBlob_native_getInt32 }, 4259266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber { "getInt64", "(J)J", (void *)JHwBlob_native_getInt64 }, 4269266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber { "getFloat", "(J)F", (void *)JHwBlob_native_getFloat }, 4279266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber { "getDouble", "(J)D", (void *)JHwBlob_native_getDouble }, 4289266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber { "getString", "(J)Ljava/lang/String;", (void *)JHwBlob_native_getString }, 4299266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 4309266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber { "putBool", "(JZ)V", (void *)JHwBlob_native_putBool }, 4319266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber { "putInt8", "(JB)V", (void *)JHwBlob_native_putInt8 }, 4329266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber { "putInt16", "(JS)V", (void *)JHwBlob_native_putInt16 }, 4339266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber { "putInt32", "(JI)V", (void *)JHwBlob_native_putInt32 }, 4349266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber { "putInt64", "(JJ)V", (void *)JHwBlob_native_putInt64 }, 4359266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber { "putFloat", "(JF)V", (void *)JHwBlob_native_putFloat }, 4369266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber { "putDouble", "(JD)V", (void *)JHwBlob_native_putDouble }, 4379266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber { "putString", "(JLjava/lang/String;)V", (void *)JHwBlob_native_putString }, 4389266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 4399266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber { "putBlob", "(JL" PACKAGE_PATH "/HwBlob;)V", 4409266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber (void *)JHwBlob_native_putBlob }, 4419266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 4429266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber { "handle", "()J", (void *)JHwBlob_native_handle }, 4439266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber}; 4449266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 4459266f9928d5b3431982cd04f4d6946b70f40766aAndreas Hubernamespace android { 4469266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 4479266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huberint register_android_os_HwBlob(JNIEnv *env) { 4489266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber return RegisterMethodsOrDie(env, CLASS_PATH, gMethods, NELEM(gMethods)); 4499266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber} 4509266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 4519266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber} // namespace android 4529266f9928d5b3431982cd04f4d6946b70f40766aAndreas Huber 453