summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/tv/TvInputHal.java15
-rwxr-xr-xservices/core/java/com/android/server/tv/TvInputHardwareManager.java24
-rw-r--r--services/core/java/com/android/server/tv/TvInputManagerService.java22
-rw-r--r--services/core/jni/Android.bp2
-rw-r--r--services/core/jni/com_android_server_tv_TvInputHal.cpp13
-rw-r--r--services/core/jni/tvinput/JTvInputHal.cpp86
-rw-r--r--services/core/jni/tvinput/JTvInputHal.h41
-rw-r--r--services/core/jni/tvinput/jstruct.h9
8 files changed, 211 insertions, 1 deletions
diff --git a/services/core/java/com/android/server/tv/TvInputHal.java b/services/core/java/com/android/server/tv/TvInputHal.java
index 4bbca335b8e3..c05d148d50d8 100644
--- a/services/core/java/com/android/server/tv/TvInputHal.java
+++ b/services/core/java/com/android/server/tv/TvInputHal.java
@@ -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;
diff --git a/services/core/java/com/android/server/tv/TvInputHardwareManager.java b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
index 077f8d527ab5..9cdceef006d9 100755
--- a/services/core/java/com/android/server/tv/TvInputHardwareManager.java
+++ b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
@@ -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;
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index 1f5c1cf6a959..9cfdd5fb42e7 100644
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -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 {
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index 2ce86add4e58..d5217c8295bd 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -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",
diff --git a/services/core/jni/com_android_server_tv_TvInputHal.cpp b/services/core/jni/com_android_server_tv_TvInputHal.cpp
index a8806b5ef643..1e6384031f9a 100644
--- a/services/core/jni/com_android_server_tv_TvInputHal.cpp
+++ b/services/core/jni/com_android_server_tv_TvInputHal.cpp
@@ -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));
diff --git a/services/core/jni/tvinput/JTvInputHal.cpp b/services/core/jni/tvinput/JTvInputHal.cpp
index 6bb52174fcb2..c494044e8e18 100644
--- a/services/core/jni/tvinput/JTvInputHal.cpp
+++ b/services/core/jni/tvinput/JTvInputHal.cpp
@@ -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
diff --git a/services/core/jni/tvinput/JTvInputHal.h b/services/core/jni/tvinput/JTvInputHal.h
index e29da79d62dd..e8b1c9931372 100644
--- a/services/core/jni/tvinput/JTvInputHal.h
+++ b/services/core/jni/tvinput/JTvInputHal.h
@@ -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;
diff --git a/services/core/jni/tvinput/jstruct.h b/services/core/jni/tvinput/jstruct.h
index 0a4a64dbb40c..23cf4aeaffa9 100644
--- a/services/core/jni/tvinput/jstruct.h
+++ b/services/core/jni/tvinput/jstruct.h
@@ -23,6 +23,7 @@ typedef struct {
jmethodID deviceUnavailable;
jmethodID streamConfigsChanged;
jmethodID firstFrameCaptured;
+ jmethodID tvMessageReceived;
} gTvInputHalClassInfoType;
typedef struct {
@@ -31,6 +32,14 @@ typedef struct {
typedef struct {
jclass clazz;
+ jmethodID constructor;
+ jmethodID putByteArray;
+ jmethodID putString;
+ jmethodID putInt;
+} gBundleClassInfoType;
+
+typedef struct {
+ jclass clazz;
jmethodID constructor;
jmethodID streamId;