16714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis/* 26714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis * Copyright (C) 2010 The Android Open Source Project 36714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis * 46714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis * Licensed under the Apache License, Version 2.0 (the "License"); 56714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis * you may not use this file except in compliance with the License. 66714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis * You may obtain a copy of the License at 76714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis * 86714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis * http://www.apache.org/licenses/LICENSE-2.0 96714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis * 106714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis * Unless required by applicable law or agreed to in writing, software 116714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis * distributed under the License is distributed on an "AS IS" BASIS, 126714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 136714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis * See the License for the specific language governing permissions and 146714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis * limitations under the License. 156714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis */ 166714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis 176714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis#define LOG_TAG "SurfaceTexture" 186714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis 196714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis#include <stdio.h> 206714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis 214bbb8504a755fd273cd8e6be3d6e2fbc7ccbc2a4Craig Donner#include <EGL/egl.h> 224bbb8504a755fd273cd8e6be3d6e2fbc7ccbc2a4Craig Donner#include <EGL/eglext.h> 23e3eae73abb5e429d9747f9c36ab025219e68bb26Mathias Agopian#include <GLES2/gl2.h> 24e3eae73abb5e429d9747f9c36ab025219e68bb26Mathias Agopian#include <GLES2/gl2ext.h> 25e3eae73abb5e429d9747f9c36ab025219e68bb26Mathias Agopian 26d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFadden#include <gui/GLConsumer.h> 2752800617946c456e78ed010c82d0ec4358368164Mathias Agopian#include <gui/Surface.h> 286714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis 29ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe#include "core_jni_helpers.h" 306714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis 316714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis#include <utils/Log.h> 326714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis#include <utils/misc.h> 336714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis 346714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis#include "jni.h" 35376590d668e22a918439877b55faf075427b13f3Jamie Gennis#include "JNIHelp.h" 366714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis 376714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis// ---------------------------------------------------------------------------- 386714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis 39afe9a4c67c2e2988c76232796f017a992a6f2a28Craig Donner#define EGL_PROTECTED_CONTENT_EXT 0x32C0 404bbb8504a755fd273cd8e6be3d6e2fbc7ccbc2a4Craig Donner 416714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennisnamespace android { 426714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis 436714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennisstatic const char* const OutOfResourcesException = 44a86ab640f7bb0bf3cb4eaed80473ca8c5d131903Igor Murashkin "android/view/Surface$OutOfResourcesException"; 452b4bfa5efec7df408b4db127961cfc9aca9e57cfJamie Gennisstatic const char* const IllegalStateException = "java/lang/IllegalStateException"; 46050316184b01c0d1a01c46afae7429b89a27c31btedboconst char* const kSurfaceTextureClassPathName = "android/graphics/SurfaceTexture"; 476714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis 48376590d668e22a918439877b55faf075427b13f3Jamie Gennisstruct fields_t { 49376590d668e22a918439877b55faf075427b13f3Jamie Gennis jfieldID surfaceTexture; 500dc146be5a6cd0c33910d5b18885df46873a93cbDan Stoza jfieldID producer; 51c99db2bc460cc795947d99076da380e22a21e493Igor Murashkin jfieldID frameAvailableListener; 52376590d668e22a918439877b55faf075427b13f3Jamie Gennis jmethodID postEvent; 536714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis}; 54376590d668e22a918439877b55faf075427b13f3Jamie Gennisstatic fields_t fields; 556714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis 56ef9db7d81b0ce1093944b9e3d5efb6ab756f5cbcEino-Ville Talvala// Get an ID that's unique within this process. 57ef9db7d81b0ce1093944b9e3d5efb6ab756f5cbcEino-Ville Talvalastatic int32_t createProcessUniqueId() { 58ef9db7d81b0ce1093944b9e3d5efb6ab756f5cbcEino-Ville Talvala static volatile int32_t globalCounter = 0; 59ef9db7d81b0ce1093944b9e3d5efb6ab756f5cbcEino-Ville Talvala return android_atomic_inc(&globalCounter); 60ef9db7d81b0ce1093944b9e3d5efb6ab756f5cbcEino-Ville Talvala} 61ef9db7d81b0ce1093944b9e3d5efb6ab756f5cbcEino-Ville Talvala 624bbb8504a755fd273cd8e6be3d6e2fbc7ccbc2a4Craig Donner// Check whether the current EGL context is protected. 634bbb8504a755fd273cd8e6be3d6e2fbc7ccbc2a4Craig Donnerstatic bool isProtectedContext() { 644bbb8504a755fd273cd8e6be3d6e2fbc7ccbc2a4Craig Donner EGLDisplay dpy = eglGetCurrentDisplay(); 654bbb8504a755fd273cd8e6be3d6e2fbc7ccbc2a4Craig Donner EGLContext ctx = eglGetCurrentContext(); 664bbb8504a755fd273cd8e6be3d6e2fbc7ccbc2a4Craig Donner 67afe9a4c67c2e2988c76232796f017a992a6f2a28Craig Donner if (dpy == EGL_NO_DISPLAY || ctx == EGL_NO_CONTEXT) { 684bbb8504a755fd273cd8e6be3d6e2fbc7ccbc2a4Craig Donner return false; 694bbb8504a755fd273cd8e6be3d6e2fbc7ccbc2a4Craig Donner } 704bbb8504a755fd273cd8e6be3d6e2fbc7ccbc2a4Craig Donner 714bbb8504a755fd273cd8e6be3d6e2fbc7ccbc2a4Craig Donner EGLint isProtected = EGL_FALSE; 72afe9a4c67c2e2988c76232796f017a992a6f2a28Craig Donner eglQueryContext(dpy, ctx, EGL_PROTECTED_CONTENT_EXT, &isProtected); 734bbb8504a755fd273cd8e6be3d6e2fbc7ccbc2a4Craig Donner 744bbb8504a755fd273cd8e6be3d6e2fbc7ccbc2a4Craig Donner return isProtected; 754bbb8504a755fd273cd8e6be3d6e2fbc7ccbc2a4Craig Donner} 764bbb8504a755fd273cd8e6be3d6e2fbc7ccbc2a4Craig Donner 776714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis// ---------------------------------------------------------------------------- 786714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis 79376590d668e22a918439877b55faf075427b13f3Jamie Gennisstatic void SurfaceTexture_setSurfaceTexture(JNIEnv* env, jobject thiz, 80d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFadden const sp<GLConsumer>& surfaceTexture) 816714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis{ 82d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFadden GLConsumer* const p = 8372aa313ff4c91e7b2aae3d37067f9201b2b0fdbeAshok Bhat (GLConsumer*)env->GetLongField(thiz, fields.surfaceTexture); 846714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis if (surfaceTexture.get()) { 85b1d90c8f60f71422196c337f1d078b68867f5710Mathias Agopian surfaceTexture->incStrong((void*)SurfaceTexture_setSurfaceTexture); 866714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis } 876714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis if (p) { 88b1d90c8f60f71422196c337f1d078b68867f5710Mathias Agopian p->decStrong((void*)SurfaceTexture_setSurfaceTexture); 896714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis } 9072aa313ff4c91e7b2aae3d37067f9201b2b0fdbeAshok Bhat env->SetLongField(thiz, fields.surfaceTexture, (jlong)surfaceTexture.get()); 916714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis} 926714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis 930dc146be5a6cd0c33910d5b18885df46873a93cbDan Stozastatic void SurfaceTexture_setProducer(JNIEnv* env, jobject thiz, 940dc146be5a6cd0c33910d5b18885df46873a93cbDan Stoza const sp<IGraphicBufferProducer>& producer) 9552a9a10b6b8c7b7a9f97777541841b94d4fd9754Mathias Agopian{ 960dc146be5a6cd0c33910d5b18885df46873a93cbDan Stoza IGraphicBufferProducer* const p = 970dc146be5a6cd0c33910d5b18885df46873a93cbDan Stoza (IGraphicBufferProducer*)env->GetLongField(thiz, fields.producer); 980dc146be5a6cd0c33910d5b18885df46873a93cbDan Stoza if (producer.get()) { 990dc146be5a6cd0c33910d5b18885df46873a93cbDan Stoza producer->incStrong((void*)SurfaceTexture_setProducer); 10052a9a10b6b8c7b7a9f97777541841b94d4fd9754Mathias Agopian } 10152a9a10b6b8c7b7a9f97777541841b94d4fd9754Mathias Agopian if (p) { 1020dc146be5a6cd0c33910d5b18885df46873a93cbDan Stoza p->decStrong((void*)SurfaceTexture_setProducer); 10352a9a10b6b8c7b7a9f97777541841b94d4fd9754Mathias Agopian } 1040dc146be5a6cd0c33910d5b18885df46873a93cbDan Stoza env->SetLongField(thiz, fields.producer, (jlong)producer.get()); 10552a9a10b6b8c7b7a9f97777541841b94d4fd9754Mathias Agopian} 10652a9a10b6b8c7b7a9f97777541841b94d4fd9754Mathias Agopian 107c99db2bc460cc795947d99076da380e22a21e493Igor Murashkinstatic void SurfaceTexture_setFrameAvailableListener(JNIEnv* env, 108d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFadden jobject thiz, sp<GLConsumer::FrameAvailableListener> listener) 1096714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis{ 110d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFadden GLConsumer::FrameAvailableListener* const p = 111d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFadden (GLConsumer::FrameAvailableListener*) 11272aa313ff4c91e7b2aae3d37067f9201b2b0fdbeAshok Bhat env->GetLongField(thiz, fields.frameAvailableListener); 113c99db2bc460cc795947d99076da380e22a21e493Igor Murashkin if (listener.get()) { 114b1d90c8f60f71422196c337f1d078b68867f5710Mathias Agopian listener->incStrong((void*)SurfaceTexture_setSurfaceTexture); 115c99db2bc460cc795947d99076da380e22a21e493Igor Murashkin } 116c99db2bc460cc795947d99076da380e22a21e493Igor Murashkin if (p) { 117b1d90c8f60f71422196c337f1d078b68867f5710Mathias Agopian p->decStrong((void*)SurfaceTexture_setSurfaceTexture); 118c99db2bc460cc795947d99076da380e22a21e493Igor Murashkin } 11972aa313ff4c91e7b2aae3d37067f9201b2b0fdbeAshok Bhat env->SetLongField(thiz, fields.frameAvailableListener, (jlong)listener.get()); 120c99db2bc460cc795947d99076da380e22a21e493Igor Murashkin} 121c99db2bc460cc795947d99076da380e22a21e493Igor Murashkin 12252a9a10b6b8c7b7a9f97777541841b94d4fd9754Mathias Agopiansp<GLConsumer> SurfaceTexture_getSurfaceTexture(JNIEnv* env, jobject thiz) { 12372aa313ff4c91e7b2aae3d37067f9201b2b0fdbeAshok Bhat return (GLConsumer*)env->GetLongField(thiz, fields.surfaceTexture); 1246714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis} 1256714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis 12652a9a10b6b8c7b7a9f97777541841b94d4fd9754Mathias Agopiansp<IGraphicBufferProducer> SurfaceTexture_getProducer(JNIEnv* env, jobject thiz) { 1270dc146be5a6cd0c33910d5b18885df46873a93cbDan Stoza return (IGraphicBufferProducer*)env->GetLongField(thiz, fields.producer); 12852a9a10b6b8c7b7a9f97777541841b94d4fd9754Mathias Agopian} 12952a9a10b6b8c7b7a9f97777541841b94d4fd9754Mathias Agopian 13052a9a10b6b8c7b7a9f97777541841b94d4fd9754Mathias Agopiansp<ANativeWindow> android_SurfaceTexture_getNativeWindow(JNIEnv* env, jobject thiz) { 131d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFadden sp<GLConsumer> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz)); 13252a9a10b6b8c7b7a9f97777541841b94d4fd9754Mathias Agopian sp<IGraphicBufferProducer> producer(SurfaceTexture_getProducer(env, thiz)); 13352a9a10b6b8c7b7a9f97777541841b94d4fd9754Mathias Agopian sp<Surface> surfaceTextureClient(surfaceTexture != NULL ? new Surface(producer) : NULL); 134846db33313aa0899fa7928256c6734964bd92520Glenn Kasten return surfaceTextureClient; 135846db33313aa0899fa7928256c6734964bd92520Glenn Kasten} 136846db33313aa0899fa7928256c6734964bd92520Glenn Kasten 13752a9a10b6b8c7b7a9f97777541841b94d4fd9754Mathias Agopianbool android_SurfaceTexture_isInstanceOf(JNIEnv* env, jobject thiz) { 138050316184b01c0d1a01c46afae7429b89a27c31btedbo jclass surfaceTextureClass = env->FindClass(kSurfaceTextureClassPathName); 139050316184b01c0d1a01c46afae7429b89a27c31btedbo return env->IsInstanceOf(thiz, surfaceTextureClass); 140050316184b01c0d1a01c46afae7429b89a27c31btedbo} 141050316184b01c0d1a01c46afae7429b89a27c31btedbo 1426714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis// ---------------------------------------------------------------------------- 1436714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis 144d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFaddenclass JNISurfaceTextureContext : public GLConsumer::FrameAvailableListener 1456714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis{ 146376590d668e22a918439877b55faf075427b13f3Jamie Gennispublic: 147376590d668e22a918439877b55faf075427b13f3Jamie Gennis JNISurfaceTextureContext(JNIEnv* env, jobject weakThiz, jclass clazz); 148376590d668e22a918439877b55faf075427b13f3Jamie Gennis virtual ~JNISurfaceTextureContext(); 1492c34b5e8136eac0332dac294cb06a6a98eac1c14Dan Stoza virtual void onFrameAvailable(const BufferItem& item); 150376590d668e22a918439877b55faf075427b13f3Jamie Gennis 151376590d668e22a918439877b55faf075427b13f3Jamie Gennisprivate: 1520a8fd9b610b2de92930c92d71ac184dc9e2bcb4dJamie Gennis static JNIEnv* getJNIEnv(bool* needsDetach); 1530a8fd9b610b2de92930c92d71ac184dc9e2bcb4dJamie Gennis static void detachJNI(); 15484293fb9625a3ab7d7d302436bea05441b8d7316Jamie Gennis 155376590d668e22a918439877b55faf075427b13f3Jamie Gennis jobject mWeakThiz; 156376590d668e22a918439877b55faf075427b13f3Jamie Gennis jclass mClazz; 157376590d668e22a918439877b55faf075427b13f3Jamie Gennis}; 158376590d668e22a918439877b55faf075427b13f3Jamie Gennis 159376590d668e22a918439877b55faf075427b13f3Jamie GennisJNISurfaceTextureContext::JNISurfaceTextureContext(JNIEnv* env, 160376590d668e22a918439877b55faf075427b13f3Jamie Gennis jobject weakThiz, jclass clazz) : 161376590d668e22a918439877b55faf075427b13f3Jamie Gennis mWeakThiz(env->NewGlobalRef(weakThiz)), 162376590d668e22a918439877b55faf075427b13f3Jamie Gennis mClazz((jclass)env->NewGlobalRef(clazz)) 163376590d668e22a918439877b55faf075427b13f3Jamie Gennis{} 164376590d668e22a918439877b55faf075427b13f3Jamie Gennis 1650a8fd9b610b2de92930c92d71ac184dc9e2bcb4dJamie GennisJNIEnv* JNISurfaceTextureContext::getJNIEnv(bool* needsDetach) { 1660a8fd9b610b2de92930c92d71ac184dc9e2bcb4dJamie Gennis *needsDetach = false; 1670a8fd9b610b2de92930c92d71ac184dc9e2bcb4dJamie Gennis JNIEnv* env = AndroidRuntime::getJNIEnv(); 1680a8fd9b610b2de92930c92d71ac184dc9e2bcb4dJamie Gennis if (env == NULL) { 1699b311c900dcc3666febf52c1bed8eae7ce1f2815Andy McFadden JavaVMAttachArgs args = { 1709b311c900dcc3666febf52c1bed8eae7ce1f2815Andy McFadden JNI_VERSION_1_4, "JNISurfaceTextureContext", NULL }; 1710a8fd9b610b2de92930c92d71ac184dc9e2bcb4dJamie Gennis JavaVM* vm = AndroidRuntime::getJavaVM(); 1720a8fd9b610b2de92930c92d71ac184dc9e2bcb4dJamie Gennis int result = vm->AttachCurrentThread(&env, (void*) &args); 1730a8fd9b610b2de92930c92d71ac184dc9e2bcb4dJamie Gennis if (result != JNI_OK) { 1743762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("thread attach failed: %#x", result); 1750a8fd9b610b2de92930c92d71ac184dc9e2bcb4dJamie Gennis return NULL; 1760a8fd9b610b2de92930c92d71ac184dc9e2bcb4dJamie Gennis } 1770a8fd9b610b2de92930c92d71ac184dc9e2bcb4dJamie Gennis *needsDetach = true; 1780a8fd9b610b2de92930c92d71ac184dc9e2bcb4dJamie Gennis } 1790a8fd9b610b2de92930c92d71ac184dc9e2bcb4dJamie Gennis return env; 1800a8fd9b610b2de92930c92d71ac184dc9e2bcb4dJamie Gennis} 1810a8fd9b610b2de92930c92d71ac184dc9e2bcb4dJamie Gennis 1820a8fd9b610b2de92930c92d71ac184dc9e2bcb4dJamie Gennisvoid JNISurfaceTextureContext::detachJNI() { 18384293fb9625a3ab7d7d302436bea05441b8d7316Jamie Gennis JavaVM* vm = AndroidRuntime::getJavaVM(); 1840a8fd9b610b2de92930c92d71ac184dc9e2bcb4dJamie Gennis int result = vm->DetachCurrentThread(); 18584293fb9625a3ab7d7d302436bea05441b8d7316Jamie Gennis if (result != JNI_OK) { 1863762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("thread detach failed: %#x", result); 18784293fb9625a3ab7d7d302436bea05441b8d7316Jamie Gennis } 18884293fb9625a3ab7d7d302436bea05441b8d7316Jamie Gennis} 18984293fb9625a3ab7d7d302436bea05441b8d7316Jamie Gennis 190376590d668e22a918439877b55faf075427b13f3Jamie GennisJNISurfaceTextureContext::~JNISurfaceTextureContext() 191376590d668e22a918439877b55faf075427b13f3Jamie Gennis{ 1920a8fd9b610b2de92930c92d71ac184dc9e2bcb4dJamie Gennis bool needsDetach = false; 1930a8fd9b610b2de92930c92d71ac184dc9e2bcb4dJamie Gennis JNIEnv* env = getJNIEnv(&needsDetach); 19484293fb9625a3ab7d7d302436bea05441b8d7316Jamie Gennis if (env != NULL) { 19584293fb9625a3ab7d7d302436bea05441b8d7316Jamie Gennis env->DeleteGlobalRef(mWeakThiz); 19684293fb9625a3ab7d7d302436bea05441b8d7316Jamie Gennis env->DeleteGlobalRef(mClazz); 19784293fb9625a3ab7d7d302436bea05441b8d7316Jamie Gennis } else { 1988564c8da817a845353d213acd8636b76f567b234Steve Block ALOGW("leaking JNI object references"); 19984293fb9625a3ab7d7d302436bea05441b8d7316Jamie Gennis } 2000a8fd9b610b2de92930c92d71ac184dc9e2bcb4dJamie Gennis if (needsDetach) { 2010a8fd9b610b2de92930c92d71ac184dc9e2bcb4dJamie Gennis detachJNI(); 2020a8fd9b610b2de92930c92d71ac184dc9e2bcb4dJamie Gennis } 203376590d668e22a918439877b55faf075427b13f3Jamie Gennis} 204376590d668e22a918439877b55faf075427b13f3Jamie Gennis 2052c34b5e8136eac0332dac294cb06a6a98eac1c14Dan Stozavoid JNISurfaceTextureContext::onFrameAvailable(const BufferItem& /* item */) 206376590d668e22a918439877b55faf075427b13f3Jamie Gennis{ 2070a8fd9b610b2de92930c92d71ac184dc9e2bcb4dJamie Gennis bool needsDetach = false; 2080a8fd9b610b2de92930c92d71ac184dc9e2bcb4dJamie Gennis JNIEnv* env = getJNIEnv(&needsDetach); 20984293fb9625a3ab7d7d302436bea05441b8d7316Jamie Gennis if (env != NULL) { 21084293fb9625a3ab7d7d302436bea05441b8d7316Jamie Gennis env->CallStaticVoidMethod(mClazz, fields.postEvent, mWeakThiz); 21184293fb9625a3ab7d7d302436bea05441b8d7316Jamie Gennis } else { 2128564c8da817a845353d213acd8636b76f567b234Steve Block ALOGW("onFrameAvailable event will not posted"); 21384293fb9625a3ab7d7d302436bea05441b8d7316Jamie Gennis } 2140a8fd9b610b2de92930c92d71ac184dc9e2bcb4dJamie Gennis if (needsDetach) { 2150a8fd9b610b2de92930c92d71ac184dc9e2bcb4dJamie Gennis detachJNI(); 2160a8fd9b610b2de92930c92d71ac184dc9e2bcb4dJamie Gennis } 217376590d668e22a918439877b55faf075427b13f3Jamie Gennis} 218376590d668e22a918439877b55faf075427b13f3Jamie Gennis 219376590d668e22a918439877b55faf075427b13f3Jamie Gennis// ---------------------------------------------------------------------------- 220376590d668e22a918439877b55faf075427b13f3Jamie Gennis 22152a9a10b6b8c7b7a9f97777541841b94d4fd9754Mathias Agopian 22252a9a10b6b8c7b7a9f97777541841b94d4fd9754Mathias Agopian#define ANDROID_GRAPHICS_SURFACETEXTURE_JNI_ID "mSurfaceTexture" 2230dc146be5a6cd0c33910d5b18885df46873a93cbDan Stoza#define ANDROID_GRAPHICS_PRODUCER_JNI_ID "mProducer" 22452a9a10b6b8c7b7a9f97777541841b94d4fd9754Mathias Agopian#define ANDROID_GRAPHICS_FRAMEAVAILABLELISTENER_JNI_ID \ 22552a9a10b6b8c7b7a9f97777541841b94d4fd9754Mathias Agopian "mFrameAvailableListener" 22652a9a10b6b8c7b7a9f97777541841b94d4fd9754Mathias Agopian 227376590d668e22a918439877b55faf075427b13f3Jamie Gennisstatic void SurfaceTexture_classInit(JNIEnv* env, jclass clazz) 228376590d668e22a918439877b55faf075427b13f3Jamie Gennis{ 229376590d668e22a918439877b55faf075427b13f3Jamie Gennis fields.surfaceTexture = env->GetFieldID(clazz, 23072aa313ff4c91e7b2aae3d37067f9201b2b0fdbeAshok Bhat ANDROID_GRAPHICS_SURFACETEXTURE_JNI_ID, "J"); 231376590d668e22a918439877b55faf075427b13f3Jamie Gennis if (fields.surfaceTexture == NULL) { 2323762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("can't find android/graphics/SurfaceTexture.%s", 233376590d668e22a918439877b55faf075427b13f3Jamie Gennis ANDROID_GRAPHICS_SURFACETEXTURE_JNI_ID); 234376590d668e22a918439877b55faf075427b13f3Jamie Gennis } 2350dc146be5a6cd0c33910d5b18885df46873a93cbDan Stoza fields.producer = env->GetFieldID(clazz, 2360dc146be5a6cd0c33910d5b18885df46873a93cbDan Stoza ANDROID_GRAPHICS_PRODUCER_JNI_ID, "J"); 2370dc146be5a6cd0c33910d5b18885df46873a93cbDan Stoza if (fields.producer == NULL) { 23852a9a10b6b8c7b7a9f97777541841b94d4fd9754Mathias Agopian ALOGE("can't find android/graphics/SurfaceTexture.%s", 2390dc146be5a6cd0c33910d5b18885df46873a93cbDan Stoza ANDROID_GRAPHICS_PRODUCER_JNI_ID); 24052a9a10b6b8c7b7a9f97777541841b94d4fd9754Mathias Agopian } 241c99db2bc460cc795947d99076da380e22a21e493Igor Murashkin fields.frameAvailableListener = env->GetFieldID(clazz, 24272aa313ff4c91e7b2aae3d37067f9201b2b0fdbeAshok Bhat ANDROID_GRAPHICS_FRAMEAVAILABLELISTENER_JNI_ID, "J"); 243c99db2bc460cc795947d99076da380e22a21e493Igor Murashkin if (fields.frameAvailableListener == NULL) { 244c99db2bc460cc795947d99076da380e22a21e493Igor Murashkin ALOGE("can't find android/graphics/SurfaceTexture.%s", 245c99db2bc460cc795947d99076da380e22a21e493Igor Murashkin ANDROID_GRAPHICS_FRAMEAVAILABLELISTENER_JNI_ID); 246c99db2bc460cc795947d99076da380e22a21e493Igor Murashkin } 247376590d668e22a918439877b55faf075427b13f3Jamie Gennis 248376590d668e22a918439877b55faf075427b13f3Jamie Gennis fields.postEvent = env->GetStaticMethodID(clazz, "postEventFromNative", 249c7282e57cd01f1576baac04356bf99bee34e4c18Jeff Brown "(Ljava/lang/ref/WeakReference;)V"); 250376590d668e22a918439877b55faf075427b13f3Jamie Gennis if (fields.postEvent == NULL) { 2513762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("can't find android/graphics/SurfaceTexture.postEventFromNative"); 252376590d668e22a918439877b55faf075427b13f3Jamie Gennis } 253376590d668e22a918439877b55faf075427b13f3Jamie Gennis} 2546714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis 255493f2e11909e2d5839ca81ddc66d48d538192478Dan Stozastatic void SurfaceTexture_init(JNIEnv* env, jobject thiz, jboolean isDetached, 256e591b49de038a9942cbcc77540c03e85c96e3dcbMathias Agopian jint texName, jboolean singleBufferMode, jobject weakThiz) 257376590d668e22a918439877b55faf075427b13f3Jamie Gennis{ 2580dc146be5a6cd0c33910d5b18885df46873a93cbDan Stoza sp<IGraphicBufferProducer> producer; 2590dc146be5a6cd0c33910d5b18885df46873a93cbDan Stoza sp<IGraphicBufferConsumer> consumer; 2600dc146be5a6cd0c33910d5b18885df46873a93cbDan Stoza BufferQueue::createBufferQueue(&producer, &consumer); 261e591b49de038a9942cbcc77540c03e85c96e3dcbMathias Agopian 262e591b49de038a9942cbcc77540c03e85c96e3dcbMathias Agopian if (singleBufferMode) { 263e442b63c837c8852546f9fa7ba28985e8eea7290Pablo Ceballos consumer->setMaxBufferCount(1); 264e591b49de038a9942cbcc77540c03e85c96e3dcbMathias Agopian } 265e591b49de038a9942cbcc77540c03e85c96e3dcbMathias Agopian 266493f2e11909e2d5839ca81ddc66d48d538192478Dan Stoza sp<GLConsumer> surfaceTexture; 267493f2e11909e2d5839ca81ddc66d48d538192478Dan Stoza if (isDetached) { 268493f2e11909e2d5839ca81ddc66d48d538192478Dan Stoza surfaceTexture = new GLConsumer(consumer, GL_TEXTURE_EXTERNAL_OES, 269e442b63c837c8852546f9fa7ba28985e8eea7290Pablo Ceballos true, !singleBufferMode); 270493f2e11909e2d5839ca81ddc66d48d538192478Dan Stoza } else { 271493f2e11909e2d5839ca81ddc66d48d538192478Dan Stoza surfaceTexture = new GLConsumer(consumer, texName, 272e442b63c837c8852546f9fa7ba28985e8eea7290Pablo Ceballos GL_TEXTURE_EXTERNAL_OES, true, !singleBufferMode); 273493f2e11909e2d5839ca81ddc66d48d538192478Dan Stoza } 274493f2e11909e2d5839ca81ddc66d48d538192478Dan Stoza 2756714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis if (surfaceTexture == 0) { 276376590d668e22a918439877b55faf075427b13f3Jamie Gennis jniThrowException(env, OutOfResourcesException, 277376590d668e22a918439877b55faf075427b13f3Jamie Gennis "Unable to create native SurfaceTexture"); 278376590d668e22a918439877b55faf075427b13f3Jamie Gennis return; 279376590d668e22a918439877b55faf075427b13f3Jamie Gennis } 280ef9db7d81b0ce1093944b9e3d5efb6ab756f5cbcEino-Ville Talvala surfaceTexture->setName(String8::format("SurfaceTexture-%d-%d-%d", 281ef9db7d81b0ce1093944b9e3d5efb6ab756f5cbcEino-Ville Talvala (isDetached ? 0 : texName), 282ef9db7d81b0ce1093944b9e3d5efb6ab756f5cbcEino-Ville Talvala getpid(), 283ef9db7d81b0ce1093944b9e3d5efb6ab756f5cbcEino-Ville Talvala createProcessUniqueId())); 284ef9db7d81b0ce1093944b9e3d5efb6ab756f5cbcEino-Ville Talvala 2854bbb8504a755fd273cd8e6be3d6e2fbc7ccbc2a4Craig Donner // If the current context is protected, inform the producer. 2864bbb8504a755fd273cd8e6be3d6e2fbc7ccbc2a4Craig Donner if (isProtectedContext()) { 2874bbb8504a755fd273cd8e6be3d6e2fbc7ccbc2a4Craig Donner consumer->setConsumerUsageBits(GRALLOC_USAGE_PROTECTED); 2884bbb8504a755fd273cd8e6be3d6e2fbc7ccbc2a4Craig Donner } 2894bbb8504a755fd273cd8e6be3d6e2fbc7ccbc2a4Craig Donner 290376590d668e22a918439877b55faf075427b13f3Jamie Gennis SurfaceTexture_setSurfaceTexture(env, thiz, surfaceTexture); 2910dc146be5a6cd0c33910d5b18885df46873a93cbDan Stoza SurfaceTexture_setProducer(env, thiz, producer); 292376590d668e22a918439877b55faf075427b13f3Jamie Gennis 293376590d668e22a918439877b55faf075427b13f3Jamie Gennis jclass clazz = env->GetObjectClass(thiz); 294376590d668e22a918439877b55faf075427b13f3Jamie Gennis if (clazz == NULL) { 295376590d668e22a918439877b55faf075427b13f3Jamie Gennis jniThrowRuntimeException(env, 296376590d668e22a918439877b55faf075427b13f3Jamie Gennis "Can't find android/graphics/SurfaceTexture"); 2976714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis return; 2986714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis } 299376590d668e22a918439877b55faf075427b13f3Jamie Gennis 300376590d668e22a918439877b55faf075427b13f3Jamie Gennis sp<JNISurfaceTextureContext> ctx(new JNISurfaceTextureContext(env, weakThiz, 301376590d668e22a918439877b55faf075427b13f3Jamie Gennis clazz)); 302376590d668e22a918439877b55faf075427b13f3Jamie Gennis surfaceTexture->setFrameAvailableListener(ctx); 303c99db2bc460cc795947d99076da380e22a21e493Igor Murashkin SurfaceTexture_setFrameAvailableListener(env, thiz, ctx); 304376590d668e22a918439877b55faf075427b13f3Jamie Gennis} 305376590d668e22a918439877b55faf075427b13f3Jamie Gennis 306376590d668e22a918439877b55faf075427b13f3Jamie Gennisstatic void SurfaceTexture_finalize(JNIEnv* env, jobject thiz) 307376590d668e22a918439877b55faf075427b13f3Jamie Gennis{ 308d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFadden sp<GLConsumer> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz)); 309376590d668e22a918439877b55faf075427b13f3Jamie Gennis surfaceTexture->setFrameAvailableListener(0); 310c99db2bc460cc795947d99076da380e22a21e493Igor Murashkin SurfaceTexture_setFrameAvailableListener(env, thiz, 0); 311376590d668e22a918439877b55faf075427b13f3Jamie Gennis SurfaceTexture_setSurfaceTexture(env, thiz, 0); 3120dc146be5a6cd0c33910d5b18885df46873a93cbDan Stoza SurfaceTexture_setProducer(env, thiz, 0); 3136714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis} 3146714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis 315050316184b01c0d1a01c46afae7429b89a27c31btedbostatic void SurfaceTexture_setDefaultBufferSize( 31652a9a10b6b8c7b7a9f97777541841b94d4fd9754Mathias Agopian JNIEnv* env, jobject thiz, jint width, jint height) { 317d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFadden sp<GLConsumer> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz)); 318050316184b01c0d1a01c46afae7429b89a27c31btedbo surfaceTexture->setDefaultBufferSize(width, height); 319050316184b01c0d1a01c46afae7429b89a27c31btedbo} 320050316184b01c0d1a01c46afae7429b89a27c31btedbo 3212b4bfa5efec7df408b4db127961cfc9aca9e57cfJamie Gennisstatic void SurfaceTexture_updateTexImage(JNIEnv* env, jobject thiz) 3226714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis{ 323d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFadden sp<GLConsumer> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz)); 3242b4bfa5efec7df408b4db127961cfc9aca9e57cfJamie Gennis status_t err = surfaceTexture->updateTexImage(); 3252b4bfa5efec7df408b4db127961cfc9aca9e57cfJamie Gennis if (err == INVALID_OPERATION) { 3262b4bfa5efec7df408b4db127961cfc9aca9e57cfJamie Gennis jniThrowException(env, IllegalStateException, "Unable to update texture contents (see " 3272b4bfa5efec7df408b4db127961cfc9aca9e57cfJamie Gennis "logcat for details)"); 328721bfaa63d14f0ac858d32431ab2eff582143b0fJamie Gennis } else if (err < 0) { 3292b4bfa5efec7df408b4db127961cfc9aca9e57cfJamie Gennis jniThrowRuntimeException(env, "Error during updateTexImage (see logcat for details)"); 3302b4bfa5efec7df408b4db127961cfc9aca9e57cfJamie Gennis } 3316714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis} 3326714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis 333e591b49de038a9942cbcc77540c03e85c96e3dcbMathias Agopianstatic void SurfaceTexture_releaseTexImage(JNIEnv* env, jobject thiz) 334e591b49de038a9942cbcc77540c03e85c96e3dcbMathias Agopian{ 335e591b49de038a9942cbcc77540c03e85c96e3dcbMathias Agopian sp<GLConsumer> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz)); 336e591b49de038a9942cbcc77540c03e85c96e3dcbMathias Agopian status_t err = surfaceTexture->releaseTexImage(); 337e591b49de038a9942cbcc77540c03e85c96e3dcbMathias Agopian if (err == INVALID_OPERATION) { 338e591b49de038a9942cbcc77540c03e85c96e3dcbMathias Agopian jniThrowException(env, IllegalStateException, "Unable to release texture contents (see " 339e591b49de038a9942cbcc77540c03e85c96e3dcbMathias Agopian "logcat for details)"); 340e591b49de038a9942cbcc77540c03e85c96e3dcbMathias Agopian } else if (err < 0) { 341e591b49de038a9942cbcc77540c03e85c96e3dcbMathias Agopian jniThrowRuntimeException(env, "Error during updateTexImage (see logcat for details)"); 342e591b49de038a9942cbcc77540c03e85c96e3dcbMathias Agopian } 343e591b49de038a9942cbcc77540c03e85c96e3dcbMathias Agopian} 344e591b49de038a9942cbcc77540c03e85c96e3dcbMathias Agopian 345c6d993077761fc737bbb0f4db44b961a4e7b6bbbJamie Gennisstatic jint SurfaceTexture_detachFromGLContext(JNIEnv* env, jobject thiz) 346c6d993077761fc737bbb0f4db44b961a4e7b6bbbJamie Gennis{ 347d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFadden sp<GLConsumer> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz)); 348c6d993077761fc737bbb0f4db44b961a4e7b6bbbJamie Gennis return surfaceTexture->detachFromContext(); 349c6d993077761fc737bbb0f4db44b961a4e7b6bbbJamie Gennis} 350c6d993077761fc737bbb0f4db44b961a4e7b6bbbJamie Gennis 351c6d993077761fc737bbb0f4db44b961a4e7b6bbbJamie Gennisstatic jint SurfaceTexture_attachToGLContext(JNIEnv* env, jobject thiz, jint tex) 352c6d993077761fc737bbb0f4db44b961a4e7b6bbbJamie Gennis{ 353d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFadden sp<GLConsumer> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz)); 354c6d993077761fc737bbb0f4db44b961a4e7b6bbbJamie Gennis return surfaceTexture->attachToContext((GLuint)tex); 355c6d993077761fc737bbb0f4db44b961a4e7b6bbbJamie Gennis} 356c6d993077761fc737bbb0f4db44b961a4e7b6bbbJamie Gennis 357376590d668e22a918439877b55faf075427b13f3Jamie Gennisstatic void SurfaceTexture_getTransformMatrix(JNIEnv* env, jobject thiz, 358b0ba48c95ea8768a051100c5adb4c906caa1e080Jamie Gennis jfloatArray jmtx) 359b0ba48c95ea8768a051100c5adb4c906caa1e080Jamie Gennis{ 360d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFadden sp<GLConsumer> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz)); 361b0ba48c95ea8768a051100c5adb4c906caa1e080Jamie Gennis float* mtx = env->GetFloatArrayElements(jmtx, NULL); 362b0ba48c95ea8768a051100c5adb4c906caa1e080Jamie Gennis surfaceTexture->getTransformMatrix(mtx); 363b0ba48c95ea8768a051100c5adb4c906caa1e080Jamie Gennis env->ReleaseFloatArrayElements(jmtx, mtx, 0); 364b0ba48c95ea8768a051100c5adb4c906caa1e080Jamie Gennis} 365b0ba48c95ea8768a051100c5adb4c906caa1e080Jamie Gennis 366c5f94d8a4779050125145396ca83fbc862c7ed6bEino-Ville Talvalastatic jlong SurfaceTexture_getTimestamp(JNIEnv* env, jobject thiz) 367c5f94d8a4779050125145396ca83fbc862c7ed6bEino-Ville Talvala{ 368d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFadden sp<GLConsumer> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz)); 369c5f94d8a4779050125145396ca83fbc862c7ed6bEino-Ville Talvala return surfaceTexture->getTimestamp(); 370c5f94d8a4779050125145396ca83fbc862c7ed6bEino-Ville Talvala} 371c5f94d8a4779050125145396ca83fbc862c7ed6bEino-Ville Talvala 372ec46b4e1ca89d7c3a9ad70ded58da08b5e19f08fMathias Agopianstatic void SurfaceTexture_release(JNIEnv* env, jobject thiz) 373ec46b4e1ca89d7c3a9ad70ded58da08b5e19f08fMathias Agopian{ 374d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFadden sp<GLConsumer> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz)); 375ec46b4e1ca89d7c3a9ad70ded58da08b5e19f08fMathias Agopian surfaceTexture->abandon(); 376ec46b4e1ca89d7c3a9ad70ded58da08b5e19f08fMathias Agopian} 377ec46b4e1ca89d7c3a9ad70ded58da08b5e19f08fMathias Agopian 3786d8371e73ff6452be5a23089e7edeb8d6d96f065John Reckstatic jboolean SurfaceTexture_isReleased(JNIEnv* env, jobject thiz) 3796d8371e73ff6452be5a23089e7edeb8d6d96f065John Reck{ 3806d8371e73ff6452be5a23089e7edeb8d6d96f065John Reck sp<GLConsumer> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz)); 3816d8371e73ff6452be5a23089e7edeb8d6d96f065John Reck return surfaceTexture->isAbandoned(); 3826d8371e73ff6452be5a23089e7edeb8d6d96f065John Reck} 3836d8371e73ff6452be5a23089e7edeb8d6d96f065John Reck 3846714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis// ---------------------------------------------------------------------------- 3856714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis 38676f6a86de25e1bf74717e047e55fd44b089673f3Daniel Micaystatic const JNINativeMethod gSurfaceTextureMethods[] = { 387c6d993077761fc737bbb0f4db44b961a4e7b6bbbJamie Gennis {"nativeClassInit", "()V", (void*)SurfaceTexture_classInit }, 388493f2e11909e2d5839ca81ddc66d48d538192478Dan Stoza {"nativeInit", "(ZIZLjava/lang/ref/WeakReference;)V", (void*)SurfaceTexture_init }, 389c6d993077761fc737bbb0f4db44b961a4e7b6bbbJamie Gennis {"nativeFinalize", "()V", (void*)SurfaceTexture_finalize }, 390050316184b01c0d1a01c46afae7429b89a27c31btedbo {"nativeSetDefaultBufferSize", "(II)V", (void*)SurfaceTexture_setDefaultBufferSize }, 3912b4bfa5efec7df408b4db127961cfc9aca9e57cfJamie Gennis {"nativeUpdateTexImage", "()V", (void*)SurfaceTexture_updateTexImage }, 392e591b49de038a9942cbcc77540c03e85c96e3dcbMathias Agopian {"nativeReleaseTexImage", "()V", (void*)SurfaceTexture_releaseTexImage }, 393c6d993077761fc737bbb0f4db44b961a4e7b6bbbJamie Gennis {"nativeDetachFromGLContext", "()I", (void*)SurfaceTexture_detachFromGLContext }, 394c6d993077761fc737bbb0f4db44b961a4e7b6bbbJamie Gennis {"nativeAttachToGLContext", "(I)I", (void*)SurfaceTexture_attachToGLContext }, 395c6d993077761fc737bbb0f4db44b961a4e7b6bbbJamie Gennis {"nativeGetTransformMatrix", "([F)V", (void*)SurfaceTexture_getTransformMatrix }, 396c6d993077761fc737bbb0f4db44b961a4e7b6bbbJamie Gennis {"nativeGetTimestamp", "()J", (void*)SurfaceTexture_getTimestamp }, 397c6d993077761fc737bbb0f4db44b961a4e7b6bbbJamie Gennis {"nativeRelease", "()V", (void*)SurfaceTexture_release }, 3986d8371e73ff6452be5a23089e7edeb8d6d96f065John Reck {"nativeIsReleased", "()Z", (void*)SurfaceTexture_isReleased }, 3996714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis}; 4006714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis 4016714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennisint register_android_graphics_SurfaceTexture(JNIEnv* env) 4026714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis{ 403ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe return RegisterMethodsOrDie(env, kSurfaceTextureClassPathName, gSurfaceTextureMethods, 404ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe NELEM(gSurfaceTextureMethods)); 4056714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis} 4066714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis 4076714efc5e0c52953b65e774de0003e22377e7d39Jamie Gennis} // namespace android 408