1c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim/* 2c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim * Copyright 2014 The Android Open Source Project 3c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim * 4c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim * Licensed under the Apache License, Version 2.0 (the "License"); 5c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim * you may not use this file except in compliance with the License. 6c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim * You may obtain a copy of the License at 7c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim * 8c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim * http://www.apache.org/licenses/LICENSE-2.0 9c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim * 10c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim * Unless required by applicable law or agreed to in writing, software 11c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim * distributed under the License is distributed on an "AS IS" BASIS, 12c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim * See the License for the specific language governing permissions and 14c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim * limitations under the License. 15c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim */ 16c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 17c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim#define LOG_TAG "TvInputHal" 18c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 19c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim//#define LOG_NDEBUG 0 20c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 21a617074c531dfa317e5051fa70ec6b6c21d14386Wonsik Kim#include "android_os_MessageQueue.h" 22c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim#include "android_runtime/AndroidRuntime.h" 23c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim#include "android_runtime/android_view_Surface.h" 24c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim#include "JNIHelp.h" 25c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim#include "jni.h" 26c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 27c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim#include <gui/Surface.h> 28c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim#include <utils/Errors.h> 29c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim#include <utils/KeyedVector.h> 30c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim#include <utils/Log.h> 31a617074c531dfa317e5051fa70ec6b6c21d14386Wonsik Kim#include <utils/Looper.h> 32c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim#include <utils/NativeHandle.h> 33c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim#include <hardware/tv_input.h> 34c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 35c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kimnamespace android { 36c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 37c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kimstatic struct { 38c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim jmethodID deviceAvailable; 39c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim jmethodID deviceUnavailable; 40c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim jmethodID streamConfigsChanged; 41c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo jmethodID firstFrameCaptured; 42c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim} gTvInputHalClassInfo; 43c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 44c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kimstatic struct { 45c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim jclass clazz; 46c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim} gTvStreamConfigClassInfo; 47c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 48c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kimstatic struct { 49c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim jclass clazz; 50c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 51c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim jmethodID constructor; 52c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim jmethodID streamId; 53c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim jmethodID type; 54c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim jmethodID maxWidth; 55c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim jmethodID maxHeight; 56c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim jmethodID generation; 57c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim jmethodID build; 58c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim} gTvStreamConfigBuilderClassInfo; 59c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 60d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kimstatic struct { 61d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim jclass clazz; 62d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim 63d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim jmethodID constructor; 64d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim jmethodID deviceId; 65d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim jmethodID type; 66a358b53e1d0bb7a7fc08b0a4d2a2e256f3045859Wonsik Kim jmethodID hdmiPortId; 67d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim jmethodID audioType; 68d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim jmethodID audioAddress; 69d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim jmethodID build; 70d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim} gTvInputHardwareInfoBuilderClassInfo; 71d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim 72c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim//////////////////////////////////////////////////////////////////////////////// 73c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 740b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kimclass BufferProducerThread : public Thread { 750b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kimpublic: 760b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim BufferProducerThread(tv_input_device_t* device, int deviceId, const tv_stream_t* stream); 770b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim 780b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim virtual status_t readyToRun(); 790b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim 800b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim void setSurface(const sp<Surface>& surface); 810b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim void onCaptured(uint32_t seq, bool succeeded); 820b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim void shutdown(); 830b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim 840b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kimprivate: 850b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim Mutex mLock; 860b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim Condition mCondition; 870b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim sp<Surface> mSurface; 880b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim tv_input_device_t* mDevice; 890b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim int mDeviceId; 900b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim tv_stream_t mStream; 910b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim sp<ANativeWindowBuffer_t> mBuffer; 920b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim enum { 930b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim CAPTURING, 940b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim CAPTURED, 950b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim RELEASED, 960b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim } mBufferState; 970b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim uint32_t mSeq; 980b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim bool mShutdown; 990b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim 1000b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim virtual bool threadLoop(); 1010b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim 1020b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim void setSurfaceLocked(const sp<Surface>& surface); 1030b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim}; 1040b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim 1050b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik KimBufferProducerThread::BufferProducerThread( 1060b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim tv_input_device_t* device, int deviceId, const tv_stream_t* stream) 1070b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim : Thread(false), 1080b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim mDevice(device), 1090b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim mDeviceId(deviceId), 1100b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim mBuffer(NULL), 1110b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim mBufferState(RELEASED), 1120b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim mSeq(0u), 1130b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim mShutdown(false) { 1140b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim memcpy(&mStream, stream, sizeof(mStream)); 1150b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim} 1160b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim 1170b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kimstatus_t BufferProducerThread::readyToRun() { 1180b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim sp<ANativeWindow> anw(mSurface); 1190b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim status_t err = native_window_set_usage(anw.get(), mStream.buffer_producer.usage); 1200b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim if (err != NO_ERROR) { 1210b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim return err; 1220b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim } 1230b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim err = native_window_set_buffers_dimensions( 1240b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim anw.get(), mStream.buffer_producer.width, mStream.buffer_producer.height); 1250b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim if (err != NO_ERROR) { 1260b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim return err; 1270b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim } 1280b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim err = native_window_set_buffers_format(anw.get(), mStream.buffer_producer.format); 1290b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim if (err != NO_ERROR) { 1300b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim return err; 1310b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim } 1320b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim return NO_ERROR; 1330b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim} 1340b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim 1350b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kimvoid BufferProducerThread::setSurface(const sp<Surface>& surface) { 1360b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim Mutex::Autolock autoLock(&mLock); 1370b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim setSurfaceLocked(surface); 1380b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim} 1390b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim 1400b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kimvoid BufferProducerThread::setSurfaceLocked(const sp<Surface>& surface) { 1410b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim if (surface == mSurface) { 1420b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim return; 1430b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim } 1440b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim 1450b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim if (mBufferState == CAPTURING) { 1460b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim mDevice->cancel_capture(mDevice, mDeviceId, mStream.stream_id, mSeq); 1470b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim } 1480b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim while (mBufferState == CAPTURING) { 1490b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim status_t err = mCondition.waitRelative(mLock, s2ns(1)); 1500b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim if (err != NO_ERROR) { 1510b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim ALOGE("error %d while wating for buffer state to change.", err); 1520b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim break; 1530b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim } 1540b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim } 1550b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim mBuffer.clear(); 1560b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim mBufferState = RELEASED; 1570b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim 1580b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim mSurface = surface; 1590b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim mCondition.broadcast(); 1600b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim} 1610b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim 1620b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kimvoid BufferProducerThread::onCaptured(uint32_t seq, bool succeeded) { 1630b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim Mutex::Autolock autoLock(&mLock); 1640b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim if (seq != mSeq) { 1650b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim ALOGW("Incorrect sequence value: expected %u actual %u", mSeq, seq); 1660b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim } 1670b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim if (mBufferState != CAPTURING) { 1680b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim ALOGW("mBufferState != CAPTURING : instead %d", mBufferState); 1690b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim } 1700b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim if (succeeded) { 1710b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim mBufferState = CAPTURED; 1720b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim } else { 1730b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim mBuffer.clear(); 1740b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim mBufferState = RELEASED; 1750b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim } 1760b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim mCondition.broadcast(); 1770b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim} 1780b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim 1790b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kimvoid BufferProducerThread::shutdown() { 1800b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim Mutex::Autolock autoLock(&mLock); 1810b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim mShutdown = true; 1820b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim setSurfaceLocked(NULL); 1830b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim requestExitAndWait(); 1840b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim} 1850b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim 1860b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kimbool BufferProducerThread::threadLoop() { 1870b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim Mutex::Autolock autoLock(&mLock); 1880b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim 1890b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim status_t err = NO_ERROR; 1900b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim if (mSurface == NULL) { 1910b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim err = mCondition.waitRelative(mLock, s2ns(1)); 1920b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim // It's OK to time out here. 1930b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim if (err != NO_ERROR && err != TIMED_OUT) { 1940b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim ALOGE("error %d while wating for non-null surface to be set", err); 1950b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim return false; 1960b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim } 1970b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim return true; 1980b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim } 1990b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim sp<ANativeWindow> anw(mSurface); 2000b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim while (mBufferState == CAPTURING) { 2010b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim err = mCondition.waitRelative(mLock, s2ns(1)); 2020b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim if (err != NO_ERROR) { 2030b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim ALOGE("error %d while wating for buffer state to change.", err); 2040b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim return false; 2050b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim } 2060b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim } 2070b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim if (mBufferState == CAPTURED && anw != NULL) { 2080b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim err = anw->queueBuffer(anw.get(), mBuffer.get(), -1); 2090b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim if (err != NO_ERROR) { 2100b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim ALOGE("error %d while queueing buffer to surface", err); 2110b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim return false; 2120b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim } 2130b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim mBuffer.clear(); 2140b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim mBufferState = RELEASED; 2150b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim } 2160b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim if (mBuffer == NULL && !mShutdown && anw != NULL) { 2170b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim ANativeWindowBuffer_t* buffer = NULL; 2180b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim err = native_window_dequeue_buffer_and_wait(anw.get(), &buffer); 2190b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim if (err != NO_ERROR) { 2200b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim ALOGE("error %d while dequeueing buffer to surface", err); 2210b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim return false; 2220b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim } 2230b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim mBuffer = buffer; 2240b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim mBufferState = CAPTURING; 2250b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim mDevice->request_capture(mDevice, mDeviceId, mStream.stream_id, 2260b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim buffer->handle, ++mSeq); 2270b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim } 2280b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim 2290b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim return true; 2300b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim} 2310b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim 2320b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim//////////////////////////////////////////////////////////////////////////////// 2330b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim 234c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kimclass JTvInputHal { 235c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kimpublic: 236c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim ~JTvInputHal(); 237c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 238a617074c531dfa317e5051fa70ec6b6c21d14386Wonsik Kim static JTvInputHal* createInstance(JNIEnv* env, jobject thiz, const sp<Looper>& looper); 239c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 2408f24a8b60f9afc1aedb89e7ee80ce65515439600Wonsik Kim int addOrUpdateStream(int deviceId, int streamId, const sp<Surface>& surface); 241839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim int removeStream(int deviceId, int streamId); 2424a3a601082b88ee057aa71421e45cb00041ecfffDongwon Kang const tv_stream_config_t* getStreamConfigs(int deviceId, int* numConfigs); 243c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 244a617074c531dfa317e5051fa70ec6b6c21d14386Wonsik Kim void onDeviceAvailable(const tv_input_device_info_t& info); 245a617074c531dfa317e5051fa70ec6b6c21d14386Wonsik Kim void onDeviceUnavailable(int deviceId); 246a617074c531dfa317e5051fa70ec6b6c21d14386Wonsik Kim void onStreamConfigurationsChanged(int deviceId); 247a617074c531dfa317e5051fa70ec6b6c21d14386Wonsik Kim void onCaptured(int deviceId, int streamId, uint32_t seq, bool succeeded); 248a617074c531dfa317e5051fa70ec6b6c21d14386Wonsik Kim 249c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kimprivate: 2500b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim // Connection between a surface and a stream. 251c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim class Connection { 252c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim public: 253839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim Connection() {} 254c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 255c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim sp<Surface> mSurface; 2560b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim tv_stream_type_t mStreamType; 2570b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim 2580b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim // Only valid when mStreamType == TV_STREAM_TYPE_INDEPENDENT_VIDEO_SOURCE 259c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim sp<NativeHandle> mSourceHandle; 2600b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim // Only valid when mStreamType == TV_STREAM_TYPE_BUFFER_PRODUCER 2610b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim sp<BufferProducerThread> mThread; 262c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim }; 263c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 264a617074c531dfa317e5051fa70ec6b6c21d14386Wonsik Kim class NotifyHandler : public MessageHandler { 265a617074c531dfa317e5051fa70ec6b6c21d14386Wonsik Kim public: 266a617074c531dfa317e5051fa70ec6b6c21d14386Wonsik Kim NotifyHandler(JTvInputHal* hal, const tv_input_event_t* event); 26762f38d14c531e5983dafb2e0b93bae9f7769953cSungsoo Lim ~NotifyHandler(); 268a617074c531dfa317e5051fa70ec6b6c21d14386Wonsik Kim 269a617074c531dfa317e5051fa70ec6b6c21d14386Wonsik Kim virtual void handleMessage(const Message& message); 270a617074c531dfa317e5051fa70ec6b6c21d14386Wonsik Kim 271a617074c531dfa317e5051fa70ec6b6c21d14386Wonsik Kim private: 272a617074c531dfa317e5051fa70ec6b6c21d14386Wonsik Kim tv_input_event_t mEvent; 273a617074c531dfa317e5051fa70ec6b6c21d14386Wonsik Kim JTvInputHal* mHal; 274a617074c531dfa317e5051fa70ec6b6c21d14386Wonsik Kim }; 275a617074c531dfa317e5051fa70ec6b6c21d14386Wonsik Kim 276a617074c531dfa317e5051fa70ec6b6c21d14386Wonsik Kim JTvInputHal(JNIEnv* env, jobject thiz, tv_input_device_t* dev, const sp<Looper>& looper); 277c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 278c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim static void notify( 2790b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim tv_input_device_t* dev, tv_input_event_t* event, void* data); 280c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 28162f38d14c531e5983dafb2e0b93bae9f7769953cSungsoo Lim static void cloneTvInputEvent( 28262f38d14c531e5983dafb2e0b93bae9f7769953cSungsoo Lim tv_input_event_t* dstEvent, const tv_input_event_t* srcEvent); 28362f38d14c531e5983dafb2e0b93bae9f7769953cSungsoo Lim 2840b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim Mutex mLock; 285c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim jweak mThiz; 286c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim tv_input_device_t* mDevice; 287c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim tv_input_callback_ops_t mCallback; 288a617074c531dfa317e5051fa70ec6b6c21d14386Wonsik Kim sp<Looper> mLooper; 289c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 290839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim KeyedVector<int, KeyedVector<int, Connection> > mConnections; 291c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim}; 292c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 293a617074c531dfa317e5051fa70ec6b6c21d14386Wonsik KimJTvInputHal::JTvInputHal(JNIEnv* env, jobject thiz, tv_input_device_t* device, 2944a3a601082b88ee057aa71421e45cb00041ecfffDongwon Kang const sp<Looper>& looper) { 295c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim mThiz = env->NewWeakGlobalRef(thiz); 296c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim mDevice = device; 297c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim mCallback.notify = &JTvInputHal::notify; 298a617074c531dfa317e5051fa70ec6b6c21d14386Wonsik Kim mLooper = looper; 299c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 300c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim mDevice->initialize(mDevice, &mCallback, this); 301c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim} 302c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 303c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik KimJTvInputHal::~JTvInputHal() { 304c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim mDevice->common.close((hw_device_t*)mDevice); 305c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 306c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim JNIEnv* env = AndroidRuntime::getJNIEnv(); 307c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim env->DeleteWeakGlobalRef(mThiz); 308c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim mThiz = NULL; 309c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim} 310c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 311a617074c531dfa317e5051fa70ec6b6c21d14386Wonsik KimJTvInputHal* JTvInputHal::createInstance(JNIEnv* env, jobject thiz, const sp<Looper>& looper) { 312c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim tv_input_module_t* module = NULL; 313c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim status_t err = hw_get_module(TV_INPUT_HARDWARE_MODULE_ID, 314c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim (hw_module_t const**)&module); 315c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim if (err) { 316c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim ALOGE("Couldn't load %s module (%s)", 317c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim TV_INPUT_HARDWARE_MODULE_ID, strerror(-err)); 318c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return 0; 319c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 320c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 321c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim tv_input_device_t* device = NULL; 322c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim err = module->common.methods->open( 323c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim (hw_module_t*)module, 324c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim TV_INPUT_DEFAULT_DEVICE, 325c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim (hw_device_t**)&device); 326c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim if (err) { 327c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim ALOGE("Couldn't open %s device (%s)", 328c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim TV_INPUT_DEFAULT_DEVICE, strerror(-err)); 329c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return 0; 330c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 331c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 332a617074c531dfa317e5051fa70ec6b6c21d14386Wonsik Kim return new JTvInputHal(env, thiz, device, looper); 333c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim} 334c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 3358f24a8b60f9afc1aedb89e7ee80ce65515439600Wonsik Kimint JTvInputHal::addOrUpdateStream(int deviceId, int streamId, const sp<Surface>& surface) { 336839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim KeyedVector<int, Connection>& connections = mConnections.editValueFor(deviceId); 337839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim if (connections.indexOfKey(streamId) < 0) { 338839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim connections.add(streamId, Connection()); 339839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim } 340839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim Connection& connection = connections.editValueFor(streamId); 341839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim if (connection.mSurface == surface) { 342c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim // Nothing to do 343c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return NO_ERROR; 344c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 3450b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim // Clear the surface in the connection. 3460b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim if (connection.mSurface != NULL) { 3470b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim if (connection.mStreamType == TV_STREAM_TYPE_INDEPENDENT_VIDEO_SOURCE) { 3480b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim if (Surface::isValid(connection.mSurface)) { 3490b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim connection.mSurface->setSidebandStream(NULL); 3500b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim } 3510b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim } 352c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim connection.mSurface.clear(); 353c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 3540b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim if (connection.mSourceHandle == NULL && connection.mThread == NULL) { 355c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim // Need to configure stream 356c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim int numConfigs = 0; 3574a3a601082b88ee057aa71421e45cb00041ecfffDongwon Kang const tv_stream_config_t* configs = NULL; 3584a3a601082b88ee057aa71421e45cb00041ecfffDongwon Kang if (mDevice->get_stream_configurations( 3594a3a601082b88ee057aa71421e45cb00041ecfffDongwon Kang mDevice, deviceId, &numConfigs, &configs) != 0) { 360c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim ALOGE("Couldn't get stream configs"); 361c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return UNKNOWN_ERROR; 362c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 363c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim int configIndex = -1; 364c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim for (int i = 0; i < numConfigs; ++i) { 3654a3a601082b88ee057aa71421e45cb00041ecfffDongwon Kang if (configs[i].stream_id == streamId) { 366c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim configIndex = i; 367c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim break; 368c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 369c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 370c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim if (configIndex == -1) { 371c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim ALOGE("Cannot find a config with given stream ID: %d", streamId); 372c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return BAD_VALUE; 373c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 3744a3a601082b88ee057aa71421e45cb00041ecfffDongwon Kang connection.mStreamType = configs[configIndex].type; 37521aa3467cd14260418cc47334b656adf841a567cWonsik Kim 376c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim tv_stream_t stream; 3774a3a601082b88ee057aa71421e45cb00041ecfffDongwon Kang stream.stream_id = configs[configIndex].stream_id; 3780b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim if (connection.mStreamType == TV_STREAM_TYPE_BUFFER_PRODUCER) { 3794a3a601082b88ee057aa71421e45cb00041ecfffDongwon Kang stream.buffer_producer.width = configs[configIndex].max_video_width; 3804a3a601082b88ee057aa71421e45cb00041ecfffDongwon Kang stream.buffer_producer.height = configs[configIndex].max_video_height; 3810b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim } 382c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim if (mDevice->open_stream(mDevice, deviceId, &stream) != 0) { 383c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim ALOGE("Couldn't add stream"); 384c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return UNKNOWN_ERROR; 385c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 3860b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim if (connection.mStreamType == TV_STREAM_TYPE_INDEPENDENT_VIDEO_SOURCE) { 3870b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim connection.mSourceHandle = NativeHandle::create( 3880b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim stream.sideband_stream_source_handle, false); 3890b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim } else if (connection.mStreamType == TV_STREAM_TYPE_BUFFER_PRODUCER) { 3900b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim if (connection.mThread != NULL) { 3910b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim connection.mThread->shutdown(); 3920b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim } 3930b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim connection.mThread = new BufferProducerThread(mDevice, deviceId, &stream); 39466f4831aa105f981ba1d5c21e3dcf8f1e0d76de8Brian Carlstrom connection.mThread->run("BufferProducerThread"); 3950b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim } 3960b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim } 3970b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim connection.mSurface = surface; 3980b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim if (connection.mStreamType == TV_STREAM_TYPE_INDEPENDENT_VIDEO_SOURCE) { 399c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim connection.mSurface->setSidebandStream(connection.mSourceHandle); 4000b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim } else if (connection.mStreamType == TV_STREAM_TYPE_BUFFER_PRODUCER) { 4010b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim connection.mThread->setSurface(surface); 402c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 403c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return NO_ERROR; 404c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim} 405c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 406839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kimint JTvInputHal::removeStream(int deviceId, int streamId) { 407839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim KeyedVector<int, Connection>& connections = mConnections.editValueFor(deviceId); 408839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim if (connections.indexOfKey(streamId) < 0) { 409839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim return BAD_VALUE; 410839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim } 411839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim Connection& connection = connections.editValueFor(streamId); 412839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim if (connection.mSurface == NULL) { 413839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim // Nothing to do 414839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim return NO_ERROR; 415839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim } 416839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim if (Surface::isValid(connection.mSurface)) { 417839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim connection.mSurface->setSidebandStream(NULL); 418839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim } 4196b1e695c56d19e8931c3bfecda77a9bbf30a6f02Wonsik Kim connection.mSurface.clear(); 420b82de3600f15edbff693d1362bf33140c2aabd33Wonsik Kim if (connection.mThread != NULL) { 421b82de3600f15edbff693d1362bf33140c2aabd33Wonsik Kim connection.mThread->shutdown(); 422b82de3600f15edbff693d1362bf33140c2aabd33Wonsik Kim connection.mThread.clear(); 423b82de3600f15edbff693d1362bf33140c2aabd33Wonsik Kim } 424b82de3600f15edbff693d1362bf33140c2aabd33Wonsik Kim if (mDevice->close_stream(mDevice, deviceId, streamId) != 0) { 425b82de3600f15edbff693d1362bf33140c2aabd33Wonsik Kim ALOGE("Couldn't remove stream"); 426b82de3600f15edbff693d1362bf33140c2aabd33Wonsik Kim return BAD_VALUE; 427b82de3600f15edbff693d1362bf33140c2aabd33Wonsik Kim } 428839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim if (connection.mSourceHandle != NULL) { 429839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim connection.mSourceHandle.clear(); 430839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim } 431839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim return NO_ERROR; 432839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim} 433839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim 4344a3a601082b88ee057aa71421e45cb00041ecfffDongwon Kangconst tv_stream_config_t* JTvInputHal::getStreamConfigs(int deviceId, int* numConfigs) { 4354a3a601082b88ee057aa71421e45cb00041ecfffDongwon Kang const tv_stream_config_t* configs = NULL; 4364a3a601082b88ee057aa71421e45cb00041ecfffDongwon Kang if (mDevice->get_stream_configurations( 4374a3a601082b88ee057aa71421e45cb00041ecfffDongwon Kang mDevice, deviceId, numConfigs, &configs) != 0) { 4384a3a601082b88ee057aa71421e45cb00041ecfffDongwon Kang ALOGE("Couldn't get stream configs"); 4394a3a601082b88ee057aa71421e45cb00041ecfffDongwon Kang return NULL; 440c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 441c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return configs; 442c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim} 443c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 444c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim// static 445c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kimvoid JTvInputHal::notify( 446c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim tv_input_device_t* dev, tv_input_event_t* event, void* data) { 447c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim JTvInputHal* thiz = (JTvInputHal*)data; 448a617074c531dfa317e5051fa70ec6b6c21d14386Wonsik Kim thiz->mLooper->sendMessage(new NotifyHandler(thiz, event), event->type); 449c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim} 450c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 45162f38d14c531e5983dafb2e0b93bae9f7769953cSungsoo Lim// static 45262f38d14c531e5983dafb2e0b93bae9f7769953cSungsoo Limvoid JTvInputHal::cloneTvInputEvent( 45362f38d14c531e5983dafb2e0b93bae9f7769953cSungsoo Lim tv_input_event_t* dstEvent, const tv_input_event_t* srcEvent) { 45462f38d14c531e5983dafb2e0b93bae9f7769953cSungsoo Lim memcpy(dstEvent, srcEvent, sizeof(tv_input_event_t)); 45562f38d14c531e5983dafb2e0b93bae9f7769953cSungsoo Lim if ((srcEvent->type == TV_INPUT_EVENT_DEVICE_AVAILABLE || 45662f38d14c531e5983dafb2e0b93bae9f7769953cSungsoo Lim srcEvent->type == TV_INPUT_EVENT_DEVICE_UNAVAILABLE || 45762f38d14c531e5983dafb2e0b93bae9f7769953cSungsoo Lim srcEvent->type == TV_INPUT_EVENT_STREAM_CONFIGURATIONS_CHANGED) && 45862f38d14c531e5983dafb2e0b93bae9f7769953cSungsoo Lim srcEvent->device_info.audio_address != NULL){ 45962f38d14c531e5983dafb2e0b93bae9f7769953cSungsoo Lim char* audio_address = new char[strlen(srcEvent->device_info.audio_address) + 1]; 46062f38d14c531e5983dafb2e0b93bae9f7769953cSungsoo Lim strcpy(audio_address, srcEvent->device_info.audio_address); 46162f38d14c531e5983dafb2e0b93bae9f7769953cSungsoo Lim dstEvent->device_info.audio_address = audio_address; 46262f38d14c531e5983dafb2e0b93bae9f7769953cSungsoo Lim } 46362f38d14c531e5983dafb2e0b93bae9f7769953cSungsoo Lim} 46462f38d14c531e5983dafb2e0b93bae9f7769953cSungsoo Lim 465c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kimvoid JTvInputHal::onDeviceAvailable(const tv_input_device_info_t& info) { 4660b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim { 4670b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim Mutex::Autolock autoLock(&mLock); 4680b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim mConnections.add(info.device_id, KeyedVector<int, Connection>()); 4690b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim } 470c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim JNIEnv* env = AndroidRuntime::getJNIEnv(); 471d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim 472d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim jobject builder = env->NewObject( 473d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim gTvInputHardwareInfoBuilderClassInfo.clazz, 474d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim gTvInputHardwareInfoBuilderClassInfo.constructor); 475d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim env->CallObjectMethod( 476d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim builder, gTvInputHardwareInfoBuilderClassInfo.deviceId, info.device_id); 477d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim env->CallObjectMethod( 478d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim builder, gTvInputHardwareInfoBuilderClassInfo.type, info.type); 479a358b53e1d0bb7a7fc08b0a4d2a2e256f3045859Wonsik Kim if (info.type == TV_INPUT_TYPE_HDMI) { 480a358b53e1d0bb7a7fc08b0a4d2a2e256f3045859Wonsik Kim env->CallObjectMethod( 481a358b53e1d0bb7a7fc08b0a4d2a2e256f3045859Wonsik Kim builder, gTvInputHardwareInfoBuilderClassInfo.hdmiPortId, info.hdmi.port_id); 482a358b53e1d0bb7a7fc08b0a4d2a2e256f3045859Wonsik Kim } 483d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim env->CallObjectMethod( 484d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim builder, gTvInputHardwareInfoBuilderClassInfo.audioType, info.audio_type); 485d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim if (info.audio_type != AUDIO_DEVICE_NONE) { 486d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim jstring audioAddress = env->NewStringUTF(info.audio_address); 487d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim env->CallObjectMethod( 488d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim builder, gTvInputHardwareInfoBuilderClassInfo.audioAddress, audioAddress); 489d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim env->DeleteLocalRef(audioAddress); 490d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim } 491d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim 492d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim jobject infoObject = env->CallObjectMethod(builder, gTvInputHardwareInfoBuilderClassInfo.build); 493d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim 494c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim env->CallVoidMethod( 495c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim mThiz, 496c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim gTvInputHalClassInfo.deviceAvailable, 497d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim infoObject); 498d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim 499d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim env->DeleteLocalRef(builder); 500d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim env->DeleteLocalRef(infoObject); 501c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim} 502c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 503c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kimvoid JTvInputHal::onDeviceUnavailable(int deviceId) { 5040b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim { 5050b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim Mutex::Autolock autoLock(&mLock); 5060b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim KeyedVector<int, Connection>& connections = mConnections.editValueFor(deviceId); 5070b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim for (size_t i = 0; i < connections.size(); ++i) { 5080b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim removeStream(deviceId, connections.keyAt(i)); 5090b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim } 5100b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim connections.clear(); 5110b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim mConnections.removeItem(deviceId); 512839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim } 5130b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim JNIEnv* env = AndroidRuntime::getJNIEnv(); 514c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim env->CallVoidMethod( 515c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim mThiz, 516c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim gTvInputHalClassInfo.deviceUnavailable, 517c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim deviceId); 518c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim} 519c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 520c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kimvoid JTvInputHal::onStreamConfigurationsChanged(int deviceId) { 5210b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim { 5220b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim Mutex::Autolock autoLock(&mLock); 5230b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim KeyedVector<int, Connection>& connections = mConnections.editValueFor(deviceId); 5240b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim for (size_t i = 0; i < connections.size(); ++i) { 5250b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim removeStream(deviceId, connections.keyAt(i)); 5260b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim } 5270b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim connections.clear(); 528839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim } 5290b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim JNIEnv* env = AndroidRuntime::getJNIEnv(); 530c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim env->CallVoidMethod( 531c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim mThiz, 532c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim gTvInputHalClassInfo.streamConfigsChanged, 533c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim deviceId); 534c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim} 535c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 5360b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kimvoid JTvInputHal::onCaptured(int deviceId, int streamId, uint32_t seq, bool succeeded) { 5370b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim sp<BufferProducerThread> thread; 5380b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim { 5390b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim Mutex::Autolock autoLock(&mLock); 5400b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim KeyedVector<int, Connection>& connections = mConnections.editValueFor(deviceId); 5410b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim Connection& connection = connections.editValueFor(streamId); 5420b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim if (connection.mThread == NULL) { 5430b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim ALOGE("capture thread not existing."); 5440b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim return; 5450b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim } 5460b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim thread = connection.mThread; 5470b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim } 5480b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim thread->onCaptured(seq, succeeded); 549c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo if (seq == 0) { 550c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo JNIEnv* env = AndroidRuntime::getJNIEnv(); 551c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo env->CallVoidMethod( 552c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo mThiz, 553c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo gTvInputHalClassInfo.firstFrameCaptured, 554c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo deviceId, 555c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo streamId); 556c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 5570b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim} 5580b2691b6873f9d328884c5a9e5ab1fe308f3ee36Wonsik Kim 559a617074c531dfa317e5051fa70ec6b6c21d14386Wonsik KimJTvInputHal::NotifyHandler::NotifyHandler(JTvInputHal* hal, const tv_input_event_t* event) { 560a617074c531dfa317e5051fa70ec6b6c21d14386Wonsik Kim mHal = hal; 56162f38d14c531e5983dafb2e0b93bae9f7769953cSungsoo Lim cloneTvInputEvent(&mEvent, event); 56262f38d14c531e5983dafb2e0b93bae9f7769953cSungsoo Lim} 56362f38d14c531e5983dafb2e0b93bae9f7769953cSungsoo Lim 56462f38d14c531e5983dafb2e0b93bae9f7769953cSungsoo LimJTvInputHal::NotifyHandler::~NotifyHandler() { 56562f38d14c531e5983dafb2e0b93bae9f7769953cSungsoo Lim if ((mEvent.type == TV_INPUT_EVENT_DEVICE_AVAILABLE || 56662f38d14c531e5983dafb2e0b93bae9f7769953cSungsoo Lim mEvent.type == TV_INPUT_EVENT_DEVICE_UNAVAILABLE || 56762f38d14c531e5983dafb2e0b93bae9f7769953cSungsoo Lim mEvent.type == TV_INPUT_EVENT_STREAM_CONFIGURATIONS_CHANGED) && 56862f38d14c531e5983dafb2e0b93bae9f7769953cSungsoo Lim mEvent.device_info.audio_address != NULL) { 56962f38d14c531e5983dafb2e0b93bae9f7769953cSungsoo Lim delete mEvent.device_info.audio_address; 57062f38d14c531e5983dafb2e0b93bae9f7769953cSungsoo Lim } 571a617074c531dfa317e5051fa70ec6b6c21d14386Wonsik Kim} 572a617074c531dfa317e5051fa70ec6b6c21d14386Wonsik Kim 573a617074c531dfa317e5051fa70ec6b6c21d14386Wonsik Kimvoid JTvInputHal::NotifyHandler::handleMessage(const Message& message) { 574a617074c531dfa317e5051fa70ec6b6c21d14386Wonsik Kim switch (mEvent.type) { 575a617074c531dfa317e5051fa70ec6b6c21d14386Wonsik Kim case TV_INPUT_EVENT_DEVICE_AVAILABLE: { 576a617074c531dfa317e5051fa70ec6b6c21d14386Wonsik Kim mHal->onDeviceAvailable(mEvent.device_info); 577a617074c531dfa317e5051fa70ec6b6c21d14386Wonsik Kim } break; 578a617074c531dfa317e5051fa70ec6b6c21d14386Wonsik Kim case TV_INPUT_EVENT_DEVICE_UNAVAILABLE: { 579a617074c531dfa317e5051fa70ec6b6c21d14386Wonsik Kim mHal->onDeviceUnavailable(mEvent.device_info.device_id); 580a617074c531dfa317e5051fa70ec6b6c21d14386Wonsik Kim } break; 581a617074c531dfa317e5051fa70ec6b6c21d14386Wonsik Kim case TV_INPUT_EVENT_STREAM_CONFIGURATIONS_CHANGED: { 582a617074c531dfa317e5051fa70ec6b6c21d14386Wonsik Kim mHal->onStreamConfigurationsChanged(mEvent.device_info.device_id); 583a617074c531dfa317e5051fa70ec6b6c21d14386Wonsik Kim } break; 584a617074c531dfa317e5051fa70ec6b6c21d14386Wonsik Kim case TV_INPUT_EVENT_CAPTURE_SUCCEEDED: { 585a617074c531dfa317e5051fa70ec6b6c21d14386Wonsik Kim mHal->onCaptured(mEvent.capture_result.device_id, 586a617074c531dfa317e5051fa70ec6b6c21d14386Wonsik Kim mEvent.capture_result.stream_id, 587a617074c531dfa317e5051fa70ec6b6c21d14386Wonsik Kim mEvent.capture_result.seq, 588a617074c531dfa317e5051fa70ec6b6c21d14386Wonsik Kim true /* succeeded */); 589a617074c531dfa317e5051fa70ec6b6c21d14386Wonsik Kim } break; 590a617074c531dfa317e5051fa70ec6b6c21d14386Wonsik Kim case TV_INPUT_EVENT_CAPTURE_FAILED: { 591a617074c531dfa317e5051fa70ec6b6c21d14386Wonsik Kim mHal->onCaptured(mEvent.capture_result.device_id, 592a617074c531dfa317e5051fa70ec6b6c21d14386Wonsik Kim mEvent.capture_result.stream_id, 593a617074c531dfa317e5051fa70ec6b6c21d14386Wonsik Kim mEvent.capture_result.seq, 594a617074c531dfa317e5051fa70ec6b6c21d14386Wonsik Kim false /* succeeded */); 595a617074c531dfa317e5051fa70ec6b6c21d14386Wonsik Kim } break; 596a617074c531dfa317e5051fa70ec6b6c21d14386Wonsik Kim default: 597a617074c531dfa317e5051fa70ec6b6c21d14386Wonsik Kim ALOGE("Unrecognizable event"); 598a617074c531dfa317e5051fa70ec6b6c21d14386Wonsik Kim } 599a617074c531dfa317e5051fa70ec6b6c21d14386Wonsik Kim} 600a617074c531dfa317e5051fa70ec6b6c21d14386Wonsik Kim 601c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim//////////////////////////////////////////////////////////////////////////////// 602c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 603a617074c531dfa317e5051fa70ec6b6c21d14386Wonsik Kimstatic jlong nativeOpen(JNIEnv* env, jobject thiz, jobject messageQueueObj) { 604a617074c531dfa317e5051fa70ec6b6c21d14386Wonsik Kim sp<MessageQueue> messageQueue = 605a617074c531dfa317e5051fa70ec6b6c21d14386Wonsik Kim android_os_MessageQueue_getMessageQueue(env, messageQueueObj); 606a617074c531dfa317e5051fa70ec6b6c21d14386Wonsik Kim return (jlong)JTvInputHal::createInstance(env, thiz, messageQueue->getLooper()); 607c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim} 608c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 6098f24a8b60f9afc1aedb89e7ee80ce65515439600Wonsik Kimstatic int nativeAddOrUpdateStream(JNIEnv* env, jclass clazz, 610c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim jlong ptr, jint deviceId, jint streamId, jobject jsurface) { 611c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim JTvInputHal* tvInputHal = (JTvInputHal*)ptr; 612839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim if (!jsurface) { 613839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim return BAD_VALUE; 614839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim } 615839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim sp<Surface> surface(android_view_Surface_getSurface(env, jsurface)); 6166b1e695c56d19e8931c3bfecda77a9bbf30a6f02Wonsik Kim if (!Surface::isValid(surface)) { 6176b1e695c56d19e8931c3bfecda77a9bbf30a6f02Wonsik Kim return BAD_VALUE; 6186b1e695c56d19e8931c3bfecda77a9bbf30a6f02Wonsik Kim } 6198f24a8b60f9afc1aedb89e7ee80ce65515439600Wonsik Kim return tvInputHal->addOrUpdateStream(deviceId, streamId, surface); 620839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim} 621839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim 622839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kimstatic int nativeRemoveStream(JNIEnv* env, jclass clazz, 623839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim jlong ptr, jint deviceId, jint streamId) { 624839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim JTvInputHal* tvInputHal = (JTvInputHal*)ptr; 625839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim return tvInputHal->removeStream(deviceId, streamId); 626c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim} 627c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 628c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kimstatic jobjectArray nativeGetStreamConfigs(JNIEnv* env, jclass clazz, 629c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim jlong ptr, jint deviceId, jint generation) { 630c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim JTvInputHal* tvInputHal = (JTvInputHal*)ptr; 631c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim int numConfigs = 0; 6324a3a601082b88ee057aa71421e45cb00041ecfffDongwon Kang const tv_stream_config_t* configs = tvInputHal->getStreamConfigs(deviceId, &numConfigs); 633c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 634c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim jobjectArray result = env->NewObjectArray(numConfigs, gTvStreamConfigClassInfo.clazz, NULL); 635c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim for (int i = 0; i < numConfigs; ++i) { 636c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim jobject builder = env->NewObject( 637c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim gTvStreamConfigBuilderClassInfo.clazz, 638c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim gTvStreamConfigBuilderClassInfo.constructor); 639c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim env->CallObjectMethod( 6404a3a601082b88ee057aa71421e45cb00041ecfffDongwon Kang builder, gTvStreamConfigBuilderClassInfo.streamId, configs[i].stream_id); 641c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim env->CallObjectMethod( 6424a3a601082b88ee057aa71421e45cb00041ecfffDongwon Kang builder, gTvStreamConfigBuilderClassInfo.type, configs[i].type); 643c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim env->CallObjectMethod( 6444a3a601082b88ee057aa71421e45cb00041ecfffDongwon Kang builder, gTvStreamConfigBuilderClassInfo.maxWidth, configs[i].max_video_width); 645c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim env->CallObjectMethod( 6464a3a601082b88ee057aa71421e45cb00041ecfffDongwon Kang builder, gTvStreamConfigBuilderClassInfo.maxHeight, configs[i].max_video_height); 647c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim env->CallObjectMethod( 648c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim builder, gTvStreamConfigBuilderClassInfo.generation, generation); 649c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 650c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim jobject config = env->CallObjectMethod(builder, gTvStreamConfigBuilderClassInfo.build); 651c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 652c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim env->SetObjectArrayElement(result, i, config); 653c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 654c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim env->DeleteLocalRef(config); 655c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim env->DeleteLocalRef(builder); 656c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 657c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return result; 658c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim} 659c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 660c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kimstatic void nativeClose(JNIEnv* env, jclass clazz, jlong ptr) { 661c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim JTvInputHal* tvInputHal = (JTvInputHal*)ptr; 662c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim delete tvInputHal; 663c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim} 664c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 66576f6a86de25e1bf74717e047e55fd44b089673f3Daniel Micaystatic const JNINativeMethod gTvInputHalMethods[] = { 666c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim /* name, signature, funcPtr */ 667a617074c531dfa317e5051fa70ec6b6c21d14386Wonsik Kim { "nativeOpen", "(Landroid/os/MessageQueue;)J", 668c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim (void*) nativeOpen }, 6698f24a8b60f9afc1aedb89e7ee80ce65515439600Wonsik Kim { "nativeAddOrUpdateStream", "(JIILandroid/view/Surface;)I", 6708f24a8b60f9afc1aedb89e7ee80ce65515439600Wonsik Kim (void*) nativeAddOrUpdateStream }, 671839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim { "nativeRemoveStream", "(JII)I", 672839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim (void*) nativeRemoveStream }, 673d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seo { "nativeGetStreamConfigs", "(JII)[Landroid/media/tv/TvStreamConfig;", 674c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim (void*) nativeGetStreamConfigs }, 675c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim { "nativeClose", "(J)V", 676c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim (void*) nativeClose }, 677c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim}; 678c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 679c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim#define FIND_CLASS(var, className) \ 680c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim var = env->FindClass(className); \ 681c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim LOG_FATAL_IF(! var, "Unable to find class " className) 682c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 683c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim#define GET_METHOD_ID(var, clazz, methodName, fieldDescriptor) \ 684c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim var = env->GetMethodID(clazz, methodName, fieldDescriptor); \ 685c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim LOG_FATAL_IF(! var, "Unable to find method" methodName) 686c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 687c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kimint register_android_server_tv_TvInputHal(JNIEnv* env) { 688c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim int res = jniRegisterNativeMethods(env, "com/android/server/tv/TvInputHal", 689c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim gTvInputHalMethods, NELEM(gTvInputHalMethods)); 690c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim LOG_FATAL_IF(res < 0, "Unable to register native methods."); 6914048a4bcb1ea709ddb83a4fde3ff5c53e642f7d0Bernhard Rosenkränzer (void)res; // Don't complain about unused variable in the LOG_NDEBUG case 692c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 693c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim jclass clazz; 694c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim FIND_CLASS(clazz, "com/android/server/tv/TvInputHal"); 695c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 696c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim GET_METHOD_ID( 697d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim gTvInputHalClassInfo.deviceAvailable, clazz, 698d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim "deviceAvailableFromNative", "(Landroid/media/tv/TvInputHardwareInfo;)V"); 699c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim GET_METHOD_ID( 700c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim gTvInputHalClassInfo.deviceUnavailable, clazz, "deviceUnavailableFromNative", "(I)V"); 701c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim GET_METHOD_ID( 702c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim gTvInputHalClassInfo.streamConfigsChanged, clazz, 703c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim "streamConfigsChangedFromNative", "(I)V"); 704c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo GET_METHOD_ID( 705c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo gTvInputHalClassInfo.firstFrameCaptured, clazz, 706c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo "firstFrameCapturedFromNative", "(II)V"); 707c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 708d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seo FIND_CLASS(gTvStreamConfigClassInfo.clazz, "android/media/tv/TvStreamConfig"); 709c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim gTvStreamConfigClassInfo.clazz = jclass(env->NewGlobalRef(gTvStreamConfigClassInfo.clazz)); 710c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 711d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seo FIND_CLASS(gTvStreamConfigBuilderClassInfo.clazz, "android/media/tv/TvStreamConfig$Builder"); 712c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim gTvStreamConfigBuilderClassInfo.clazz = 713c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim jclass(env->NewGlobalRef(gTvStreamConfigBuilderClassInfo.clazz)); 714c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 715c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim GET_METHOD_ID( 716c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim gTvStreamConfigBuilderClassInfo.constructor, 717c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim gTvStreamConfigBuilderClassInfo.clazz, 718c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim "<init>", "()V"); 719c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim GET_METHOD_ID( 720c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim gTvStreamConfigBuilderClassInfo.streamId, 721c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim gTvStreamConfigBuilderClassInfo.clazz, 722d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seo "streamId", "(I)Landroid/media/tv/TvStreamConfig$Builder;"); 723c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim GET_METHOD_ID( 724c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim gTvStreamConfigBuilderClassInfo.type, 725c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim gTvStreamConfigBuilderClassInfo.clazz, 726d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seo "type", "(I)Landroid/media/tv/TvStreamConfig$Builder;"); 727c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim GET_METHOD_ID( 728c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim gTvStreamConfigBuilderClassInfo.maxWidth, 729c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim gTvStreamConfigBuilderClassInfo.clazz, 730d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seo "maxWidth", "(I)Landroid/media/tv/TvStreamConfig$Builder;"); 731c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim GET_METHOD_ID( 732c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim gTvStreamConfigBuilderClassInfo.maxHeight, 733c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim gTvStreamConfigBuilderClassInfo.clazz, 734d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seo "maxHeight", "(I)Landroid/media/tv/TvStreamConfig$Builder;"); 735c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim GET_METHOD_ID( 736c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim gTvStreamConfigBuilderClassInfo.generation, 737c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim gTvStreamConfigBuilderClassInfo.clazz, 738d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seo "generation", "(I)Landroid/media/tv/TvStreamConfig$Builder;"); 739c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim GET_METHOD_ID( 740c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim gTvStreamConfigBuilderClassInfo.build, 741c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim gTvStreamConfigBuilderClassInfo.clazz, 742d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seo "build", "()Landroid/media/tv/TvStreamConfig;"); 743c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 744d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim FIND_CLASS(gTvInputHardwareInfoBuilderClassInfo.clazz, 745d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim "android/media/tv/TvInputHardwareInfo$Builder"); 746d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim gTvInputHardwareInfoBuilderClassInfo.clazz = 747d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim jclass(env->NewGlobalRef(gTvInputHardwareInfoBuilderClassInfo.clazz)); 748d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim 749d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim GET_METHOD_ID( 750d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim gTvInputHardwareInfoBuilderClassInfo.constructor, 751d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim gTvInputHardwareInfoBuilderClassInfo.clazz, 752d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim "<init>", "()V"); 753d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim GET_METHOD_ID( 754d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim gTvInputHardwareInfoBuilderClassInfo.deviceId, 755d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim gTvInputHardwareInfoBuilderClassInfo.clazz, 756d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim "deviceId", "(I)Landroid/media/tv/TvInputHardwareInfo$Builder;"); 757d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim GET_METHOD_ID( 758d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim gTvInputHardwareInfoBuilderClassInfo.type, 759d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim gTvInputHardwareInfoBuilderClassInfo.clazz, 760d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim "type", "(I)Landroid/media/tv/TvInputHardwareInfo$Builder;"); 761d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim GET_METHOD_ID( 762a358b53e1d0bb7a7fc08b0a4d2a2e256f3045859Wonsik Kim gTvInputHardwareInfoBuilderClassInfo.hdmiPortId, 763a358b53e1d0bb7a7fc08b0a4d2a2e256f3045859Wonsik Kim gTvInputHardwareInfoBuilderClassInfo.clazz, 764a358b53e1d0bb7a7fc08b0a4d2a2e256f3045859Wonsik Kim "hdmiPortId", "(I)Landroid/media/tv/TvInputHardwareInfo$Builder;"); 765a358b53e1d0bb7a7fc08b0a4d2a2e256f3045859Wonsik Kim GET_METHOD_ID( 766d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim gTvInputHardwareInfoBuilderClassInfo.audioType, 767d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim gTvInputHardwareInfoBuilderClassInfo.clazz, 768d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim "audioType", "(I)Landroid/media/tv/TvInputHardwareInfo$Builder;"); 769d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim GET_METHOD_ID( 770d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim gTvInputHardwareInfoBuilderClassInfo.audioAddress, 771d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim gTvInputHardwareInfoBuilderClassInfo.clazz, 772d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim "audioAddress", "(Ljava/lang/String;)Landroid/media/tv/TvInputHardwareInfo$Builder;"); 773d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim GET_METHOD_ID( 774d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim gTvInputHardwareInfoBuilderClassInfo.build, 775d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim gTvInputHardwareInfoBuilderClassInfo.clazz, 776d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim "build", "()Landroid/media/tv/TvInputHardwareInfo;"); 777d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim 778c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return 0; 779c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim} 780c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 781c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim} /* namespace android */ 782