com_android_server_tv_TvInputHal.cpp revision b82de3600f15edbff693d1362bf33140c2aabd33
1/* 2 * Copyright 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#define LOG_TAG "TvInputHal" 18 19//#define LOG_NDEBUG 0 20 21#include "android_runtime/AndroidRuntime.h" 22#include "android_runtime/android_view_Surface.h" 23#include "JNIHelp.h" 24#include "jni.h" 25 26#include <gui/Surface.h> 27#include <utils/Errors.h> 28#include <utils/KeyedVector.h> 29#include <utils/Log.h> 30#include <utils/NativeHandle.h> 31#include <hardware/tv_input.h> 32 33namespace android { 34 35static struct { 36 jmethodID deviceAvailable; 37 jmethodID deviceUnavailable; 38 jmethodID streamConfigsChanged; 39 jmethodID firstFrameCaptured; 40} gTvInputHalClassInfo; 41 42static struct { 43 jclass clazz; 44} gTvStreamConfigClassInfo; 45 46static struct { 47 jclass clazz; 48 49 jmethodID constructor; 50 jmethodID streamId; 51 jmethodID type; 52 jmethodID maxWidth; 53 jmethodID maxHeight; 54 jmethodID generation; 55 jmethodID build; 56} gTvStreamConfigBuilderClassInfo; 57 58static struct { 59 jclass clazz; 60 61 jmethodID constructor; 62 jmethodID deviceId; 63 jmethodID type; 64 jmethodID hdmiPortId; 65 jmethodID audioType; 66 jmethodID audioAddress; 67 jmethodID build; 68} gTvInputHardwareInfoBuilderClassInfo; 69 70//////////////////////////////////////////////////////////////////////////////// 71 72class BufferProducerThread : public Thread { 73public: 74 BufferProducerThread(tv_input_device_t* device, int deviceId, const tv_stream_t* stream); 75 76 virtual status_t readyToRun(); 77 78 void setSurface(const sp<Surface>& surface); 79 void onCaptured(uint32_t seq, bool succeeded); 80 void shutdown(); 81 82private: 83 Mutex mLock; 84 Condition mCondition; 85 sp<Surface> mSurface; 86 tv_input_device_t* mDevice; 87 int mDeviceId; 88 tv_stream_t mStream; 89 sp<ANativeWindowBuffer_t> mBuffer; 90 enum { 91 CAPTURING, 92 CAPTURED, 93 RELEASED, 94 } mBufferState; 95 uint32_t mSeq; 96 bool mShutdown; 97 98 virtual bool threadLoop(); 99 100 void setSurfaceLocked(const sp<Surface>& surface); 101}; 102 103BufferProducerThread::BufferProducerThread( 104 tv_input_device_t* device, int deviceId, const tv_stream_t* stream) 105 : Thread(false), 106 mDevice(device), 107 mDeviceId(deviceId), 108 mBuffer(NULL), 109 mBufferState(RELEASED), 110 mSeq(0u), 111 mShutdown(false) { 112 memcpy(&mStream, stream, sizeof(mStream)); 113} 114 115status_t BufferProducerThread::readyToRun() { 116 sp<ANativeWindow> anw(mSurface); 117 status_t err = native_window_set_usage(anw.get(), mStream.buffer_producer.usage); 118 if (err != NO_ERROR) { 119 return err; 120 } 121 err = native_window_set_buffers_dimensions( 122 anw.get(), mStream.buffer_producer.width, mStream.buffer_producer.height); 123 if (err != NO_ERROR) { 124 return err; 125 } 126 err = native_window_set_buffers_format(anw.get(), mStream.buffer_producer.format); 127 if (err != NO_ERROR) { 128 return err; 129 } 130 return NO_ERROR; 131} 132 133void BufferProducerThread::setSurface(const sp<Surface>& surface) { 134 Mutex::Autolock autoLock(&mLock); 135 setSurfaceLocked(surface); 136} 137 138void BufferProducerThread::setSurfaceLocked(const sp<Surface>& surface) { 139 if (surface == mSurface) { 140 return; 141 } 142 143 if (mBufferState == CAPTURING) { 144 mDevice->cancel_capture(mDevice, mDeviceId, mStream.stream_id, mSeq); 145 } 146 while (mBufferState == CAPTURING) { 147 status_t err = mCondition.waitRelative(mLock, s2ns(1)); 148 if (err != NO_ERROR) { 149 ALOGE("error %d while wating for buffer state to change.", err); 150 break; 151 } 152 } 153 mBuffer.clear(); 154 mBufferState = RELEASED; 155 156 mSurface = surface; 157 mCondition.broadcast(); 158} 159 160void BufferProducerThread::onCaptured(uint32_t seq, bool succeeded) { 161 Mutex::Autolock autoLock(&mLock); 162 if (seq != mSeq) { 163 ALOGW("Incorrect sequence value: expected %u actual %u", mSeq, seq); 164 } 165 if (mBufferState != CAPTURING) { 166 ALOGW("mBufferState != CAPTURING : instead %d", mBufferState); 167 } 168 if (succeeded) { 169 mBufferState = CAPTURED; 170 } else { 171 mBuffer.clear(); 172 mBufferState = RELEASED; 173 } 174 mCondition.broadcast(); 175} 176 177void BufferProducerThread::shutdown() { 178 Mutex::Autolock autoLock(&mLock); 179 mShutdown = true; 180 setSurfaceLocked(NULL); 181 requestExitAndWait(); 182} 183 184bool BufferProducerThread::threadLoop() { 185 Mutex::Autolock autoLock(&mLock); 186 187 status_t err = NO_ERROR; 188 if (mSurface == NULL) { 189 err = mCondition.waitRelative(mLock, s2ns(1)); 190 // It's OK to time out here. 191 if (err != NO_ERROR && err != TIMED_OUT) { 192 ALOGE("error %d while wating for non-null surface to be set", err); 193 return false; 194 } 195 return true; 196 } 197 sp<ANativeWindow> anw(mSurface); 198 while (mBufferState == CAPTURING) { 199 err = mCondition.waitRelative(mLock, s2ns(1)); 200 if (err != NO_ERROR) { 201 ALOGE("error %d while wating for buffer state to change.", err); 202 return false; 203 } 204 } 205 if (mBufferState == CAPTURED && anw != NULL) { 206 err = anw->queueBuffer(anw.get(), mBuffer.get(), -1); 207 if (err != NO_ERROR) { 208 ALOGE("error %d while queueing buffer to surface", err); 209 return false; 210 } 211 mBuffer.clear(); 212 mBufferState = RELEASED; 213 } 214 if (mBuffer == NULL && !mShutdown && anw != NULL) { 215 ANativeWindowBuffer_t* buffer = NULL; 216 err = native_window_dequeue_buffer_and_wait(anw.get(), &buffer); 217 if (err != NO_ERROR) { 218 ALOGE("error %d while dequeueing buffer to surface", err); 219 return false; 220 } 221 mBuffer = buffer; 222 mBufferState = CAPTURING; 223 mDevice->request_capture(mDevice, mDeviceId, mStream.stream_id, 224 buffer->handle, ++mSeq); 225 } 226 227 return true; 228} 229 230//////////////////////////////////////////////////////////////////////////////// 231 232class JTvInputHal { 233public: 234 ~JTvInputHal(); 235 236 static JTvInputHal* createInstance(JNIEnv* env, jobject thiz); 237 238 int addStream(int deviceId, int streamId, const sp<Surface>& surface); 239 int removeStream(int deviceId, int streamId); 240 const tv_stream_config_t* getStreamConfigs(int deviceId, int* numConfigs); 241 242private: 243 // Connection between a surface and a stream. 244 class Connection { 245 public: 246 Connection() {} 247 248 sp<Surface> mSurface; 249 tv_stream_type_t mStreamType; 250 251 // Only valid when mStreamType == TV_STREAM_TYPE_INDEPENDENT_VIDEO_SOURCE 252 sp<NativeHandle> mSourceHandle; 253 // Only valid when mStreamType == TV_STREAM_TYPE_BUFFER_PRODUCER 254 sp<BufferProducerThread> mThread; 255 }; 256 257 JTvInputHal(JNIEnv* env, jobject thiz, tv_input_device_t* dev); 258 259 static void notify( 260 tv_input_device_t* dev, tv_input_event_t* event, void* data); 261 262 void onDeviceAvailable(const tv_input_device_info_t& info); 263 void onDeviceUnavailable(int deviceId); 264 void onStreamConfigurationsChanged(int deviceId); 265 void onCaptured(int deviceId, int streamId, uint32_t seq, bool succeeded); 266 267 Mutex mLock; 268 jweak mThiz; 269 tv_input_device_t* mDevice; 270 tv_input_callback_ops_t mCallback; 271 272 KeyedVector<int, KeyedVector<int, Connection> > mConnections; 273}; 274 275JTvInputHal::JTvInputHal(JNIEnv* env, jobject thiz, tv_input_device_t* device) { 276 mThiz = env->NewWeakGlobalRef(thiz); 277 mDevice = device; 278 mCallback.notify = &JTvInputHal::notify; 279 280 mDevice->initialize(mDevice, &mCallback, this); 281} 282 283JTvInputHal::~JTvInputHal() { 284 mDevice->common.close((hw_device_t*)mDevice); 285 286 JNIEnv* env = AndroidRuntime::getJNIEnv(); 287 env->DeleteWeakGlobalRef(mThiz); 288 mThiz = NULL; 289} 290 291JTvInputHal* JTvInputHal::createInstance(JNIEnv* env, jobject thiz) { 292 tv_input_module_t* module = NULL; 293 status_t err = hw_get_module(TV_INPUT_HARDWARE_MODULE_ID, 294 (hw_module_t const**)&module); 295 if (err) { 296 ALOGE("Couldn't load %s module (%s)", 297 TV_INPUT_HARDWARE_MODULE_ID, strerror(-err)); 298 return 0; 299 } 300 301 tv_input_device_t* device = NULL; 302 err = module->common.methods->open( 303 (hw_module_t*)module, 304 TV_INPUT_DEFAULT_DEVICE, 305 (hw_device_t**)&device); 306 if (err) { 307 ALOGE("Couldn't open %s device (%s)", 308 TV_INPUT_DEFAULT_DEVICE, strerror(-err)); 309 return 0; 310 } 311 312 return new JTvInputHal(env, thiz, device); 313} 314 315int JTvInputHal::addStream(int deviceId, int streamId, const sp<Surface>& surface) { 316 KeyedVector<int, Connection>& connections = mConnections.editValueFor(deviceId); 317 if (connections.indexOfKey(streamId) < 0) { 318 connections.add(streamId, Connection()); 319 } 320 Connection& connection = connections.editValueFor(streamId); 321 if (connection.mSurface == surface) { 322 // Nothing to do 323 return NO_ERROR; 324 } 325 // Clear the surface in the connection. 326 if (connection.mSurface != NULL) { 327 if (connection.mStreamType == TV_STREAM_TYPE_INDEPENDENT_VIDEO_SOURCE) { 328 if (Surface::isValid(connection.mSurface)) { 329 connection.mSurface->setSidebandStream(NULL); 330 } 331 } 332 connection.mSurface.clear(); 333 } 334 if (connection.mSourceHandle == NULL && connection.mThread == NULL) { 335 // Need to configure stream 336 int numConfigs = 0; 337 const tv_stream_config_t* configs = NULL; 338 if (mDevice->get_stream_configurations( 339 mDevice, deviceId, &numConfigs, &configs) != 0) { 340 ALOGE("Couldn't get stream configs"); 341 return UNKNOWN_ERROR; 342 } 343 int configIndex = -1; 344 for (int i = 0; i < numConfigs; ++i) { 345 if (configs[i].stream_id == streamId) { 346 configIndex = i; 347 break; 348 } 349 } 350 if (configIndex == -1) { 351 ALOGE("Cannot find a config with given stream ID: %d", streamId); 352 return BAD_VALUE; 353 } 354 connection.mStreamType = configs[configIndex].type; 355 356 tv_stream_t stream; 357 stream.stream_id = configs[configIndex].stream_id; 358 if (connection.mStreamType == TV_STREAM_TYPE_BUFFER_PRODUCER) { 359 stream.buffer_producer.width = configs[configIndex].max_video_width; 360 stream.buffer_producer.height = configs[configIndex].max_video_height; 361 } 362 if (mDevice->open_stream(mDevice, deviceId, &stream) != 0) { 363 ALOGE("Couldn't add stream"); 364 return UNKNOWN_ERROR; 365 } 366 if (connection.mStreamType == TV_STREAM_TYPE_INDEPENDENT_VIDEO_SOURCE) { 367 connection.mSourceHandle = NativeHandle::create( 368 stream.sideband_stream_source_handle, false); 369 } else if (connection.mStreamType == TV_STREAM_TYPE_BUFFER_PRODUCER) { 370 if (connection.mThread != NULL) { 371 connection.mThread->shutdown(); 372 } 373 connection.mThread = new BufferProducerThread(mDevice, deviceId, &stream); 374 connection.mThread->run(); 375 } 376 } 377 connection.mSurface = surface; 378 if (connection.mStreamType == TV_STREAM_TYPE_INDEPENDENT_VIDEO_SOURCE) { 379 connection.mSurface->setSidebandStream(connection.mSourceHandle); 380 } else if (connection.mStreamType == TV_STREAM_TYPE_BUFFER_PRODUCER) { 381 connection.mThread->setSurface(surface); 382 } 383 return NO_ERROR; 384} 385 386int JTvInputHal::removeStream(int deviceId, int streamId) { 387 KeyedVector<int, Connection>& connections = mConnections.editValueFor(deviceId); 388 if (connections.indexOfKey(streamId) < 0) { 389 return BAD_VALUE; 390 } 391 Connection& connection = connections.editValueFor(streamId); 392 if (connection.mSurface == NULL) { 393 // Nothing to do 394 return NO_ERROR; 395 } 396 if (Surface::isValid(connection.mSurface)) { 397 connection.mSurface.clear(); 398 } 399 if (connection.mSurface != NULL) { 400 connection.mSurface->setSidebandStream(NULL); 401 connection.mSurface.clear(); 402 } 403 if (connection.mThread != NULL) { 404 connection.mThread->shutdown(); 405 connection.mThread.clear(); 406 } 407 if (mDevice->close_stream(mDevice, deviceId, streamId) != 0) { 408 ALOGE("Couldn't remove stream"); 409 return BAD_VALUE; 410 } 411 if (connection.mSourceHandle != NULL) { 412 connection.mSourceHandle.clear(); 413 } 414 return NO_ERROR; 415} 416 417const tv_stream_config_t* JTvInputHal::getStreamConfigs(int deviceId, int* numConfigs) { 418 const tv_stream_config_t* configs = NULL; 419 if (mDevice->get_stream_configurations( 420 mDevice, deviceId, numConfigs, &configs) != 0) { 421 ALOGE("Couldn't get stream configs"); 422 return NULL; 423 } 424 return configs; 425} 426 427// static 428void JTvInputHal::notify( 429 tv_input_device_t* dev, tv_input_event_t* event, void* data) { 430 JTvInputHal* thiz = (JTvInputHal*)data; 431 switch (event->type) { 432 case TV_INPUT_EVENT_DEVICE_AVAILABLE: { 433 thiz->onDeviceAvailable(event->device_info); 434 } break; 435 case TV_INPUT_EVENT_DEVICE_UNAVAILABLE: { 436 thiz->onDeviceUnavailable(event->device_info.device_id); 437 } break; 438 case TV_INPUT_EVENT_STREAM_CONFIGURATIONS_CHANGED: { 439 thiz->onStreamConfigurationsChanged(event->device_info.device_id); 440 } break; 441 case TV_INPUT_EVENT_CAPTURE_SUCCEEDED: { 442 thiz->onCaptured(event->capture_result.device_id, 443 event->capture_result.stream_id, 444 event->capture_result.seq, 445 true /* succeeded */); 446 } break; 447 case TV_INPUT_EVENT_CAPTURE_FAILED: { 448 thiz->onCaptured(event->capture_result.device_id, 449 event->capture_result.stream_id, 450 event->capture_result.seq, 451 false /* succeeded */); 452 } break; 453 default: 454 ALOGE("Unrecognizable event"); 455 } 456} 457 458void JTvInputHal::onDeviceAvailable(const tv_input_device_info_t& info) { 459 { 460 Mutex::Autolock autoLock(&mLock); 461 mConnections.add(info.device_id, KeyedVector<int, Connection>()); 462 } 463 JNIEnv* env = AndroidRuntime::getJNIEnv(); 464 465 jobject builder = env->NewObject( 466 gTvInputHardwareInfoBuilderClassInfo.clazz, 467 gTvInputHardwareInfoBuilderClassInfo.constructor); 468 env->CallObjectMethod( 469 builder, gTvInputHardwareInfoBuilderClassInfo.deviceId, info.device_id); 470 env->CallObjectMethod( 471 builder, gTvInputHardwareInfoBuilderClassInfo.type, info.type); 472 if (info.type == TV_INPUT_TYPE_HDMI) { 473 env->CallObjectMethod( 474 builder, gTvInputHardwareInfoBuilderClassInfo.hdmiPortId, info.hdmi.port_id); 475 } 476 env->CallObjectMethod( 477 builder, gTvInputHardwareInfoBuilderClassInfo.audioType, info.audio_type); 478 if (info.audio_type != AUDIO_DEVICE_NONE) { 479 jstring audioAddress = env->NewStringUTF(info.audio_address); 480 env->CallObjectMethod( 481 builder, gTvInputHardwareInfoBuilderClassInfo.audioAddress, audioAddress); 482 env->DeleteLocalRef(audioAddress); 483 } 484 485 jobject infoObject = env->CallObjectMethod(builder, gTvInputHardwareInfoBuilderClassInfo.build); 486 487 env->CallVoidMethod( 488 mThiz, 489 gTvInputHalClassInfo.deviceAvailable, 490 infoObject); 491 492 env->DeleteLocalRef(builder); 493 env->DeleteLocalRef(infoObject); 494} 495 496void JTvInputHal::onDeviceUnavailable(int deviceId) { 497 { 498 Mutex::Autolock autoLock(&mLock); 499 KeyedVector<int, Connection>& connections = mConnections.editValueFor(deviceId); 500 for (size_t i = 0; i < connections.size(); ++i) { 501 removeStream(deviceId, connections.keyAt(i)); 502 } 503 connections.clear(); 504 mConnections.removeItem(deviceId); 505 } 506 JNIEnv* env = AndroidRuntime::getJNIEnv(); 507 env->CallVoidMethod( 508 mThiz, 509 gTvInputHalClassInfo.deviceUnavailable, 510 deviceId); 511} 512 513void JTvInputHal::onStreamConfigurationsChanged(int deviceId) { 514 { 515 Mutex::Autolock autoLock(&mLock); 516 KeyedVector<int, Connection>& connections = mConnections.editValueFor(deviceId); 517 for (size_t i = 0; i < connections.size(); ++i) { 518 removeStream(deviceId, connections.keyAt(i)); 519 } 520 connections.clear(); 521 } 522 JNIEnv* env = AndroidRuntime::getJNIEnv(); 523 env->CallVoidMethod( 524 mThiz, 525 gTvInputHalClassInfo.streamConfigsChanged, 526 deviceId); 527} 528 529void JTvInputHal::onCaptured(int deviceId, int streamId, uint32_t seq, bool succeeded) { 530 sp<BufferProducerThread> thread; 531 { 532 Mutex::Autolock autoLock(&mLock); 533 KeyedVector<int, Connection>& connections = mConnections.editValueFor(deviceId); 534 Connection& connection = connections.editValueFor(streamId); 535 if (connection.mThread == NULL) { 536 ALOGE("capture thread not existing."); 537 return; 538 } 539 thread = connection.mThread; 540 } 541 thread->onCaptured(seq, succeeded); 542 if (seq == 0) { 543 JNIEnv* env = AndroidRuntime::getJNIEnv(); 544 env->CallVoidMethod( 545 mThiz, 546 gTvInputHalClassInfo.firstFrameCaptured, 547 deviceId, 548 streamId); 549 } 550} 551 552//////////////////////////////////////////////////////////////////////////////// 553 554static jlong nativeOpen(JNIEnv* env, jobject thiz) { 555 return (jlong)JTvInputHal::createInstance(env, thiz); 556} 557 558static int nativeAddStream(JNIEnv* env, jclass clazz, 559 jlong ptr, jint deviceId, jint streamId, jobject jsurface) { 560 JTvInputHal* tvInputHal = (JTvInputHal*)ptr; 561 if (!jsurface) { 562 return BAD_VALUE; 563 } 564 sp<Surface> surface(android_view_Surface_getSurface(env, jsurface)); 565 return tvInputHal->addStream(deviceId, streamId, surface); 566} 567 568static int nativeRemoveStream(JNIEnv* env, jclass clazz, 569 jlong ptr, jint deviceId, jint streamId) { 570 JTvInputHal* tvInputHal = (JTvInputHal*)ptr; 571 return tvInputHal->removeStream(deviceId, streamId); 572} 573 574static jobjectArray nativeGetStreamConfigs(JNIEnv* env, jclass clazz, 575 jlong ptr, jint deviceId, jint generation) { 576 JTvInputHal* tvInputHal = (JTvInputHal*)ptr; 577 int numConfigs = 0; 578 const tv_stream_config_t* configs = tvInputHal->getStreamConfigs(deviceId, &numConfigs); 579 580 jobjectArray result = env->NewObjectArray(numConfigs, gTvStreamConfigClassInfo.clazz, NULL); 581 for (int i = 0; i < numConfigs; ++i) { 582 jobject builder = env->NewObject( 583 gTvStreamConfigBuilderClassInfo.clazz, 584 gTvStreamConfigBuilderClassInfo.constructor); 585 env->CallObjectMethod( 586 builder, gTvStreamConfigBuilderClassInfo.streamId, configs[i].stream_id); 587 env->CallObjectMethod( 588 builder, gTvStreamConfigBuilderClassInfo.type, configs[i].type); 589 env->CallObjectMethod( 590 builder, gTvStreamConfigBuilderClassInfo.maxWidth, configs[i].max_video_width); 591 env->CallObjectMethod( 592 builder, gTvStreamConfigBuilderClassInfo.maxHeight, configs[i].max_video_height); 593 env->CallObjectMethod( 594 builder, gTvStreamConfigBuilderClassInfo.generation, generation); 595 596 jobject config = env->CallObjectMethod(builder, gTvStreamConfigBuilderClassInfo.build); 597 598 env->SetObjectArrayElement(result, i, config); 599 600 env->DeleteLocalRef(config); 601 env->DeleteLocalRef(builder); 602 } 603 return result; 604} 605 606static void nativeClose(JNIEnv* env, jclass clazz, jlong ptr) { 607 JTvInputHal* tvInputHal = (JTvInputHal*)ptr; 608 delete tvInputHal; 609} 610 611static JNINativeMethod gTvInputHalMethods[] = { 612 /* name, signature, funcPtr */ 613 { "nativeOpen", "()J", 614 (void*) nativeOpen }, 615 { "nativeAddStream", "(JIILandroid/view/Surface;)I", 616 (void*) nativeAddStream }, 617 { "nativeRemoveStream", "(JII)I", 618 (void*) nativeRemoveStream }, 619 { "nativeGetStreamConfigs", "(JII)[Landroid/media/tv/TvStreamConfig;", 620 (void*) nativeGetStreamConfigs }, 621 { "nativeClose", "(J)V", 622 (void*) nativeClose }, 623}; 624 625#define FIND_CLASS(var, className) \ 626 var = env->FindClass(className); \ 627 LOG_FATAL_IF(! var, "Unable to find class " className) 628 629#define GET_METHOD_ID(var, clazz, methodName, fieldDescriptor) \ 630 var = env->GetMethodID(clazz, methodName, fieldDescriptor); \ 631 LOG_FATAL_IF(! var, "Unable to find method" methodName) 632 633int register_android_server_tv_TvInputHal(JNIEnv* env) { 634 int res = jniRegisterNativeMethods(env, "com/android/server/tv/TvInputHal", 635 gTvInputHalMethods, NELEM(gTvInputHalMethods)); 636 LOG_FATAL_IF(res < 0, "Unable to register native methods."); 637 638 jclass clazz; 639 FIND_CLASS(clazz, "com/android/server/tv/TvInputHal"); 640 641 GET_METHOD_ID( 642 gTvInputHalClassInfo.deviceAvailable, clazz, 643 "deviceAvailableFromNative", "(Landroid/media/tv/TvInputHardwareInfo;)V"); 644 GET_METHOD_ID( 645 gTvInputHalClassInfo.deviceUnavailable, clazz, "deviceUnavailableFromNative", "(I)V"); 646 GET_METHOD_ID( 647 gTvInputHalClassInfo.streamConfigsChanged, clazz, 648 "streamConfigsChangedFromNative", "(I)V"); 649 GET_METHOD_ID( 650 gTvInputHalClassInfo.firstFrameCaptured, clazz, 651 "firstFrameCapturedFromNative", "(II)V"); 652 653 FIND_CLASS(gTvStreamConfigClassInfo.clazz, "android/media/tv/TvStreamConfig"); 654 gTvStreamConfigClassInfo.clazz = jclass(env->NewGlobalRef(gTvStreamConfigClassInfo.clazz)); 655 656 FIND_CLASS(gTvStreamConfigBuilderClassInfo.clazz, "android/media/tv/TvStreamConfig$Builder"); 657 gTvStreamConfigBuilderClassInfo.clazz = 658 jclass(env->NewGlobalRef(gTvStreamConfigBuilderClassInfo.clazz)); 659 660 GET_METHOD_ID( 661 gTvStreamConfigBuilderClassInfo.constructor, 662 gTvStreamConfigBuilderClassInfo.clazz, 663 "<init>", "()V"); 664 GET_METHOD_ID( 665 gTvStreamConfigBuilderClassInfo.streamId, 666 gTvStreamConfigBuilderClassInfo.clazz, 667 "streamId", "(I)Landroid/media/tv/TvStreamConfig$Builder;"); 668 GET_METHOD_ID( 669 gTvStreamConfigBuilderClassInfo.type, 670 gTvStreamConfigBuilderClassInfo.clazz, 671 "type", "(I)Landroid/media/tv/TvStreamConfig$Builder;"); 672 GET_METHOD_ID( 673 gTvStreamConfigBuilderClassInfo.maxWidth, 674 gTvStreamConfigBuilderClassInfo.clazz, 675 "maxWidth", "(I)Landroid/media/tv/TvStreamConfig$Builder;"); 676 GET_METHOD_ID( 677 gTvStreamConfigBuilderClassInfo.maxHeight, 678 gTvStreamConfigBuilderClassInfo.clazz, 679 "maxHeight", "(I)Landroid/media/tv/TvStreamConfig$Builder;"); 680 GET_METHOD_ID( 681 gTvStreamConfigBuilderClassInfo.generation, 682 gTvStreamConfigBuilderClassInfo.clazz, 683 "generation", "(I)Landroid/media/tv/TvStreamConfig$Builder;"); 684 GET_METHOD_ID( 685 gTvStreamConfigBuilderClassInfo.build, 686 gTvStreamConfigBuilderClassInfo.clazz, 687 "build", "()Landroid/media/tv/TvStreamConfig;"); 688 689 FIND_CLASS(gTvInputHardwareInfoBuilderClassInfo.clazz, 690 "android/media/tv/TvInputHardwareInfo$Builder"); 691 gTvInputHardwareInfoBuilderClassInfo.clazz = 692 jclass(env->NewGlobalRef(gTvInputHardwareInfoBuilderClassInfo.clazz)); 693 694 GET_METHOD_ID( 695 gTvInputHardwareInfoBuilderClassInfo.constructor, 696 gTvInputHardwareInfoBuilderClassInfo.clazz, 697 "<init>", "()V"); 698 GET_METHOD_ID( 699 gTvInputHardwareInfoBuilderClassInfo.deviceId, 700 gTvInputHardwareInfoBuilderClassInfo.clazz, 701 "deviceId", "(I)Landroid/media/tv/TvInputHardwareInfo$Builder;"); 702 GET_METHOD_ID( 703 gTvInputHardwareInfoBuilderClassInfo.type, 704 gTvInputHardwareInfoBuilderClassInfo.clazz, 705 "type", "(I)Landroid/media/tv/TvInputHardwareInfo$Builder;"); 706 GET_METHOD_ID( 707 gTvInputHardwareInfoBuilderClassInfo.hdmiPortId, 708 gTvInputHardwareInfoBuilderClassInfo.clazz, 709 "hdmiPortId", "(I)Landroid/media/tv/TvInputHardwareInfo$Builder;"); 710 GET_METHOD_ID( 711 gTvInputHardwareInfoBuilderClassInfo.audioType, 712 gTvInputHardwareInfoBuilderClassInfo.clazz, 713 "audioType", "(I)Landroid/media/tv/TvInputHardwareInfo$Builder;"); 714 GET_METHOD_ID( 715 gTvInputHardwareInfoBuilderClassInfo.audioAddress, 716 gTvInputHardwareInfoBuilderClassInfo.clazz, 717 "audioAddress", "(Ljava/lang/String;)Landroid/media/tv/TvInputHardwareInfo$Builder;"); 718 GET_METHOD_ID( 719 gTvInputHardwareInfoBuilderClassInfo.build, 720 gTvInputHardwareInfoBuilderClassInfo.clazz, 721 "build", "()Landroid/media/tv/TvInputHardwareInfo;"); 722 723 return 0; 724} 725 726} /* namespace android */ 727