Merge "tv.input: Updating tv input hal client with hidl."

This commit is contained in:
TreeHugger Robot
2016-10-26 00:46:59 +00:00
committed by Android (Google) Code Review
2 changed files with 125 additions and 143 deletions

View File

@@ -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 \

View File

@@ -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>
@@ -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 {
@@ -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);
@@ -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);
class TvInputCallback : public ITvInputCallback {
public:
TvInputCallback(JTvInputHal* hal);
Return<void> notify(const TvInputEvent& event) override;
private:
JTvInputHal* mHal;
};
static void notify(
tv_input_device_t* dev, tv_input_event_t* event, void* data);
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;
// TODO(b/31632518)
sp<ITvInput> tvInput = ITvInput::getService("tv.input");
if (tvInput == nullptr) {
ALOGE("Couldn't get tv.input service.");
return nullptr;
}
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;
}
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) {
@@ -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;
}
@@ -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;
}
if (mDevice->open_stream(mDevice, deviceId, &stream) != 0) {
ALOGE("Couldn't add stream");
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 (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;
}
@@ -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) {
@@ -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;
}
});
if (result != Result::OK) {
ALOGE("Couldn't get stream configs for device id:%d result:%d", deviceId, result);
}
return configs;
return list;
}
// 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);
}
// 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();
@@ -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);
@@ -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);
case TvInputEventType::DEVICE_AVAILABLE: {
mHal->onDeviceAvailable(mEvent.deviceInfo);
} break;
case TV_INPUT_EVENT_DEVICE_UNAVAILABLE: {
mHal->onDeviceUnavailable(mEvent.device_info.device_id);
case TvInputEventType::DEVICE_UNAVAILABLE: {
mHal->onDeviceUnavailable(mEvent.deviceInfo.deviceId);
} break;
case TV_INPUT_EVENT_STREAM_CONFIGURATIONS_CHANGED: {
mHal->onStreamConfigurationsChanged(mEvent.device_info.device_id);
} 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) {
@@ -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);