Loading services/core/jni/Android.mk +2 −0 Original line number Diff line number Diff line Loading @@ -71,3 +71,5 @@ LOCAL_SHARED_LIBRARIES += \ android.hardware.vibrator@1.0 \ android.hardware.light@2.0 \ android.hardware.vr@1.0 \ android.hardware.audio.common@2.0 \ android.hardware.tv.input@1.0 \ services/core/jni/com_android_server_tv_TvInputHal.cpp +127 −147 Original line number Diff line number Diff line Loading @@ -24,6 +24,9 @@ #include "JNIHelp.h" #include "jni.h" #include <android/hardware/tv/input/1.0/ITvInputCallback.h> #include <android/hardware/tv/input/1.0/ITvInput.h> #include <android/hardware/tv/input/1.0/types.h> #include <gui/Surface.h> #include <utils/Errors.h> #include <utils/KeyedVector.h> Loading @@ -32,6 +35,20 @@ #include <utils/NativeHandle.h> #include <hardware/tv_input.h> using ::android::hardware::audio::common::V2_0::AudioDevice; using ::android::hardware::tv::input::V1_0::ITvInput; using ::android::hardware::tv::input::V1_0::ITvInputCallback; using ::android::hardware::tv::input::V1_0::Result; using ::android::hardware::tv::input::V1_0::TvInputDeviceInfo; using ::android::hardware::tv::input::V1_0::TvInputEvent; using ::android::hardware::tv::input::V1_0::TvInputEventType; using ::android::hardware::tv::input::V1_0::TvInputType; using ::android::hardware::tv::input::V1_0::TvStreamConfig; using ::android::hardware::Return; using ::android::hardware::Void; using ::android::hardware::hidl_vec; using ::android::hardware::hidl_string; namespace android { static struct { Loading Loading @@ -239,9 +256,9 @@ public: int addOrUpdateStream(int deviceId, int streamId, const sp<Surface>& surface); int removeStream(int deviceId, int streamId); const tv_stream_config_t* getStreamConfigs(int deviceId, int* numConfigs); const hidl_vec<TvStreamConfig> getStreamConfigs(int deviceId); void onDeviceAvailable(const tv_input_device_info_t& info); void onDeviceAvailable(const TvInputDeviceInfo& info); void onDeviceUnavailable(int deviceId); void onStreamConfigurationsChanged(int deviceId); void onCaptured(int deviceId, int streamId, uint32_t seq, bool succeeded); Loading @@ -263,73 +280,60 @@ private: class NotifyHandler : public MessageHandler { public: NotifyHandler(JTvInputHal* hal, const tv_input_event_t* event); ~NotifyHandler(); NotifyHandler(JTvInputHal* hal, const TvInputEvent& event); virtual void handleMessage(const Message& message); private: tv_input_event_t mEvent; TvInputEvent mEvent; JTvInputHal* mHal; }; JTvInputHal(JNIEnv* env, jobject thiz, tv_input_device_t* dev, const sp<Looper>& looper); static void notify( tv_input_device_t* dev, tv_input_event_t* event, void* data); class TvInputCallback : public ITvInputCallback { public: TvInputCallback(JTvInputHal* hal); Return<void> notify(const TvInputEvent& event) override; private: JTvInputHal* mHal; }; static void cloneTvInputEvent( tv_input_event_t* dstEvent, const tv_input_event_t* srcEvent); JTvInputHal(JNIEnv* env, jobject thiz, sp<ITvInput> tvInput, const sp<Looper>& looper); Mutex mLock; jweak mThiz; tv_input_device_t* mDevice; tv_input_callback_ops_t mCallback; sp<Looper> mLooper; KeyedVector<int, KeyedVector<int, Connection> > mConnections; sp<ITvInput> mTvInput; sp<ITvInputCallback> mTvInputCallback; }; JTvInputHal::JTvInputHal(JNIEnv* env, jobject thiz, tv_input_device_t* device, JTvInputHal::JTvInputHal(JNIEnv* env, jobject thiz, sp<ITvInput> tvInput, const sp<Looper>& looper) { mThiz = env->NewWeakGlobalRef(thiz); mDevice = device; mCallback.notify = &JTvInputHal::notify; mTvInput = tvInput; mLooper = looper; mDevice->initialize(mDevice, &mCallback, this); mTvInputCallback = new TvInputCallback(this); mTvInput->setCallback(mTvInputCallback); } JTvInputHal::~JTvInputHal() { mDevice->common.close((hw_device_t*)mDevice); mTvInput->setCallback(nullptr); JNIEnv* env = AndroidRuntime::getJNIEnv(); env->DeleteWeakGlobalRef(mThiz); mThiz = NULL; } JTvInputHal* JTvInputHal::createInstance(JNIEnv* env, jobject thiz, const sp<Looper>& looper) { tv_input_module_t* module = NULL; status_t err = hw_get_module(TV_INPUT_HARDWARE_MODULE_ID, (hw_module_t const**)&module); if (err) { ALOGE("Couldn't load %s module (%s)", TV_INPUT_HARDWARE_MODULE_ID, strerror(-err)); return 0; } tv_input_device_t* device = NULL; err = module->common.methods->open( (hw_module_t*)module, TV_INPUT_DEFAULT_DEVICE, (hw_device_t**)&device); if (err) { ALOGE("Couldn't open %s device (%s)", TV_INPUT_DEFAULT_DEVICE, strerror(-err)); return 0; // TODO(b/31632518) sp<ITvInput> tvInput = ITvInput::getService("tv.input"); if (tvInput == nullptr) { ALOGE("Couldn't get tv.input service."); return nullptr; } return new JTvInputHal(env, thiz, device, looper); return new JTvInputHal(env, thiz, tvInput, looper); } int JTvInputHal::addOrUpdateStream(int deviceId, int streamId, const sp<Surface>& surface) { Loading @@ -353,16 +357,22 @@ int JTvInputHal::addOrUpdateStream(int deviceId, int streamId, const sp<Surface> } if (connection.mSourceHandle == NULL && connection.mThread == NULL) { // Need to configure stream int numConfigs = 0; const tv_stream_config_t* configs = NULL; if (mDevice->get_stream_configurations( mDevice, deviceId, &numConfigs, &configs) != 0) { ALOGE("Couldn't get stream configs"); Result result = Result::UNKNOWN; hidl_vec<TvStreamConfig> list; mTvInput->getStreamConfigurations(deviceId, [&result, &list](Result res, hidl_vec<TvStreamConfig> configs) { result = res; if (res == Result::OK) { list = configs; } }); if (result != Result::OK) { ALOGE("Couldn't get stream configs for device id:%d result:%d", deviceId, result); return UNKNOWN_ERROR; } int configIndex = -1; for (int i = 0; i < numConfigs; ++i) { if (configs[i].stream_id == streamId) { for (size_t i = 0; i < list.size(); ++i) { if (list[i].streamId == streamId) { configIndex = i; break; } Loading @@ -371,34 +381,27 @@ int JTvInputHal::addOrUpdateStream(int deviceId, int streamId, const sp<Surface> ALOGE("Cannot find a config with given stream ID: %d", streamId); return BAD_VALUE; } connection.mStreamType = configs[configIndex].type; connection.mStreamType = TV_STREAM_TYPE_INDEPENDENT_VIDEO_SOURCE; tv_stream_t stream; stream.stream_id = configs[configIndex].stream_id; if (connection.mStreamType == TV_STREAM_TYPE_BUFFER_PRODUCER) { stream.buffer_producer.width = configs[configIndex].max_video_width; stream.buffer_producer.height = configs[configIndex].max_video_height; result = Result::UNKNOWN; const native_handle_t* sidebandStream; mTvInput->openStream(deviceId, streamId, [&result, &sidebandStream](Result res, const native_handle_t* handle) { result = res; if (res == Result::OK) { sidebandStream = handle; } if (mDevice->open_stream(mDevice, deviceId, &stream) != 0) { ALOGE("Couldn't add stream"); }); if (result != Result::OK) { ALOGE("Couldn't open stream. device id:%d stream id:%d result:%d", deviceId, streamId, result); return UNKNOWN_ERROR; } if (connection.mStreamType == TV_STREAM_TYPE_INDEPENDENT_VIDEO_SOURCE) { connection.mSourceHandle = NativeHandle::create( stream.sideband_stream_source_handle, false); } else if (connection.mStreamType == TV_STREAM_TYPE_BUFFER_PRODUCER) { if (connection.mThread != NULL) { connection.mThread->shutdown(); } connection.mThread = new BufferProducerThread(mDevice, deviceId, &stream); connection.mThread->run("BufferProducerThread"); } connection.mSourceHandle = NativeHandle::create((native_handle_t*)sidebandStream, false); } connection.mSurface = surface; if (connection.mStreamType == TV_STREAM_TYPE_INDEPENDENT_VIDEO_SOURCE) { if (connection.mSurface != nullptr) { connection.mSurface->setSidebandStream(connection.mSourceHandle); } else if (connection.mStreamType == TV_STREAM_TYPE_BUFFER_PRODUCER) { connection.mThread->setSurface(surface); } return NO_ERROR; } Loading @@ -421,8 +424,8 @@ int JTvInputHal::removeStream(int deviceId, int streamId) { connection.mThread->shutdown(); connection.mThread.clear(); } if (mDevice->close_stream(mDevice, deviceId, streamId) != 0) { ALOGE("Couldn't remove stream"); if (mTvInput->closeStream(deviceId, streamId) != Result::OK) { ALOGE("Couldn't close stream. device id:%d stream id:%d", deviceId, streamId); return BAD_VALUE; } if (connection.mSourceHandle != NULL) { Loading @@ -431,41 +434,26 @@ int JTvInputHal::removeStream(int deviceId, int streamId) { return NO_ERROR; } const tv_stream_config_t* JTvInputHal::getStreamConfigs(int deviceId, int* numConfigs) { const tv_stream_config_t* configs = NULL; if (mDevice->get_stream_configurations( mDevice, deviceId, numConfigs, &configs) != 0) { ALOGE("Couldn't get stream configs"); return NULL; const hidl_vec<TvStreamConfig> JTvInputHal::getStreamConfigs(int deviceId) { Result result = Result::UNKNOWN; hidl_vec<TvStreamConfig> list; mTvInput->getStreamConfigurations(deviceId, [&result, &list](Result res, hidl_vec<TvStreamConfig> configs) { result = res; if (res == Result::OK) { list = configs; } return configs; }); if (result != Result::OK) { ALOGE("Couldn't get stream configs for device id:%d result:%d", deviceId, result); } // static void JTvInputHal::notify( tv_input_device_t* dev, tv_input_event_t* event, void* data) { JTvInputHal* thiz = (JTvInputHal*)data; thiz->mLooper->sendMessage(new NotifyHandler(thiz, event), event->type); return list; } // static void JTvInputHal::cloneTvInputEvent( tv_input_event_t* dstEvent, const tv_input_event_t* srcEvent) { memcpy(dstEvent, srcEvent, sizeof(tv_input_event_t)); if ((srcEvent->type == TV_INPUT_EVENT_DEVICE_AVAILABLE || srcEvent->type == TV_INPUT_EVENT_DEVICE_UNAVAILABLE || srcEvent->type == TV_INPUT_EVENT_STREAM_CONFIGURATIONS_CHANGED) && srcEvent->device_info.audio_address != NULL){ char* audio_address = new char[strlen(srcEvent->device_info.audio_address) + 1]; strcpy(audio_address, srcEvent->device_info.audio_address); dstEvent->device_info.audio_address = audio_address; } } void JTvInputHal::onDeviceAvailable(const tv_input_device_info_t& info) { void JTvInputHal::onDeviceAvailable(const TvInputDeviceInfo& info) { { Mutex::Autolock autoLock(&mLock); mConnections.add(info.device_id, KeyedVector<int, Connection>()); mConnections.add(info.deviceId, KeyedVector<int, Connection>()); } JNIEnv* env = AndroidRuntime::getJNIEnv(); Loading @@ -473,17 +461,20 @@ void JTvInputHal::onDeviceAvailable(const tv_input_device_info_t& info) { gTvInputHardwareInfoBuilderClassInfo.clazz, gTvInputHardwareInfoBuilderClassInfo.constructor); env->CallObjectMethod( builder, gTvInputHardwareInfoBuilderClassInfo.deviceId, info.device_id); builder, gTvInputHardwareInfoBuilderClassInfo.deviceId, info.deviceId); env->CallObjectMethod( builder, gTvInputHardwareInfoBuilderClassInfo.type, info.type); if (info.type == TV_INPUT_TYPE_HDMI) { if (info.type == TvInputType::HDMI) { env->CallObjectMethod( builder, gTvInputHardwareInfoBuilderClassInfo.hdmiPortId, info.hdmi.port_id); builder, gTvInputHardwareInfoBuilderClassInfo.hdmiPortId, info.portId); } env->CallObjectMethod( builder, gTvInputHardwareInfoBuilderClassInfo.audioType, info.audio_type); if (info.audio_type != AUDIO_DEVICE_NONE) { jstring audioAddress = env->NewStringUTF(info.audio_address); builder, gTvInputHardwareInfoBuilderClassInfo.audioType, info.audioType); if (info.audioType != AudioDevice::NONE) { uint8_t buffer[info.audioAddress.size() + 1]; memcpy(buffer, info.audioAddress.data(), info.audioAddress.size()); buffer[info.audioAddress.size()] = '\0'; jstring audioAddress = env->NewStringUTF(reinterpret_cast<const char *>(buffer)); env->CallObjectMethod( builder, gTvInputHardwareInfoBuilderClassInfo.audioAddress, audioAddress); env->DeleteLocalRef(audioAddress); Loading Loading @@ -556,48 +547,37 @@ void JTvInputHal::onCaptured(int deviceId, int streamId, uint32_t seq, bool succ } } JTvInputHal::NotifyHandler::NotifyHandler(JTvInputHal* hal, const tv_input_event_t* event) { JTvInputHal::NotifyHandler::NotifyHandler(JTvInputHal* hal, const TvInputEvent& event) { mHal = hal; cloneTvInputEvent(&mEvent, event); } JTvInputHal::NotifyHandler::~NotifyHandler() { if ((mEvent.type == TV_INPUT_EVENT_DEVICE_AVAILABLE || mEvent.type == TV_INPUT_EVENT_DEVICE_UNAVAILABLE || mEvent.type == TV_INPUT_EVENT_STREAM_CONFIGURATIONS_CHANGED) && mEvent.device_info.audio_address != NULL) { delete mEvent.device_info.audio_address; } mEvent = event; } void JTvInputHal::NotifyHandler::handleMessage(const Message& message) { switch (mEvent.type) { case TV_INPUT_EVENT_DEVICE_AVAILABLE: { mHal->onDeviceAvailable(mEvent.device_info); } break; case TV_INPUT_EVENT_DEVICE_UNAVAILABLE: { mHal->onDeviceUnavailable(mEvent.device_info.device_id); case TvInputEventType::DEVICE_AVAILABLE: { mHal->onDeviceAvailable(mEvent.deviceInfo); } break; case TV_INPUT_EVENT_STREAM_CONFIGURATIONS_CHANGED: { mHal->onStreamConfigurationsChanged(mEvent.device_info.device_id); case TvInputEventType::DEVICE_UNAVAILABLE: { mHal->onDeviceUnavailable(mEvent.deviceInfo.deviceId); } break; case TV_INPUT_EVENT_CAPTURE_SUCCEEDED: { mHal->onCaptured(mEvent.capture_result.device_id, mEvent.capture_result.stream_id, mEvent.capture_result.seq, true /* succeeded */); } break; case TV_INPUT_EVENT_CAPTURE_FAILED: { mHal->onCaptured(mEvent.capture_result.device_id, mEvent.capture_result.stream_id, mEvent.capture_result.seq, false /* succeeded */); case TvInputEventType::STREAM_CONFIGURATIONS_CHANGED: { mHal->onStreamConfigurationsChanged(mEvent.deviceInfo.deviceId); } break; default: ALOGE("Unrecognizable event"); } } JTvInputHal::TvInputCallback::TvInputCallback(JTvInputHal* hal) { mHal = hal; } Return<void> JTvInputHal::TvInputCallback::notify(const TvInputEvent& event) { // TODO(b/32200867): Ensure the event type values are in sync with the framework code. mHal->mLooper->sendMessage(new NotifyHandler(mHal, event), static_cast<int>(event.type)); return Void(); } //////////////////////////////////////////////////////////////////////////////// static jlong nativeOpen(JNIEnv* env, jobject thiz, jobject messageQueueObj) { Loading Loading @@ -628,22 +608,22 @@ static int nativeRemoveStream(JNIEnv* env, jclass clazz, static jobjectArray nativeGetStreamConfigs(JNIEnv* env, jclass clazz, jlong ptr, jint deviceId, jint generation) { JTvInputHal* tvInputHal = (JTvInputHal*)ptr; int numConfigs = 0; const tv_stream_config_t* configs = tvInputHal->getStreamConfigs(deviceId, &numConfigs); const hidl_vec<TvStreamConfig> configs = tvInputHal->getStreamConfigs(deviceId); jobjectArray result = env->NewObjectArray(numConfigs, gTvStreamConfigClassInfo.clazz, NULL); for (int i = 0; i < numConfigs; ++i) { jobjectArray result = env->NewObjectArray(configs.size(), gTvStreamConfigClassInfo.clazz, NULL); for (size_t i = 0; i < configs.size(); ++i) { jobject builder = env->NewObject( gTvStreamConfigBuilderClassInfo.clazz, gTvStreamConfigBuilderClassInfo.constructor); env->CallObjectMethod( builder, gTvStreamConfigBuilderClassInfo.streamId, configs[i].stream_id); builder, gTvStreamConfigBuilderClassInfo.streamId, configs[i].streamId); env->CallObjectMethod( builder, gTvStreamConfigBuilderClassInfo.type, configs[i].type); builder, gTvStreamConfigBuilderClassInfo.type, TV_STREAM_TYPE_INDEPENDENT_VIDEO_SOURCE); env->CallObjectMethod( builder, gTvStreamConfigBuilderClassInfo.maxWidth, configs[i].max_video_width); builder, gTvStreamConfigBuilderClassInfo.maxWidth, configs[i].maxVideoWidth); env->CallObjectMethod( builder, gTvStreamConfigBuilderClassInfo.maxHeight, configs[i].max_video_height); builder, gTvStreamConfigBuilderClassInfo.maxHeight, configs[i].maxVideoHeight); env->CallObjectMethod( builder, gTvStreamConfigBuilderClassInfo.generation, generation); Loading Loading
services/core/jni/Android.mk +2 −0 Original line number Diff line number Diff line Loading @@ -71,3 +71,5 @@ LOCAL_SHARED_LIBRARIES += \ android.hardware.vibrator@1.0 \ android.hardware.light@2.0 \ android.hardware.vr@1.0 \ android.hardware.audio.common@2.0 \ android.hardware.tv.input@1.0 \
services/core/jni/com_android_server_tv_TvInputHal.cpp +127 −147 Original line number Diff line number Diff line Loading @@ -24,6 +24,9 @@ #include "JNIHelp.h" #include "jni.h" #include <android/hardware/tv/input/1.0/ITvInputCallback.h> #include <android/hardware/tv/input/1.0/ITvInput.h> #include <android/hardware/tv/input/1.0/types.h> #include <gui/Surface.h> #include <utils/Errors.h> #include <utils/KeyedVector.h> Loading @@ -32,6 +35,20 @@ #include <utils/NativeHandle.h> #include <hardware/tv_input.h> using ::android::hardware::audio::common::V2_0::AudioDevice; using ::android::hardware::tv::input::V1_0::ITvInput; using ::android::hardware::tv::input::V1_0::ITvInputCallback; using ::android::hardware::tv::input::V1_0::Result; using ::android::hardware::tv::input::V1_0::TvInputDeviceInfo; using ::android::hardware::tv::input::V1_0::TvInputEvent; using ::android::hardware::tv::input::V1_0::TvInputEventType; using ::android::hardware::tv::input::V1_0::TvInputType; using ::android::hardware::tv::input::V1_0::TvStreamConfig; using ::android::hardware::Return; using ::android::hardware::Void; using ::android::hardware::hidl_vec; using ::android::hardware::hidl_string; namespace android { static struct { Loading Loading @@ -239,9 +256,9 @@ public: int addOrUpdateStream(int deviceId, int streamId, const sp<Surface>& surface); int removeStream(int deviceId, int streamId); const tv_stream_config_t* getStreamConfigs(int deviceId, int* numConfigs); const hidl_vec<TvStreamConfig> getStreamConfigs(int deviceId); void onDeviceAvailable(const tv_input_device_info_t& info); void onDeviceAvailable(const TvInputDeviceInfo& info); void onDeviceUnavailable(int deviceId); void onStreamConfigurationsChanged(int deviceId); void onCaptured(int deviceId, int streamId, uint32_t seq, bool succeeded); Loading @@ -263,73 +280,60 @@ private: class NotifyHandler : public MessageHandler { public: NotifyHandler(JTvInputHal* hal, const tv_input_event_t* event); ~NotifyHandler(); NotifyHandler(JTvInputHal* hal, const TvInputEvent& event); virtual void handleMessage(const Message& message); private: tv_input_event_t mEvent; TvInputEvent mEvent; JTvInputHal* mHal; }; JTvInputHal(JNIEnv* env, jobject thiz, tv_input_device_t* dev, const sp<Looper>& looper); static void notify( tv_input_device_t* dev, tv_input_event_t* event, void* data); class TvInputCallback : public ITvInputCallback { public: TvInputCallback(JTvInputHal* hal); Return<void> notify(const TvInputEvent& event) override; private: JTvInputHal* mHal; }; static void cloneTvInputEvent( tv_input_event_t* dstEvent, const tv_input_event_t* srcEvent); JTvInputHal(JNIEnv* env, jobject thiz, sp<ITvInput> tvInput, const sp<Looper>& looper); Mutex mLock; jweak mThiz; tv_input_device_t* mDevice; tv_input_callback_ops_t mCallback; sp<Looper> mLooper; KeyedVector<int, KeyedVector<int, Connection> > mConnections; sp<ITvInput> mTvInput; sp<ITvInputCallback> mTvInputCallback; }; JTvInputHal::JTvInputHal(JNIEnv* env, jobject thiz, tv_input_device_t* device, JTvInputHal::JTvInputHal(JNIEnv* env, jobject thiz, sp<ITvInput> tvInput, const sp<Looper>& looper) { mThiz = env->NewWeakGlobalRef(thiz); mDevice = device; mCallback.notify = &JTvInputHal::notify; mTvInput = tvInput; mLooper = looper; mDevice->initialize(mDevice, &mCallback, this); mTvInputCallback = new TvInputCallback(this); mTvInput->setCallback(mTvInputCallback); } JTvInputHal::~JTvInputHal() { mDevice->common.close((hw_device_t*)mDevice); mTvInput->setCallback(nullptr); JNIEnv* env = AndroidRuntime::getJNIEnv(); env->DeleteWeakGlobalRef(mThiz); mThiz = NULL; } JTvInputHal* JTvInputHal::createInstance(JNIEnv* env, jobject thiz, const sp<Looper>& looper) { tv_input_module_t* module = NULL; status_t err = hw_get_module(TV_INPUT_HARDWARE_MODULE_ID, (hw_module_t const**)&module); if (err) { ALOGE("Couldn't load %s module (%s)", TV_INPUT_HARDWARE_MODULE_ID, strerror(-err)); return 0; } tv_input_device_t* device = NULL; err = module->common.methods->open( (hw_module_t*)module, TV_INPUT_DEFAULT_DEVICE, (hw_device_t**)&device); if (err) { ALOGE("Couldn't open %s device (%s)", TV_INPUT_DEFAULT_DEVICE, strerror(-err)); return 0; // TODO(b/31632518) sp<ITvInput> tvInput = ITvInput::getService("tv.input"); if (tvInput == nullptr) { ALOGE("Couldn't get tv.input service."); return nullptr; } return new JTvInputHal(env, thiz, device, looper); return new JTvInputHal(env, thiz, tvInput, looper); } int JTvInputHal::addOrUpdateStream(int deviceId, int streamId, const sp<Surface>& surface) { Loading @@ -353,16 +357,22 @@ int JTvInputHal::addOrUpdateStream(int deviceId, int streamId, const sp<Surface> } if (connection.mSourceHandle == NULL && connection.mThread == NULL) { // Need to configure stream int numConfigs = 0; const tv_stream_config_t* configs = NULL; if (mDevice->get_stream_configurations( mDevice, deviceId, &numConfigs, &configs) != 0) { ALOGE("Couldn't get stream configs"); Result result = Result::UNKNOWN; hidl_vec<TvStreamConfig> list; mTvInput->getStreamConfigurations(deviceId, [&result, &list](Result res, hidl_vec<TvStreamConfig> configs) { result = res; if (res == Result::OK) { list = configs; } }); if (result != Result::OK) { ALOGE("Couldn't get stream configs for device id:%d result:%d", deviceId, result); return UNKNOWN_ERROR; } int configIndex = -1; for (int i = 0; i < numConfigs; ++i) { if (configs[i].stream_id == streamId) { for (size_t i = 0; i < list.size(); ++i) { if (list[i].streamId == streamId) { configIndex = i; break; } Loading @@ -371,34 +381,27 @@ int JTvInputHal::addOrUpdateStream(int deviceId, int streamId, const sp<Surface> ALOGE("Cannot find a config with given stream ID: %d", streamId); return BAD_VALUE; } connection.mStreamType = configs[configIndex].type; connection.mStreamType = TV_STREAM_TYPE_INDEPENDENT_VIDEO_SOURCE; tv_stream_t stream; stream.stream_id = configs[configIndex].stream_id; if (connection.mStreamType == TV_STREAM_TYPE_BUFFER_PRODUCER) { stream.buffer_producer.width = configs[configIndex].max_video_width; stream.buffer_producer.height = configs[configIndex].max_video_height; result = Result::UNKNOWN; const native_handle_t* sidebandStream; mTvInput->openStream(deviceId, streamId, [&result, &sidebandStream](Result res, const native_handle_t* handle) { result = res; if (res == Result::OK) { sidebandStream = handle; } if (mDevice->open_stream(mDevice, deviceId, &stream) != 0) { ALOGE("Couldn't add stream"); }); if (result != Result::OK) { ALOGE("Couldn't open stream. device id:%d stream id:%d result:%d", deviceId, streamId, result); return UNKNOWN_ERROR; } if (connection.mStreamType == TV_STREAM_TYPE_INDEPENDENT_VIDEO_SOURCE) { connection.mSourceHandle = NativeHandle::create( stream.sideband_stream_source_handle, false); } else if (connection.mStreamType == TV_STREAM_TYPE_BUFFER_PRODUCER) { if (connection.mThread != NULL) { connection.mThread->shutdown(); } connection.mThread = new BufferProducerThread(mDevice, deviceId, &stream); connection.mThread->run("BufferProducerThread"); } connection.mSourceHandle = NativeHandle::create((native_handle_t*)sidebandStream, false); } connection.mSurface = surface; if (connection.mStreamType == TV_STREAM_TYPE_INDEPENDENT_VIDEO_SOURCE) { if (connection.mSurface != nullptr) { connection.mSurface->setSidebandStream(connection.mSourceHandle); } else if (connection.mStreamType == TV_STREAM_TYPE_BUFFER_PRODUCER) { connection.mThread->setSurface(surface); } return NO_ERROR; } Loading @@ -421,8 +424,8 @@ int JTvInputHal::removeStream(int deviceId, int streamId) { connection.mThread->shutdown(); connection.mThread.clear(); } if (mDevice->close_stream(mDevice, deviceId, streamId) != 0) { ALOGE("Couldn't remove stream"); if (mTvInput->closeStream(deviceId, streamId) != Result::OK) { ALOGE("Couldn't close stream. device id:%d stream id:%d", deviceId, streamId); return BAD_VALUE; } if (connection.mSourceHandle != NULL) { Loading @@ -431,41 +434,26 @@ int JTvInputHal::removeStream(int deviceId, int streamId) { return NO_ERROR; } const tv_stream_config_t* JTvInputHal::getStreamConfigs(int deviceId, int* numConfigs) { const tv_stream_config_t* configs = NULL; if (mDevice->get_stream_configurations( mDevice, deviceId, numConfigs, &configs) != 0) { ALOGE("Couldn't get stream configs"); return NULL; const hidl_vec<TvStreamConfig> JTvInputHal::getStreamConfigs(int deviceId) { Result result = Result::UNKNOWN; hidl_vec<TvStreamConfig> list; mTvInput->getStreamConfigurations(deviceId, [&result, &list](Result res, hidl_vec<TvStreamConfig> configs) { result = res; if (res == Result::OK) { list = configs; } return configs; }); if (result != Result::OK) { ALOGE("Couldn't get stream configs for device id:%d result:%d", deviceId, result); } // static void JTvInputHal::notify( tv_input_device_t* dev, tv_input_event_t* event, void* data) { JTvInputHal* thiz = (JTvInputHal*)data; thiz->mLooper->sendMessage(new NotifyHandler(thiz, event), event->type); return list; } // static void JTvInputHal::cloneTvInputEvent( tv_input_event_t* dstEvent, const tv_input_event_t* srcEvent) { memcpy(dstEvent, srcEvent, sizeof(tv_input_event_t)); if ((srcEvent->type == TV_INPUT_EVENT_DEVICE_AVAILABLE || srcEvent->type == TV_INPUT_EVENT_DEVICE_UNAVAILABLE || srcEvent->type == TV_INPUT_EVENT_STREAM_CONFIGURATIONS_CHANGED) && srcEvent->device_info.audio_address != NULL){ char* audio_address = new char[strlen(srcEvent->device_info.audio_address) + 1]; strcpy(audio_address, srcEvent->device_info.audio_address); dstEvent->device_info.audio_address = audio_address; } } void JTvInputHal::onDeviceAvailable(const tv_input_device_info_t& info) { void JTvInputHal::onDeviceAvailable(const TvInputDeviceInfo& info) { { Mutex::Autolock autoLock(&mLock); mConnections.add(info.device_id, KeyedVector<int, Connection>()); mConnections.add(info.deviceId, KeyedVector<int, Connection>()); } JNIEnv* env = AndroidRuntime::getJNIEnv(); Loading @@ -473,17 +461,20 @@ void JTvInputHal::onDeviceAvailable(const tv_input_device_info_t& info) { gTvInputHardwareInfoBuilderClassInfo.clazz, gTvInputHardwareInfoBuilderClassInfo.constructor); env->CallObjectMethod( builder, gTvInputHardwareInfoBuilderClassInfo.deviceId, info.device_id); builder, gTvInputHardwareInfoBuilderClassInfo.deviceId, info.deviceId); env->CallObjectMethod( builder, gTvInputHardwareInfoBuilderClassInfo.type, info.type); if (info.type == TV_INPUT_TYPE_HDMI) { if (info.type == TvInputType::HDMI) { env->CallObjectMethod( builder, gTvInputHardwareInfoBuilderClassInfo.hdmiPortId, info.hdmi.port_id); builder, gTvInputHardwareInfoBuilderClassInfo.hdmiPortId, info.portId); } env->CallObjectMethod( builder, gTvInputHardwareInfoBuilderClassInfo.audioType, info.audio_type); if (info.audio_type != AUDIO_DEVICE_NONE) { jstring audioAddress = env->NewStringUTF(info.audio_address); builder, gTvInputHardwareInfoBuilderClassInfo.audioType, info.audioType); if (info.audioType != AudioDevice::NONE) { uint8_t buffer[info.audioAddress.size() + 1]; memcpy(buffer, info.audioAddress.data(), info.audioAddress.size()); buffer[info.audioAddress.size()] = '\0'; jstring audioAddress = env->NewStringUTF(reinterpret_cast<const char *>(buffer)); env->CallObjectMethod( builder, gTvInputHardwareInfoBuilderClassInfo.audioAddress, audioAddress); env->DeleteLocalRef(audioAddress); Loading Loading @@ -556,48 +547,37 @@ void JTvInputHal::onCaptured(int deviceId, int streamId, uint32_t seq, bool succ } } JTvInputHal::NotifyHandler::NotifyHandler(JTvInputHal* hal, const tv_input_event_t* event) { JTvInputHal::NotifyHandler::NotifyHandler(JTvInputHal* hal, const TvInputEvent& event) { mHal = hal; cloneTvInputEvent(&mEvent, event); } JTvInputHal::NotifyHandler::~NotifyHandler() { if ((mEvent.type == TV_INPUT_EVENT_DEVICE_AVAILABLE || mEvent.type == TV_INPUT_EVENT_DEVICE_UNAVAILABLE || mEvent.type == TV_INPUT_EVENT_STREAM_CONFIGURATIONS_CHANGED) && mEvent.device_info.audio_address != NULL) { delete mEvent.device_info.audio_address; } mEvent = event; } void JTvInputHal::NotifyHandler::handleMessage(const Message& message) { switch (mEvent.type) { case TV_INPUT_EVENT_DEVICE_AVAILABLE: { mHal->onDeviceAvailable(mEvent.device_info); } break; case TV_INPUT_EVENT_DEVICE_UNAVAILABLE: { mHal->onDeviceUnavailable(mEvent.device_info.device_id); case TvInputEventType::DEVICE_AVAILABLE: { mHal->onDeviceAvailable(mEvent.deviceInfo); } break; case TV_INPUT_EVENT_STREAM_CONFIGURATIONS_CHANGED: { mHal->onStreamConfigurationsChanged(mEvent.device_info.device_id); case TvInputEventType::DEVICE_UNAVAILABLE: { mHal->onDeviceUnavailable(mEvent.deviceInfo.deviceId); } break; case TV_INPUT_EVENT_CAPTURE_SUCCEEDED: { mHal->onCaptured(mEvent.capture_result.device_id, mEvent.capture_result.stream_id, mEvent.capture_result.seq, true /* succeeded */); } break; case TV_INPUT_EVENT_CAPTURE_FAILED: { mHal->onCaptured(mEvent.capture_result.device_id, mEvent.capture_result.stream_id, mEvent.capture_result.seq, false /* succeeded */); case TvInputEventType::STREAM_CONFIGURATIONS_CHANGED: { mHal->onStreamConfigurationsChanged(mEvent.deviceInfo.deviceId); } break; default: ALOGE("Unrecognizable event"); } } JTvInputHal::TvInputCallback::TvInputCallback(JTvInputHal* hal) { mHal = hal; } Return<void> JTvInputHal::TvInputCallback::notify(const TvInputEvent& event) { // TODO(b/32200867): Ensure the event type values are in sync with the framework code. mHal->mLooper->sendMessage(new NotifyHandler(mHal, event), static_cast<int>(event.type)); return Void(); } //////////////////////////////////////////////////////////////////////////////// static jlong nativeOpen(JNIEnv* env, jobject thiz, jobject messageQueueObj) { Loading Loading @@ -628,22 +608,22 @@ static int nativeRemoveStream(JNIEnv* env, jclass clazz, static jobjectArray nativeGetStreamConfigs(JNIEnv* env, jclass clazz, jlong ptr, jint deviceId, jint generation) { JTvInputHal* tvInputHal = (JTvInputHal*)ptr; int numConfigs = 0; const tv_stream_config_t* configs = tvInputHal->getStreamConfigs(deviceId, &numConfigs); const hidl_vec<TvStreamConfig> configs = tvInputHal->getStreamConfigs(deviceId); jobjectArray result = env->NewObjectArray(numConfigs, gTvStreamConfigClassInfo.clazz, NULL); for (int i = 0; i < numConfigs; ++i) { jobjectArray result = env->NewObjectArray(configs.size(), gTvStreamConfigClassInfo.clazz, NULL); for (size_t i = 0; i < configs.size(); ++i) { jobject builder = env->NewObject( gTvStreamConfigBuilderClassInfo.clazz, gTvStreamConfigBuilderClassInfo.constructor); env->CallObjectMethod( builder, gTvStreamConfigBuilderClassInfo.streamId, configs[i].stream_id); builder, gTvStreamConfigBuilderClassInfo.streamId, configs[i].streamId); env->CallObjectMethod( builder, gTvStreamConfigBuilderClassInfo.type, configs[i].type); builder, gTvStreamConfigBuilderClassInfo.type, TV_STREAM_TYPE_INDEPENDENT_VIDEO_SOURCE); env->CallObjectMethod( builder, gTvStreamConfigBuilderClassInfo.maxWidth, configs[i].max_video_width); builder, gTvStreamConfigBuilderClassInfo.maxWidth, configs[i].maxVideoWidth); env->CallObjectMethod( builder, gTvStreamConfigBuilderClassInfo.maxHeight, configs[i].max_video_height); builder, gTvStreamConfigBuilderClassInfo.maxHeight, configs[i].maxVideoHeight); env->CallObjectMethod( builder, gTvStreamConfigBuilderClassInfo.generation, generation); Loading