Merge "Extend JNI for TVMessages" into udc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
548abaa0e6
@@ -19,6 +19,7 @@ package com.android.server.tv;
|
||||
import android.hardware.tv.input.V1_0.Constants;
|
||||
import android.media.tv.TvInputHardwareInfo;
|
||||
import android.media.tv.TvStreamConfig;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.os.MessageQueue;
|
||||
@@ -45,12 +46,15 @@ final class TvInputHal implements Handler.Callback {
|
||||
Constants.EVENT_STREAM_CONFIGURATIONS_CHANGED;
|
||||
public static final int EVENT_FIRST_FRAME_CAPTURED = 4;
|
||||
|
||||
public static final int EVENT_TV_MESSAGE = 5;
|
||||
|
||||
public interface Callback {
|
||||
void onDeviceAvailable(TvInputHardwareInfo info, TvStreamConfig[] configs);
|
||||
void onDeviceUnavailable(int deviceId);
|
||||
void onStreamConfigurationChanged(int deviceId, TvStreamConfig[] configs,
|
||||
int cableConnectionStatus);
|
||||
void onFirstFrameCaptured(int deviceId, int streamId);
|
||||
void onTvMessage(int deviceId, int type, Bundle data);
|
||||
}
|
||||
|
||||
private native long nativeOpen(MessageQueue queue);
|
||||
@@ -171,6 +175,10 @@ final class TvInputHal implements Handler.Callback {
|
||||
mHandler.obtainMessage(EVENT_STREAM_CONFIGURATION_CHANGED, deviceId, streamId));
|
||||
}
|
||||
|
||||
private void tvMessageReceivedFromNative(int deviceId, int type, Bundle data) {
|
||||
mHandler.obtainMessage(EVENT_TV_MESSAGE, deviceId, type, data).sendToTarget();
|
||||
}
|
||||
|
||||
// Handler.Callback implementation
|
||||
|
||||
@Override
|
||||
@@ -221,6 +229,13 @@ final class TvInputHal implements Handler.Callback {
|
||||
break;
|
||||
}
|
||||
|
||||
case EVENT_TV_MESSAGE: {
|
||||
int deviceId = msg.arg1;
|
||||
int type = msg.arg2;
|
||||
Bundle data = (Bundle) msg.obj;
|
||||
mCallback.onTvMessage(deviceId, type, data);
|
||||
}
|
||||
|
||||
default:
|
||||
Slog.e(TAG, "Unknown event: " + msg);
|
||||
return false;
|
||||
|
||||
@@ -48,6 +48,7 @@ import android.media.tv.TvInputService.PriorityHintUseCaseType;
|
||||
import android.media.tv.TvStreamConfig;
|
||||
import android.media.tv.tunerresourcemanager.ResourceClientProfile;
|
||||
import android.media.tv.tunerresourcemanager.TunerResourceManager;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.Message;
|
||||
@@ -59,6 +60,7 @@ import android.util.SparseArray;
|
||||
import android.util.SparseBooleanArray;
|
||||
import android.view.Surface;
|
||||
|
||||
import com.android.internal.os.SomeArgs;
|
||||
import com.android.internal.util.DumpUtils;
|
||||
import com.android.internal.util.IndentingPrintWriter;
|
||||
import com.android.server.SystemService;
|
||||
@@ -264,6 +266,17 @@ class TvInputHardwareManager implements TvInputHal.Callback {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTvMessage(int deviceId, int type, Bundle data) {
|
||||
synchronized (mLock) {
|
||||
SomeArgs args = SomeArgs.obtain();
|
||||
args.arg1 = mHardwareInputIdMap.get(deviceId);
|
||||
args.arg2 = data;
|
||||
mHandler.obtainMessage(ListenerHandler.TV_MESSAGE_RECEIVED, type, 0, args)
|
||||
.sendToTarget();
|
||||
}
|
||||
}
|
||||
|
||||
public List<TvInputHardwareInfo> getHardwareList() {
|
||||
synchronized (mLock) {
|
||||
return Collections.unmodifiableList(mHardwareList);
|
||||
@@ -1224,6 +1237,7 @@ class TvInputHardwareManager implements TvInputHal.Callback {
|
||||
void onHdmiDeviceAdded(HdmiDeviceInfo device);
|
||||
void onHdmiDeviceRemoved(HdmiDeviceInfo device);
|
||||
void onHdmiDeviceUpdated(String inputId, HdmiDeviceInfo device);
|
||||
void onTvMessage(String inputId, int type, Bundle data);
|
||||
}
|
||||
|
||||
private class ListenerHandler extends Handler {
|
||||
@@ -1234,6 +1248,7 @@ class TvInputHardwareManager implements TvInputHal.Callback {
|
||||
private static final int HDMI_DEVICE_REMOVED = 5;
|
||||
private static final int HDMI_DEVICE_UPDATED = 6;
|
||||
private static final int TVINPUT_INFO_ADDED = 7;
|
||||
private static final int TV_MESSAGE_RECEIVED = 8;
|
||||
|
||||
@Override
|
||||
public final void handleMessage(Message msg) {
|
||||
@@ -1303,6 +1318,15 @@ class TvInputHardwareManager implements TvInputHal.Callback {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TV_MESSAGE_RECEIVED: {
|
||||
SomeArgs args = (SomeArgs) msg.obj;
|
||||
String inputId = (String) args.arg1;
|
||||
Bundle data = (Bundle) args.arg2;
|
||||
int type = msg.arg1;
|
||||
mListener.onTvMessage(inputId, type, data);
|
||||
args.recycle();
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
Slog.w(TAG, "Unhandled message: " + msg);
|
||||
break;
|
||||
|
||||
@@ -4146,6 +4146,28 @@ public final class TvInputManagerService extends SystemService {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTvMessage(String inputId, int type, Bundle data) {
|
||||
synchronized (mLock) {
|
||||
UserState userState = getOrCreateUserStateLocked(mCurrentUserId);
|
||||
TvInputState inputState = userState.inputMap.get(inputId);
|
||||
ServiceState serviceState = userState.serviceStateMap.get(inputState.info
|
||||
.getComponent());
|
||||
for (IBinder token : serviceState.sessionTokens) {
|
||||
try {
|
||||
SessionState sessionState = getSessionStateLocked(token,
|
||||
Binder.getCallingUid(), mCurrentUserId);
|
||||
if (!sessionState.isRecordingSession
|
||||
&& sessionState.hardwareSessionToken != null) {
|
||||
sessionState.session.notifyTvMessage(type, data);
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(TAG, "error in onTvMessage", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class SessionNotFoundException extends IllegalArgumentException {
|
||||
|
||||
@@ -109,6 +109,7 @@ cc_defaults {
|
||||
"libchrome",
|
||||
"libcutils",
|
||||
"libcrypto",
|
||||
"libfmq",
|
||||
"liblog",
|
||||
"libgraphicsenv",
|
||||
"libgralloctypes",
|
||||
@@ -157,6 +158,7 @@ cc_defaults {
|
||||
"android.hardware.broadcastradio@1.0",
|
||||
"android.hardware.broadcastradio@1.1",
|
||||
"android.hardware.contexthub@1.0",
|
||||
"android.hardware.common.fmq-V1-ndk",
|
||||
"android.hardware.gnss-V3-cpp",
|
||||
"android.hardware.gnss@1.0",
|
||||
"android.hardware.gnss@1.1",
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
#include "tvinput/JTvInputHal.h"
|
||||
|
||||
gBundleClassInfoType gBundleClassInfo;
|
||||
gTvInputHalClassInfoType gTvInputHalClassInfo;
|
||||
gTvStreamConfigClassInfoType gTvStreamConfigClassInfo;
|
||||
gTvStreamConfigBuilderClassInfoType gTvStreamConfigBuilderClassInfo;
|
||||
@@ -133,10 +134,22 @@ int register_android_server_tv_TvInputHal(JNIEnv* env) {
|
||||
GET_METHOD_ID(
|
||||
gTvInputHalClassInfo.firstFrameCaptured, clazz,
|
||||
"firstFrameCapturedFromNative", "(II)V");
|
||||
GET_METHOD_ID(gTvInputHalClassInfo.tvMessageReceived, clazz, "tvMessageReceivedFromNative",
|
||||
"(IILandroid/os/Bundle;)V");
|
||||
|
||||
FIND_CLASS(gTvStreamConfigClassInfo.clazz, "android/media/tv/TvStreamConfig");
|
||||
gTvStreamConfigClassInfo.clazz = jclass(env->NewGlobalRef(gTvStreamConfigClassInfo.clazz));
|
||||
|
||||
FIND_CLASS(gBundleClassInfo.clazz, "android/os/Bundle");
|
||||
gBundleClassInfo.clazz = jclass(env->NewGlobalRef(gBundleClassInfo.clazz));
|
||||
GET_METHOD_ID(gBundleClassInfo.constructor, gBundleClassInfo.clazz, "<init>", "()V");
|
||||
GET_METHOD_ID(gBundleClassInfo.putByteArray, gBundleClassInfo.clazz, "putByteArray",
|
||||
"(Ljava/lang/String;[B)V");
|
||||
GET_METHOD_ID(gBundleClassInfo.putString, gBundleClassInfo.clazz, "putString",
|
||||
"(Ljava/lang/String;Ljava/lang/String;)V");
|
||||
GET_METHOD_ID(gBundleClassInfo.putInt, gBundleClassInfo.clazz, "putInt",
|
||||
"(Ljava/lang/String;I)V");
|
||||
|
||||
FIND_CLASS(gTvStreamConfigBuilderClassInfo.clazz, "android/media/tv/TvStreamConfig$Builder");
|
||||
gTvStreamConfigBuilderClassInfo.clazz =
|
||||
jclass(env->NewGlobalRef(gTvStreamConfigBuilderClassInfo.clazz));
|
||||
|
||||
@@ -275,6 +275,26 @@ void JTvInputHal::onStreamConfigurationsChanged(int deviceId, int cableConnectio
|
||||
cableConnectionStatus);
|
||||
}
|
||||
|
||||
void JTvInputHal::onTvMessage(int deviceId, int streamId, AidlTvMessageEventType type,
|
||||
AidlTvMessage& message, signed char data[], int dataLength) {
|
||||
JNIEnv* env = AndroidRuntime::getJNIEnv();
|
||||
jobject bundle = env->NewObject(gBundleClassInfo.clazz, gBundleClassInfo.constructor);
|
||||
const jsize len = static_cast<jsize>(dataLength);
|
||||
jbyteArray convertedData = env->NewByteArray(len);
|
||||
env->SetByteArrayRegion(convertedData, 0, len, reinterpret_cast<const jbyte*>(data));
|
||||
env->CallObjectMethod(bundle, gBundleClassInfo.putString,
|
||||
"android.media.tv.TvInputManager.subtype", message.subType.c_str());
|
||||
env->CallObjectMethod(bundle, gBundleClassInfo.putByteArray,
|
||||
"android.media.tv.TvInputManager.raw_data", convertedData);
|
||||
env->CallObjectMethod(bundle, gBundleClassInfo.putInt,
|
||||
"android.media.tv.TvInputManager.group_id", message.groupId);
|
||||
env->CallObjectMethod(bundle, gBundleClassInfo.putInt,
|
||||
"android.media.tv.TvInputManager.stream_id", streamId);
|
||||
env->CallVoidMethod(mThiz, gTvInputHalClassInfo.tvMessageReceived, deviceId,
|
||||
static_cast<int>(type), bundle);
|
||||
env->DeleteLocalRef(convertedData);
|
||||
}
|
||||
|
||||
void JTvInputHal::onCaptured(int deviceId, int streamId, uint32_t seq, bool succeeded) {
|
||||
sp<BufferProducerThread> thread;
|
||||
{
|
||||
@@ -316,6 +336,17 @@ JTvInputHal::TvInputEventWrapper JTvInputHal::TvInputEventWrapper::createEventWr
|
||||
return event;
|
||||
}
|
||||
|
||||
JTvInputHal::TvMessageEventWrapper JTvInputHal::TvMessageEventWrapper::createEventWrapper(
|
||||
const AidlTvMessageEvent& aidlTvMessageEvent) {
|
||||
TvMessageEventWrapper event;
|
||||
event.messages.insert(event.messages.begin(), std::begin(aidlTvMessageEvent.messages) + 1,
|
||||
std::end(aidlTvMessageEvent.messages));
|
||||
event.streamId = aidlTvMessageEvent.streamId;
|
||||
event.deviceId = aidlTvMessageEvent.messages[0].groupId;
|
||||
event.type = aidlTvMessageEvent.type;
|
||||
return event;
|
||||
}
|
||||
|
||||
JTvInputHal::NotifyHandler::NotifyHandler(JTvInputHal* hal, const TvInputEventWrapper& event) {
|
||||
mHal = hal;
|
||||
mEvent = event;
|
||||
@@ -338,6 +369,41 @@ void JTvInputHal::NotifyHandler::handleMessage(const Message& message) {
|
||||
}
|
||||
}
|
||||
|
||||
JTvInputHal::NotifyTvMessageHandler::NotifyTvMessageHandler(JTvInputHal* hal,
|
||||
const TvMessageEventWrapper& event) {
|
||||
mHal = hal;
|
||||
mEvent = event;
|
||||
}
|
||||
|
||||
void JTvInputHal::NotifyTvMessageHandler::handleMessage(const Message& message) {
|
||||
std::shared_ptr<AidlMessageQueue<int8_t, SynchronizedReadWrite>> queue =
|
||||
mHal->mQueueMap[mEvent.deviceId][mEvent.streamId];
|
||||
for (AidlTvMessage item : mEvent.messages) {
|
||||
if (queue == NULL || !queue->isValid() || queue->availableToRead() < item.dataLengthBytes) {
|
||||
MQDescriptor<int8_t, SynchronizedReadWrite> queueDesc;
|
||||
if (mHal->mTvInput->getTvMessageQueueDesc(&queueDesc, mEvent.deviceId, mEvent.streamId)
|
||||
.isOk()) {
|
||||
queue = std::make_shared<AidlMessageQueue<int8_t, SynchronizedReadWrite>>(queueDesc,
|
||||
false);
|
||||
}
|
||||
if (queue == NULL || !queue->isValid() ||
|
||||
queue->availableToRead() < item.dataLengthBytes) {
|
||||
ALOGE("Incomplete TvMessageQueue data or missing queue");
|
||||
return;
|
||||
}
|
||||
mHal->mQueueMap[mEvent.deviceId][mEvent.streamId] = queue;
|
||||
}
|
||||
signed char* buffer = new signed char[item.dataLengthBytes];
|
||||
if (queue->read(buffer, item.dataLengthBytes)) {
|
||||
mHal->onTvMessage(mEvent.deviceId, mEvent.streamId, mEvent.type, item, buffer,
|
||||
item.dataLengthBytes);
|
||||
} else {
|
||||
ALOGE("Failed to read from TvMessageQueue");
|
||||
}
|
||||
delete[] buffer;
|
||||
}
|
||||
}
|
||||
|
||||
JTvInputHal::TvInputCallback::TvInputCallback(JTvInputHal* hal) {
|
||||
mHal = hal;
|
||||
}
|
||||
@@ -351,7 +417,15 @@ JTvInputHal::TvInputCallback::TvInputCallback(JTvInputHal* hal) {
|
||||
|
||||
::ndk::ScopedAStatus JTvInputHal::TvInputCallback::notifyTvMessageEvent(
|
||||
const AidlTvMessageEvent& event) {
|
||||
// TODO: Implement this
|
||||
const std::string DEVICE_ID_SUBTYPE = "device_id";
|
||||
if (sizeof(event.messages) > 0 && event.messages[0].subType == DEVICE_ID_SUBTYPE) {
|
||||
mHal->mLooper
|
||||
->sendMessage(new NotifyTvMessageHandler(mHal,
|
||||
TvMessageEventWrapper::createEventWrapper(
|
||||
event)),
|
||||
static_cast<int>(event.type));
|
||||
}
|
||||
|
||||
return ::ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
@@ -406,4 +480,14 @@ JTvInputHal::ITvInputWrapper::ITvInputWrapper(std::shared_ptr<AidlITvInput>& aid
|
||||
}
|
||||
}
|
||||
|
||||
::ndk::ScopedAStatus JTvInputHal::ITvInputWrapper::getTvMessageQueueDesc(
|
||||
MQDescriptor<int8_t, SynchronizedReadWrite>* out_queue, int32_t in_deviceId,
|
||||
int32_t in_streamId) {
|
||||
if (mIsHidl) {
|
||||
return ::ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
|
||||
} else {
|
||||
return mAidlTvInput->getTvMessageQueueDesc(out_queue, in_deviceId, in_streamId);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <aidl/android/media/audio/common/AudioDevice.h>
|
||||
#include <aidlcommonsupport/NativeHandle.h>
|
||||
#include <android/binder_manager.h>
|
||||
#include <fmq/AidlMessageQueue.h>
|
||||
#include <nativehelper/JNIHelp.h>
|
||||
#include <utils/Errors.h>
|
||||
#include <utils/KeyedVector.h>
|
||||
@@ -40,6 +41,10 @@
|
||||
#include "android_runtime/android_view_Surface.h"
|
||||
#include "tvinput/jstruct.h"
|
||||
|
||||
using ::android::AidlMessageQueue;
|
||||
|
||||
using ::aidl::android::hardware::common::fmq::MQDescriptor;
|
||||
using ::aidl::android::hardware::common::fmq::SynchronizedReadWrite;
|
||||
using ::aidl::android::hardware::tv::input::BnTvInputCallback;
|
||||
using ::aidl::android::hardware::tv::input::CableConnectionStatus;
|
||||
using ::aidl::android::hardware::tv::input::TvInputEventType;
|
||||
@@ -54,10 +59,16 @@ using AidlITvInput = ::aidl::android::hardware::tv::input::ITvInput;
|
||||
using AidlNativeHandle = ::aidl::android::hardware::common::NativeHandle;
|
||||
using AidlTvInputDeviceInfo = ::aidl::android::hardware::tv::input::TvInputDeviceInfo;
|
||||
using AidlTvInputEvent = ::aidl::android::hardware::tv::input::TvInputEvent;
|
||||
using AidlTvMessage = ::aidl::android::hardware::tv::input::TvMessage;
|
||||
using AidlTvMessageEvent = ::aidl::android::hardware::tv::input::TvMessageEvent;
|
||||
using AidlTvMessageEventType = ::aidl::android::hardware::tv::input::TvMessageEventType;
|
||||
using AidlTvStreamConfig = ::aidl::android::hardware::tv::input::TvStreamConfig;
|
||||
|
||||
using AidlMessageQueueMap = std::unordered_map<
|
||||
int,
|
||||
std::unordered_map<int, std::shared_ptr<AidlMessageQueue<int8_t, SynchronizedReadWrite>>>>;
|
||||
|
||||
extern gBundleClassInfoType gBundleClassInfo;
|
||||
extern gTvInputHalClassInfoType gTvInputHalClassInfo;
|
||||
extern gTvStreamConfigClassInfoType gTvStreamConfigClassInfo;
|
||||
extern gTvStreamConfigBuilderClassInfoType gTvStreamConfigBuilderClassInfo;
|
||||
@@ -121,6 +132,19 @@ private:
|
||||
TvInputDeviceInfoWrapper deviceInfo;
|
||||
};
|
||||
|
||||
class TvMessageEventWrapper {
|
||||
public:
|
||||
TvMessageEventWrapper() {}
|
||||
|
||||
static TvMessageEventWrapper createEventWrapper(
|
||||
const AidlTvMessageEvent& aidlTvMessageEvent);
|
||||
|
||||
int streamId;
|
||||
int deviceId;
|
||||
std::vector<AidlTvMessage> messages;
|
||||
AidlTvMessageEventType type;
|
||||
};
|
||||
|
||||
class NotifyHandler : public MessageHandler {
|
||||
public:
|
||||
NotifyHandler(JTvInputHal* hal, const TvInputEventWrapper& event);
|
||||
@@ -132,6 +156,17 @@ private:
|
||||
JTvInputHal* mHal;
|
||||
};
|
||||
|
||||
class NotifyTvMessageHandler : public MessageHandler {
|
||||
public:
|
||||
NotifyTvMessageHandler(JTvInputHal* hal, const TvMessageEventWrapper& event);
|
||||
|
||||
void handleMessage(const Message& message) override;
|
||||
|
||||
private:
|
||||
TvMessageEventWrapper mEvent;
|
||||
JTvInputHal* mHal;
|
||||
};
|
||||
|
||||
class TvInputCallback : public HidlITvInputCallback, public BnTvInputCallback {
|
||||
public:
|
||||
explicit TvInputCallback(JTvInputHal* hal);
|
||||
@@ -156,6 +191,9 @@ private:
|
||||
::ndk::ScopedAStatus closeStream(int32_t in_deviceId, int32_t in_streamId);
|
||||
::ndk::ScopedAStatus setTvMessageEnabled(int32_t deviceId, int32_t streamId,
|
||||
TvMessageEventType in_type, bool enabled);
|
||||
::ndk::ScopedAStatus getTvMessageQueueDesc(
|
||||
MQDescriptor<int8_t, SynchronizedReadWrite>* out_queue, int32_t in_deviceId,
|
||||
int32_t in_streamId);
|
||||
|
||||
private:
|
||||
::ndk::ScopedAStatus hidlSetCallback(const std::shared_ptr<TvInputCallback>& in_callback);
|
||||
@@ -178,11 +216,14 @@ private:
|
||||
void onDeviceUnavailable(int deviceId);
|
||||
void onStreamConfigurationsChanged(int deviceId, int cableConnectionStatus);
|
||||
void onCaptured(int deviceId, int streamId, uint32_t seq, bool succeeded);
|
||||
void onTvMessage(int deviceId, int streamId, AidlTvMessageEventType type,
|
||||
AidlTvMessage& message, signed char data[], int dataLength);
|
||||
|
||||
Mutex mLock;
|
||||
Mutex mStreamLock;
|
||||
jweak mThiz;
|
||||
sp<Looper> mLooper;
|
||||
AidlMessageQueueMap mQueueMap;
|
||||
|
||||
KeyedVector<int, KeyedVector<int, Connection> > mConnections;
|
||||
|
||||
|
||||
@@ -23,12 +23,21 @@ typedef struct {
|
||||
jmethodID deviceUnavailable;
|
||||
jmethodID streamConfigsChanged;
|
||||
jmethodID firstFrameCaptured;
|
||||
jmethodID tvMessageReceived;
|
||||
} gTvInputHalClassInfoType;
|
||||
|
||||
typedef struct {
|
||||
jclass clazz;
|
||||
} gTvStreamConfigClassInfoType;
|
||||
|
||||
typedef struct {
|
||||
jclass clazz;
|
||||
jmethodID constructor;
|
||||
jmethodID putByteArray;
|
||||
jmethodID putString;
|
||||
jmethodID putInt;
|
||||
} gBundleClassInfoType;
|
||||
|
||||
typedef struct {
|
||||
jclass clazz;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user