com_android_server_tv_TvInputHal.cpp revision 0b2691b6873f9d328884c5a9e5ab1fe308f3ee36
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} gTvInputHalClassInfo; 40 41static struct { 42 jclass clazz; 43} gTvStreamConfigClassInfo; 44 45static struct { 46 jclass clazz; 47 48 jmethodID constructor; 49 jmethodID streamId; 50 jmethodID type; 51 jmethodID maxWidth; 52 jmethodID maxHeight; 53 jmethodID generation; 54 jmethodID build; 55} gTvStreamConfigBuilderClassInfo; 56 57static struct { 58 jclass clazz; 59 60 jmethodID constructor; 61 jmethodID deviceId; 62 jmethodID type; 63 jmethodID hdmiPortId; 64 jmethodID audioType; 65 jmethodID audioAddress; 66 jmethodID build; 67} gTvInputHardwareInfoBuilderClassInfo; 68 69//////////////////////////////////////////////////////////////////////////////// 70 71class BufferProducerThread : public Thread { 72public: 73 BufferProducerThread(tv_input_device_t* device, int deviceId, const tv_stream_t* stream); 74 75 virtual status_t readyToRun(); 76 77 void setSurface(const sp<Surface>& surface); 78 void onCaptured(uint32_t seq, bool succeeded); 79 void shutdown(); 80 81private: 82 Mutex mLock; 83 Condition mCondition; 84 sp<Surface> mSurface; 85 tv_input_device_t* mDevice; 86 int mDeviceId; 87 tv_stream_t mStream; 88 sp<ANativeWindowBuffer_t> mBuffer; 89 enum { 90 CAPTURING, 91 CAPTURED, 92 RELEASED, 93 } mBufferState; 94 uint32_t mSeq; 95 bool mShutdown; 96 97 virtual bool threadLoop(); 98 99 void setSurfaceLocked(const sp<Surface>& surface); 100}; 101 102BufferProducerThread::BufferProducerThread( 103 tv_input_device_t* device, int deviceId, const tv_stream_t* stream) 104 : Thread(false), 105 mDevice(device), 106 mDeviceId(deviceId), 107 mBuffer(NULL), 108 mBufferState(RELEASED), 109 mSeq(0u), 110 mShutdown(false) { 111 memcpy(&mStream, stream, sizeof(mStream)); 112} 113 114status_t BufferProducerThread::readyToRun() { 115 sp<ANativeWindow> anw(mSurface); 116 status_t err = native_window_set_usage(anw.get(), mStream.buffer_producer.usage); 117 if (err != NO_ERROR) { 118 return err; 119 } 120 err = native_window_set_buffers_dimensions( 121 anw.get(), mStream.buffer_producer.width, mStream.buffer_producer.height); 122 if (err != NO_ERROR) { 123 return err; 124 } 125 err = native_window_set_buffers_format(anw.get(), mStream.buffer_producer.format); 126 if (err != NO_ERROR) { 127 return err; 128 } 129 return NO_ERROR; 130} 131 132void BufferProducerThread::setSurface(const sp<Surface>& surface) { 133 Mutex::Autolock autoLock(&mLock); 134 setSurfaceLocked(surface); 135} 136 137void BufferProducerThread::setSurfaceLocked(const sp<Surface>& surface) { 138 if (surface == mSurface) { 139 return; 140 } 141 142 if (mBufferState == CAPTURING) { 143 mDevice->cancel_capture(mDevice, mDeviceId, mStream.stream_id, mSeq); 144 } 145 while (mBufferState == CAPTURING) { 146 status_t err = mCondition.waitRelative(mLock, s2ns(1)); 147 if (err != NO_ERROR) { 148 ALOGE("error %d while wating for buffer state to change.", err); 149 break; 150 } 151 } 152 mBuffer.clear(); 153 mBufferState = RELEASED; 154 155 mSurface = surface; 156 mCondition.broadcast(); 157} 158 159void BufferProducerThread::onCaptured(uint32_t seq, bool succeeded) { 160 Mutex::Autolock autoLock(&mLock); 161 if (seq != mSeq) { 162 ALOGW("Incorrect sequence value: expected %u actual %u", mSeq, seq); 163 } 164 if (mBufferState != CAPTURING) { 165 ALOGW("mBufferState != CAPTURING : instead %d", mBufferState); 166 } 167 if (succeeded) { 168 mBufferState = CAPTURED; 169 } else { 170 mBuffer.clear(); 171 mBufferState = RELEASED; 172 } 173 mCondition.broadcast(); 174} 175 176void BufferProducerThread::shutdown() { 177 Mutex::Autolock autoLock(&mLock); 178 mShutdown = true; 179 setSurfaceLocked(NULL); 180 requestExitAndWait(); 181} 182 183bool BufferProducerThread::threadLoop() { 184 Mutex::Autolock autoLock(&mLock); 185 186 status_t err = NO_ERROR; 187 if (mSurface == NULL) { 188 err = mCondition.waitRelative(mLock, s2ns(1)); 189 // It's OK to time out here. 190 if (err != NO_ERROR && err != TIMED_OUT) { 191 ALOGE("error %d while wating for non-null surface to be set", err); 192 return false; 193 } 194 return true; 195 } 196 sp<ANativeWindow> anw(mSurface); 197 while (mBufferState == CAPTURING) { 198 err = mCondition.waitRelative(mLock, s2ns(1)); 199 if (err != NO_ERROR) { 200 ALOGE("error %d while wating for buffer state to change.", err); 201 return false; 202 } 203 } 204 if (mBufferState == CAPTURED && anw != NULL) { 205 err = anw->queueBuffer(anw.get(), mBuffer.get(), -1); 206 if (err != NO_ERROR) { 207 ALOGE("error %d while queueing buffer to surface", err); 208 return false; 209 } 210 mBuffer.clear(); 211 mBufferState = RELEASED; 212 } 213 if (mBuffer == NULL && !mShutdown && anw != NULL) { 214 ANativeWindowBuffer_t* buffer = NULL; 215 err = native_window_dequeue_buffer_and_wait(anw.get(), &buffer); 216 if (err != NO_ERROR) { 217 ALOGE("error %d while dequeueing buffer to surface", err); 218 return false; 219 } 220 mBuffer = buffer; 221 mBufferState = CAPTURING; 222 mDevice->request_capture(mDevice, mDeviceId, mStream.stream_id, 223 buffer->handle, ++mSeq); 224 } 225 226 return true; 227} 228 229//////////////////////////////////////////////////////////////////////////////// 230 231class JTvInputHal { 232public: 233 ~JTvInputHal(); 234 235 static JTvInputHal* createInstance(JNIEnv* env, jobject thiz); 236 237 int addStream(int deviceId, int streamId, const sp<Surface>& surface); 238 int removeStream(int deviceId, int streamId); 239 const tv_stream_config_t* getStreamConfigs(int deviceId, int* numConfigs); 240 241private: 242 // Connection between a surface and a stream. 243 class Connection { 244 public: 245 Connection() {} 246 247 sp<Surface> mSurface; 248 tv_stream_type_t mStreamType; 249 250 // Only valid when mStreamType == TV_STREAM_TYPE_INDEPENDENT_VIDEO_SOURCE 251 sp<NativeHandle> mSourceHandle; 252 // Only valid when mStreamType == TV_STREAM_TYPE_BUFFER_PRODUCER 253 sp<BufferProducerThread> mThread; 254 }; 255 256 JTvInputHal(JNIEnv* env, jobject thiz, tv_input_device_t* dev); 257 258 static void notify( 259 tv_input_device_t* dev, tv_input_event_t* event, void* data); 260 261 void onDeviceAvailable(const tv_input_device_info_t& info); 262 void onDeviceUnavailable(int deviceId); 263 void onStreamConfigurationsChanged(int deviceId); 264 void onCaptured(int deviceId, int streamId, uint32_t seq, bool succeeded); 265 266 Mutex mLock; 267 jweak mThiz; 268 tv_input_device_t* mDevice; 269 tv_input_callback_ops_t mCallback; 270 271 KeyedVector<int, KeyedVector<int, Connection> > mConnections; 272}; 273 274JTvInputHal::JTvInputHal(JNIEnv* env, jobject thiz, tv_input_device_t* device) { 275 mThiz = env->NewWeakGlobalRef(thiz); 276 mDevice = device; 277 mCallback.notify = &JTvInputHal::notify; 278 279 mDevice->initialize(mDevice, &mCallback, this); 280} 281 282JTvInputHal::~JTvInputHal() { 283 mDevice->common.close((hw_device_t*)mDevice); 284 285 JNIEnv* env = AndroidRuntime::getJNIEnv(); 286 env->DeleteWeakGlobalRef(mThiz); 287 mThiz = NULL; 288} 289 290JTvInputHal* JTvInputHal::createInstance(JNIEnv* env, jobject thiz) { 291 tv_input_module_t* module = NULL; 292 status_t err = hw_get_module(TV_INPUT_HARDWARE_MODULE_ID, 293 (hw_module_t const**)&module); 294 if (err) { 295 ALOGE("Couldn't load %s module (%s)", 296 TV_INPUT_HARDWARE_MODULE_ID, strerror(-err)); 297 return 0; 298 } 299 300 tv_input_device_t* device = NULL; 301 err = module->common.methods->open( 302 (hw_module_t*)module, 303 TV_INPUT_DEFAULT_DEVICE, 304 (hw_device_t**)&device); 305 if (err) { 306 ALOGE("Couldn't open %s device (%s)", 307 TV_INPUT_DEFAULT_DEVICE, strerror(-err)); 308 return 0; 309 } 310 311 return new JTvInputHal(env, thiz, device); 312} 313 314int JTvInputHal::addStream(int deviceId, int streamId, const sp<Surface>& surface) { 315 KeyedVector<int, Connection>& connections = mConnections.editValueFor(deviceId); 316 if (connections.indexOfKey(streamId) < 0) { 317 connections.add(streamId, Connection()); 318 } 319 Connection& connection = connections.editValueFor(streamId); 320 if (connection.mSurface == surface) { 321 // Nothing to do 322 return NO_ERROR; 323 } 324 // Clear the surface in the connection. 325 if (connection.mSurface != NULL) { 326 if (connection.mStreamType == TV_STREAM_TYPE_INDEPENDENT_VIDEO_SOURCE) { 327 if (Surface::isValid(connection.mSurface)) { 328 connection.mSurface->setSidebandStream(NULL); 329 } 330 } 331 connection.mSurface.clear(); 332 } 333 if (connection.mSourceHandle == NULL && connection.mThread == NULL) { 334 // Need to configure stream 335 int numConfigs = 0; 336 const tv_stream_config_t* configs = NULL; 337 if (mDevice->get_stream_configurations( 338 mDevice, deviceId, &numConfigs, &configs) != 0) { 339 ALOGE("Couldn't get stream configs"); 340 return UNKNOWN_ERROR; 341 } 342 int configIndex = -1; 343 for (int i = 0; i < numConfigs; ++i) { 344 if (configs[i].stream_id == streamId) { 345 configIndex = i; 346 break; 347 } 348 } 349 if (configIndex == -1) { 350 ALOGE("Cannot find a config with given stream ID: %d", streamId); 351 return BAD_VALUE; 352 } 353 tv_stream_t stream; 354 stream.stream_id = configs[configIndex].stream_id; 355 if (connection.mStreamType == TV_STREAM_TYPE_BUFFER_PRODUCER) { 356 stream.buffer_producer.width = configs[configIndex].max_video_width; 357 stream.buffer_producer.height = configs[configIndex].max_video_height; 358 } 359 if (mDevice->open_stream(mDevice, deviceId, &stream) != 0) { 360 ALOGE("Couldn't add stream"); 361 return UNKNOWN_ERROR; 362 } 363 if (connection.mStreamType == TV_STREAM_TYPE_INDEPENDENT_VIDEO_SOURCE) { 364 connection.mSourceHandle = NativeHandle::create( 365 stream.sideband_stream_source_handle, false); 366 } else if (connection.mStreamType == TV_STREAM_TYPE_BUFFER_PRODUCER) { 367 if (connection.mThread != NULL) { 368 connection.mThread->shutdown(); 369 } 370 connection.mThread = new BufferProducerThread(mDevice, deviceId, &stream); 371 connection.mThread->run(); 372 } 373 } 374 connection.mSurface = surface; 375 if (connection.mStreamType == TV_STREAM_TYPE_INDEPENDENT_VIDEO_SOURCE) { 376 connection.mSurface->setSidebandStream(connection.mSourceHandle); 377 } else if (connection.mStreamType == TV_STREAM_TYPE_BUFFER_PRODUCER) { 378 connection.mThread->setSurface(surface); 379 } 380 return NO_ERROR; 381} 382 383int JTvInputHal::removeStream(int deviceId, int streamId) { 384 KeyedVector<int, Connection>& connections = mConnections.editValueFor(deviceId); 385 if (connections.indexOfKey(streamId) < 0) { 386 return BAD_VALUE; 387 } 388 Connection& connection = connections.editValueFor(streamId); 389 if (connection.mSurface == NULL) { 390 // Nothing to do 391 return NO_ERROR; 392 } 393 if (Surface::isValid(connection.mSurface)) { 394 connection.mSurface.clear(); 395 } 396 if (connection.mSurface != NULL) { 397 connection.mSurface->setSidebandStream(NULL); 398 connection.mSurface.clear(); 399 } 400 if (connection.mSourceHandle != NULL) { 401 // Need to reset streams 402 if (mDevice->close_stream(mDevice, deviceId, streamId) != 0) { 403 ALOGE("Couldn't remove stream"); 404 return BAD_VALUE; 405 } 406 407 // Clear everything 408 if (connection.mThread != NULL) { 409 connection.mThread->shutdown(); 410 connection.mThread.clear(); 411 } 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} 543 544//////////////////////////////////////////////////////////////////////////////// 545 546static jlong nativeOpen(JNIEnv* env, jobject thiz) { 547 return (jlong)JTvInputHal::createInstance(env, thiz); 548} 549 550static int nativeAddStream(JNIEnv* env, jclass clazz, 551 jlong ptr, jint deviceId, jint streamId, jobject jsurface) { 552 JTvInputHal* tvInputHal = (JTvInputHal*)ptr; 553 if (!jsurface) { 554 return BAD_VALUE; 555 } 556 sp<Surface> surface(android_view_Surface_getSurface(env, jsurface)); 557 return tvInputHal->addStream(deviceId, streamId, surface); 558} 559 560static int nativeRemoveStream(JNIEnv* env, jclass clazz, 561 jlong ptr, jint deviceId, jint streamId) { 562 JTvInputHal* tvInputHal = (JTvInputHal*)ptr; 563 return tvInputHal->removeStream(deviceId, streamId); 564} 565 566static jobjectArray nativeGetStreamConfigs(JNIEnv* env, jclass clazz, 567 jlong ptr, jint deviceId, jint generation) { 568 JTvInputHal* tvInputHal = (JTvInputHal*)ptr; 569 int numConfigs = 0; 570 const tv_stream_config_t* configs = tvInputHal->getStreamConfigs(deviceId, &numConfigs); 571 572 jobjectArray result = env->NewObjectArray(numConfigs, gTvStreamConfigClassInfo.clazz, NULL); 573 for (int i = 0; i < numConfigs; ++i) { 574 jobject builder = env->NewObject( 575 gTvStreamConfigBuilderClassInfo.clazz, 576 gTvStreamConfigBuilderClassInfo.constructor); 577 env->CallObjectMethod( 578 builder, gTvStreamConfigBuilderClassInfo.streamId, configs[i].stream_id); 579 env->CallObjectMethod( 580 builder, gTvStreamConfigBuilderClassInfo.type, configs[i].type); 581 env->CallObjectMethod( 582 builder, gTvStreamConfigBuilderClassInfo.maxWidth, configs[i].max_video_width); 583 env->CallObjectMethod( 584 builder, gTvStreamConfigBuilderClassInfo.maxHeight, configs[i].max_video_height); 585 env->CallObjectMethod( 586 builder, gTvStreamConfigBuilderClassInfo.generation, generation); 587 588 jobject config = env->CallObjectMethod(builder, gTvStreamConfigBuilderClassInfo.build); 589 590 env->SetObjectArrayElement(result, i, config); 591 592 env->DeleteLocalRef(config); 593 env->DeleteLocalRef(builder); 594 } 595 return result; 596} 597 598static void nativeClose(JNIEnv* env, jclass clazz, jlong ptr) { 599 JTvInputHal* tvInputHal = (JTvInputHal*)ptr; 600 delete tvInputHal; 601} 602 603static JNINativeMethod gTvInputHalMethods[] = { 604 /* name, signature, funcPtr */ 605 { "nativeOpen", "()J", 606 (void*) nativeOpen }, 607 { "nativeAddStream", "(JIILandroid/view/Surface;)I", 608 (void*) nativeAddStream }, 609 { "nativeRemoveStream", "(JII)I", 610 (void*) nativeRemoveStream }, 611 { "nativeGetStreamConfigs", "(JII)[Landroid/media/tv/TvStreamConfig;", 612 (void*) nativeGetStreamConfigs }, 613 { "nativeClose", "(J)V", 614 (void*) nativeClose }, 615}; 616 617#define FIND_CLASS(var, className) \ 618 var = env->FindClass(className); \ 619 LOG_FATAL_IF(! var, "Unable to find class " className) 620 621#define GET_METHOD_ID(var, clazz, methodName, fieldDescriptor) \ 622 var = env->GetMethodID(clazz, methodName, fieldDescriptor); \ 623 LOG_FATAL_IF(! var, "Unable to find method" methodName) 624 625int register_android_server_tv_TvInputHal(JNIEnv* env) { 626 int res = jniRegisterNativeMethods(env, "com/android/server/tv/TvInputHal", 627 gTvInputHalMethods, NELEM(gTvInputHalMethods)); 628 LOG_FATAL_IF(res < 0, "Unable to register native methods."); 629 630 jclass clazz; 631 FIND_CLASS(clazz, "com/android/server/tv/TvInputHal"); 632 633 GET_METHOD_ID( 634 gTvInputHalClassInfo.deviceAvailable, clazz, 635 "deviceAvailableFromNative", "(Landroid/media/tv/TvInputHardwareInfo;)V"); 636 GET_METHOD_ID( 637 gTvInputHalClassInfo.deviceUnavailable, clazz, "deviceUnavailableFromNative", "(I)V"); 638 GET_METHOD_ID( 639 gTvInputHalClassInfo.streamConfigsChanged, clazz, 640 "streamConfigsChangedFromNative", "(I)V"); 641 642 FIND_CLASS(gTvStreamConfigClassInfo.clazz, "android/media/tv/TvStreamConfig"); 643 gTvStreamConfigClassInfo.clazz = jclass(env->NewGlobalRef(gTvStreamConfigClassInfo.clazz)); 644 645 FIND_CLASS(gTvStreamConfigBuilderClassInfo.clazz, "android/media/tv/TvStreamConfig$Builder"); 646 gTvStreamConfigBuilderClassInfo.clazz = 647 jclass(env->NewGlobalRef(gTvStreamConfigBuilderClassInfo.clazz)); 648 649 GET_METHOD_ID( 650 gTvStreamConfigBuilderClassInfo.constructor, 651 gTvStreamConfigBuilderClassInfo.clazz, 652 "<init>", "()V"); 653 GET_METHOD_ID( 654 gTvStreamConfigBuilderClassInfo.streamId, 655 gTvStreamConfigBuilderClassInfo.clazz, 656 "streamId", "(I)Landroid/media/tv/TvStreamConfig$Builder;"); 657 GET_METHOD_ID( 658 gTvStreamConfigBuilderClassInfo.type, 659 gTvStreamConfigBuilderClassInfo.clazz, 660 "type", "(I)Landroid/media/tv/TvStreamConfig$Builder;"); 661 GET_METHOD_ID( 662 gTvStreamConfigBuilderClassInfo.maxWidth, 663 gTvStreamConfigBuilderClassInfo.clazz, 664 "maxWidth", "(I)Landroid/media/tv/TvStreamConfig$Builder;"); 665 GET_METHOD_ID( 666 gTvStreamConfigBuilderClassInfo.maxHeight, 667 gTvStreamConfigBuilderClassInfo.clazz, 668 "maxHeight", "(I)Landroid/media/tv/TvStreamConfig$Builder;"); 669 GET_METHOD_ID( 670 gTvStreamConfigBuilderClassInfo.generation, 671 gTvStreamConfigBuilderClassInfo.clazz, 672 "generation", "(I)Landroid/media/tv/TvStreamConfig$Builder;"); 673 GET_METHOD_ID( 674 gTvStreamConfigBuilderClassInfo.build, 675 gTvStreamConfigBuilderClassInfo.clazz, 676 "build", "()Landroid/media/tv/TvStreamConfig;"); 677 678 FIND_CLASS(gTvInputHardwareInfoBuilderClassInfo.clazz, 679 "android/media/tv/TvInputHardwareInfo$Builder"); 680 gTvInputHardwareInfoBuilderClassInfo.clazz = 681 jclass(env->NewGlobalRef(gTvInputHardwareInfoBuilderClassInfo.clazz)); 682 683 GET_METHOD_ID( 684 gTvInputHardwareInfoBuilderClassInfo.constructor, 685 gTvInputHardwareInfoBuilderClassInfo.clazz, 686 "<init>", "()V"); 687 GET_METHOD_ID( 688 gTvInputHardwareInfoBuilderClassInfo.deviceId, 689 gTvInputHardwareInfoBuilderClassInfo.clazz, 690 "deviceId", "(I)Landroid/media/tv/TvInputHardwareInfo$Builder;"); 691 GET_METHOD_ID( 692 gTvInputHardwareInfoBuilderClassInfo.type, 693 gTvInputHardwareInfoBuilderClassInfo.clazz, 694 "type", "(I)Landroid/media/tv/TvInputHardwareInfo$Builder;"); 695 GET_METHOD_ID( 696 gTvInputHardwareInfoBuilderClassInfo.hdmiPortId, 697 gTvInputHardwareInfoBuilderClassInfo.clazz, 698 "hdmiPortId", "(I)Landroid/media/tv/TvInputHardwareInfo$Builder;"); 699 GET_METHOD_ID( 700 gTvInputHardwareInfoBuilderClassInfo.audioType, 701 gTvInputHardwareInfoBuilderClassInfo.clazz, 702 "audioType", "(I)Landroid/media/tv/TvInputHardwareInfo$Builder;"); 703 GET_METHOD_ID( 704 gTvInputHardwareInfoBuilderClassInfo.audioAddress, 705 gTvInputHardwareInfoBuilderClassInfo.clazz, 706 "audioAddress", "(Ljava/lang/String;)Landroid/media/tv/TvInputHardwareInfo$Builder;"); 707 GET_METHOD_ID( 708 gTvInputHardwareInfoBuilderClassInfo.build, 709 gTvInputHardwareInfoBuilderClassInfo.clazz, 710 "build", "()Landroid/media/tv/TvInputHardwareInfo;"); 711 712 return 0; 713} 714 715} /* namespace android */ 716