com_android_server_tv_TvInputHal.cpp revision 21aa3467cd14260418cc47334b656adf841a567c
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.mSourceHandle != NULL) { 404 // Need to reset streams 405 if (mDevice->close_stream(mDevice, deviceId, streamId) != 0) { 406 ALOGE("Couldn't remove stream"); 407 return BAD_VALUE; 408 } 409 410 // Clear everything 411 if (connection.mThread != NULL) { 412 connection.mThread->shutdown(); 413 connection.mThread.clear(); 414 } 415 connection.mSourceHandle.clear(); 416 } 417 return NO_ERROR; 418} 419 420const tv_stream_config_t* JTvInputHal::getStreamConfigs(int deviceId, int* numConfigs) { 421 const tv_stream_config_t* configs = NULL; 422 if (mDevice->get_stream_configurations( 423 mDevice, deviceId, numConfigs, &configs) != 0) { 424 ALOGE("Couldn't get stream configs"); 425 return NULL; 426 } 427 return configs; 428} 429 430// static 431void JTvInputHal::notify( 432 tv_input_device_t* dev, tv_input_event_t* event, void* data) { 433 JTvInputHal* thiz = (JTvInputHal*)data; 434 switch (event->type) { 435 case TV_INPUT_EVENT_DEVICE_AVAILABLE: { 436 thiz->onDeviceAvailable(event->device_info); 437 } break; 438 case TV_INPUT_EVENT_DEVICE_UNAVAILABLE: { 439 thiz->onDeviceUnavailable(event->device_info.device_id); 440 } break; 441 case TV_INPUT_EVENT_STREAM_CONFIGURATIONS_CHANGED: { 442 thiz->onStreamConfigurationsChanged(event->device_info.device_id); 443 } break; 444 case TV_INPUT_EVENT_CAPTURE_SUCCEEDED: { 445 thiz->onCaptured(event->capture_result.device_id, 446 event->capture_result.stream_id, 447 event->capture_result.seq, 448 true /* succeeded */); 449 } break; 450 case TV_INPUT_EVENT_CAPTURE_FAILED: { 451 thiz->onCaptured(event->capture_result.device_id, 452 event->capture_result.stream_id, 453 event->capture_result.seq, 454 false /* succeeded */); 455 } break; 456 default: 457 ALOGE("Unrecognizable event"); 458 } 459} 460 461void JTvInputHal::onDeviceAvailable(const tv_input_device_info_t& info) { 462 { 463 Mutex::Autolock autoLock(&mLock); 464 mConnections.add(info.device_id, KeyedVector<int, Connection>()); 465 } 466 JNIEnv* env = AndroidRuntime::getJNIEnv(); 467 468 jobject builder = env->NewObject( 469 gTvInputHardwareInfoBuilderClassInfo.clazz, 470 gTvInputHardwareInfoBuilderClassInfo.constructor); 471 env->CallObjectMethod( 472 builder, gTvInputHardwareInfoBuilderClassInfo.deviceId, info.device_id); 473 env->CallObjectMethod( 474 builder, gTvInputHardwareInfoBuilderClassInfo.type, info.type); 475 if (info.type == TV_INPUT_TYPE_HDMI) { 476 env->CallObjectMethod( 477 builder, gTvInputHardwareInfoBuilderClassInfo.hdmiPortId, info.hdmi.port_id); 478 } 479 env->CallObjectMethod( 480 builder, gTvInputHardwareInfoBuilderClassInfo.audioType, info.audio_type); 481 if (info.audio_type != AUDIO_DEVICE_NONE) { 482 jstring audioAddress = env->NewStringUTF(info.audio_address); 483 env->CallObjectMethod( 484 builder, gTvInputHardwareInfoBuilderClassInfo.audioAddress, audioAddress); 485 env->DeleteLocalRef(audioAddress); 486 } 487 488 jobject infoObject = env->CallObjectMethod(builder, gTvInputHardwareInfoBuilderClassInfo.build); 489 490 env->CallVoidMethod( 491 mThiz, 492 gTvInputHalClassInfo.deviceAvailable, 493 infoObject); 494 495 env->DeleteLocalRef(builder); 496 env->DeleteLocalRef(infoObject); 497} 498 499void JTvInputHal::onDeviceUnavailable(int deviceId) { 500 { 501 Mutex::Autolock autoLock(&mLock); 502 KeyedVector<int, Connection>& connections = mConnections.editValueFor(deviceId); 503 for (size_t i = 0; i < connections.size(); ++i) { 504 removeStream(deviceId, connections.keyAt(i)); 505 } 506 connections.clear(); 507 mConnections.removeItem(deviceId); 508 } 509 JNIEnv* env = AndroidRuntime::getJNIEnv(); 510 env->CallVoidMethod( 511 mThiz, 512 gTvInputHalClassInfo.deviceUnavailable, 513 deviceId); 514} 515 516void JTvInputHal::onStreamConfigurationsChanged(int deviceId) { 517 { 518 Mutex::Autolock autoLock(&mLock); 519 KeyedVector<int, Connection>& connections = mConnections.editValueFor(deviceId); 520 for (size_t i = 0; i < connections.size(); ++i) { 521 removeStream(deviceId, connections.keyAt(i)); 522 } 523 connections.clear(); 524 } 525 JNIEnv* env = AndroidRuntime::getJNIEnv(); 526 env->CallVoidMethod( 527 mThiz, 528 gTvInputHalClassInfo.streamConfigsChanged, 529 deviceId); 530} 531 532void JTvInputHal::onCaptured(int deviceId, int streamId, uint32_t seq, bool succeeded) { 533 sp<BufferProducerThread> thread; 534 { 535 Mutex::Autolock autoLock(&mLock); 536 KeyedVector<int, Connection>& connections = mConnections.editValueFor(deviceId); 537 Connection& connection = connections.editValueFor(streamId); 538 if (connection.mThread == NULL) { 539 ALOGE("capture thread not existing."); 540 return; 541 } 542 thread = connection.mThread; 543 } 544 thread->onCaptured(seq, succeeded); 545 if (seq == 0) { 546 JNIEnv* env = AndroidRuntime::getJNIEnv(); 547 env->CallVoidMethod( 548 mThiz, 549 gTvInputHalClassInfo.firstFrameCaptured, 550 deviceId, 551 streamId); 552 } 553} 554 555//////////////////////////////////////////////////////////////////////////////// 556 557static jlong nativeOpen(JNIEnv* env, jobject thiz) { 558 return (jlong)JTvInputHal::createInstance(env, thiz); 559} 560 561static int nativeAddStream(JNIEnv* env, jclass clazz, 562 jlong ptr, jint deviceId, jint streamId, jobject jsurface) { 563 JTvInputHal* tvInputHal = (JTvInputHal*)ptr; 564 if (!jsurface) { 565 return BAD_VALUE; 566 } 567 sp<Surface> surface(android_view_Surface_getSurface(env, jsurface)); 568 return tvInputHal->addStream(deviceId, streamId, surface); 569} 570 571static int nativeRemoveStream(JNIEnv* env, jclass clazz, 572 jlong ptr, jint deviceId, jint streamId) { 573 JTvInputHal* tvInputHal = (JTvInputHal*)ptr; 574 return tvInputHal->removeStream(deviceId, streamId); 575} 576 577static jobjectArray nativeGetStreamConfigs(JNIEnv* env, jclass clazz, 578 jlong ptr, jint deviceId, jint generation) { 579 JTvInputHal* tvInputHal = (JTvInputHal*)ptr; 580 int numConfigs = 0; 581 const tv_stream_config_t* configs = tvInputHal->getStreamConfigs(deviceId, &numConfigs); 582 583 jobjectArray result = env->NewObjectArray(numConfigs, gTvStreamConfigClassInfo.clazz, NULL); 584 for (int i = 0; i < numConfigs; ++i) { 585 jobject builder = env->NewObject( 586 gTvStreamConfigBuilderClassInfo.clazz, 587 gTvStreamConfigBuilderClassInfo.constructor); 588 env->CallObjectMethod( 589 builder, gTvStreamConfigBuilderClassInfo.streamId, configs[i].stream_id); 590 env->CallObjectMethod( 591 builder, gTvStreamConfigBuilderClassInfo.type, configs[i].type); 592 env->CallObjectMethod( 593 builder, gTvStreamConfigBuilderClassInfo.maxWidth, configs[i].max_video_width); 594 env->CallObjectMethod( 595 builder, gTvStreamConfigBuilderClassInfo.maxHeight, configs[i].max_video_height); 596 env->CallObjectMethod( 597 builder, gTvStreamConfigBuilderClassInfo.generation, generation); 598 599 jobject config = env->CallObjectMethod(builder, gTvStreamConfigBuilderClassInfo.build); 600 601 env->SetObjectArrayElement(result, i, config); 602 603 env->DeleteLocalRef(config); 604 env->DeleteLocalRef(builder); 605 } 606 return result; 607} 608 609static void nativeClose(JNIEnv* env, jclass clazz, jlong ptr) { 610 JTvInputHal* tvInputHal = (JTvInputHal*)ptr; 611 delete tvInputHal; 612} 613 614static JNINativeMethod gTvInputHalMethods[] = { 615 /* name, signature, funcPtr */ 616 { "nativeOpen", "()J", 617 (void*) nativeOpen }, 618 { "nativeAddStream", "(JIILandroid/view/Surface;)I", 619 (void*) nativeAddStream }, 620 { "nativeRemoveStream", "(JII)I", 621 (void*) nativeRemoveStream }, 622 { "nativeGetStreamConfigs", "(JII)[Landroid/media/tv/TvStreamConfig;", 623 (void*) nativeGetStreamConfigs }, 624 { "nativeClose", "(J)V", 625 (void*) nativeClose }, 626}; 627 628#define FIND_CLASS(var, className) \ 629 var = env->FindClass(className); \ 630 LOG_FATAL_IF(! var, "Unable to find class " className) 631 632#define GET_METHOD_ID(var, clazz, methodName, fieldDescriptor) \ 633 var = env->GetMethodID(clazz, methodName, fieldDescriptor); \ 634 LOG_FATAL_IF(! var, "Unable to find method" methodName) 635 636int register_android_server_tv_TvInputHal(JNIEnv* env) { 637 int res = jniRegisterNativeMethods(env, "com/android/server/tv/TvInputHal", 638 gTvInputHalMethods, NELEM(gTvInputHalMethods)); 639 LOG_FATAL_IF(res < 0, "Unable to register native methods."); 640 641 jclass clazz; 642 FIND_CLASS(clazz, "com/android/server/tv/TvInputHal"); 643 644 GET_METHOD_ID( 645 gTvInputHalClassInfo.deviceAvailable, clazz, 646 "deviceAvailableFromNative", "(Landroid/media/tv/TvInputHardwareInfo;)V"); 647 GET_METHOD_ID( 648 gTvInputHalClassInfo.deviceUnavailable, clazz, "deviceUnavailableFromNative", "(I)V"); 649 GET_METHOD_ID( 650 gTvInputHalClassInfo.streamConfigsChanged, clazz, 651 "streamConfigsChangedFromNative", "(I)V"); 652 GET_METHOD_ID( 653 gTvInputHalClassInfo.firstFrameCaptured, clazz, 654 "firstFrameCapturedFromNative", "(II)V"); 655 656 FIND_CLASS(gTvStreamConfigClassInfo.clazz, "android/media/tv/TvStreamConfig"); 657 gTvStreamConfigClassInfo.clazz = jclass(env->NewGlobalRef(gTvStreamConfigClassInfo.clazz)); 658 659 FIND_CLASS(gTvStreamConfigBuilderClassInfo.clazz, "android/media/tv/TvStreamConfig$Builder"); 660 gTvStreamConfigBuilderClassInfo.clazz = 661 jclass(env->NewGlobalRef(gTvStreamConfigBuilderClassInfo.clazz)); 662 663 GET_METHOD_ID( 664 gTvStreamConfigBuilderClassInfo.constructor, 665 gTvStreamConfigBuilderClassInfo.clazz, 666 "<init>", "()V"); 667 GET_METHOD_ID( 668 gTvStreamConfigBuilderClassInfo.streamId, 669 gTvStreamConfigBuilderClassInfo.clazz, 670 "streamId", "(I)Landroid/media/tv/TvStreamConfig$Builder;"); 671 GET_METHOD_ID( 672 gTvStreamConfigBuilderClassInfo.type, 673 gTvStreamConfigBuilderClassInfo.clazz, 674 "type", "(I)Landroid/media/tv/TvStreamConfig$Builder;"); 675 GET_METHOD_ID( 676 gTvStreamConfigBuilderClassInfo.maxWidth, 677 gTvStreamConfigBuilderClassInfo.clazz, 678 "maxWidth", "(I)Landroid/media/tv/TvStreamConfig$Builder;"); 679 GET_METHOD_ID( 680 gTvStreamConfigBuilderClassInfo.maxHeight, 681 gTvStreamConfigBuilderClassInfo.clazz, 682 "maxHeight", "(I)Landroid/media/tv/TvStreamConfig$Builder;"); 683 GET_METHOD_ID( 684 gTvStreamConfigBuilderClassInfo.generation, 685 gTvStreamConfigBuilderClassInfo.clazz, 686 "generation", "(I)Landroid/media/tv/TvStreamConfig$Builder;"); 687 GET_METHOD_ID( 688 gTvStreamConfigBuilderClassInfo.build, 689 gTvStreamConfigBuilderClassInfo.clazz, 690 "build", "()Landroid/media/tv/TvStreamConfig;"); 691 692 FIND_CLASS(gTvInputHardwareInfoBuilderClassInfo.clazz, 693 "android/media/tv/TvInputHardwareInfo$Builder"); 694 gTvInputHardwareInfoBuilderClassInfo.clazz = 695 jclass(env->NewGlobalRef(gTvInputHardwareInfoBuilderClassInfo.clazz)); 696 697 GET_METHOD_ID( 698 gTvInputHardwareInfoBuilderClassInfo.constructor, 699 gTvInputHardwareInfoBuilderClassInfo.clazz, 700 "<init>", "()V"); 701 GET_METHOD_ID( 702 gTvInputHardwareInfoBuilderClassInfo.deviceId, 703 gTvInputHardwareInfoBuilderClassInfo.clazz, 704 "deviceId", "(I)Landroid/media/tv/TvInputHardwareInfo$Builder;"); 705 GET_METHOD_ID( 706 gTvInputHardwareInfoBuilderClassInfo.type, 707 gTvInputHardwareInfoBuilderClassInfo.clazz, 708 "type", "(I)Landroid/media/tv/TvInputHardwareInfo$Builder;"); 709 GET_METHOD_ID( 710 gTvInputHardwareInfoBuilderClassInfo.hdmiPortId, 711 gTvInputHardwareInfoBuilderClassInfo.clazz, 712 "hdmiPortId", "(I)Landroid/media/tv/TvInputHardwareInfo$Builder;"); 713 GET_METHOD_ID( 714 gTvInputHardwareInfoBuilderClassInfo.audioType, 715 gTvInputHardwareInfoBuilderClassInfo.clazz, 716 "audioType", "(I)Landroid/media/tv/TvInputHardwareInfo$Builder;"); 717 GET_METHOD_ID( 718 gTvInputHardwareInfoBuilderClassInfo.audioAddress, 719 gTvInputHardwareInfoBuilderClassInfo.clazz, 720 "audioAddress", "(Ljava/lang/String;)Landroid/media/tv/TvInputHardwareInfo$Builder;"); 721 GET_METHOD_ID( 722 gTvInputHardwareInfoBuilderClassInfo.build, 723 gTvInputHardwareInfoBuilderClassInfo.clazz, 724 "build", "()Landroid/media/tv/TvInputHardwareInfo;"); 725 726 return 0; 727} 728 729} /* namespace android */ 730