diff options
| -rw-r--r-- | services/core/java/com/android/server/tv/TvInputHal.java | 108 | ||||
| -rw-r--r-- | services/core/jni/com_android_server_tv_TvInputHal.cpp | 1 |
2 files changed, 80 insertions, 29 deletions
diff --git a/services/core/java/com/android/server/tv/TvInputHal.java b/services/core/java/com/android/server/tv/TvInputHal.java index 1535e7a9a934..23c0a4ccd984 100644 --- a/services/core/java/com/android/server/tv/TvInputHal.java +++ b/services/core/java/com/android/server/tv/TvInputHal.java @@ -20,12 +20,19 @@ import android.media.tv.TvInputHardwareInfo; import android.media.tv.TvStreamConfig; import android.os.Handler; import android.os.HandlerThread; +import android.os.Message; import android.view.Surface; +import android.util.Slog; + +import java.util.LinkedList; +import java.util.Queue; /** * Provides access to the low-level TV input hardware abstraction layer. */ -final class TvInputHal { +final class TvInputHal implements Handler.Callback { + private final static String TAG = TvInputHal.class.getSimpleName(); + public final static int SUCCESS = 0; public final static int ERROR_NO_INIT = -1; public final static int ERROR_STALE_CONFIG = -2; @@ -35,6 +42,12 @@ final class TvInputHal { public static final int TYPE_BUILT_IN_TUNER = 2; public static final int TYPE_PASSTHROUGH = 3; + public static final int EVENT_OPEN = 0; + // Below should be in sync with hardware/libhardware/include/hardware/tv_input.h + public static final int EVENT_DEVICE_AVAILABLE = 1; + public static final int EVENT_DEVICE_UNAVAILABLE = 2; + public static final int EVENT_STREAM_CONFIGURATION_CHANGED = 3; + public interface Callback { public void onDeviceAvailable( TvInputHardwareInfo info, TvStreamConfig[] configs); @@ -50,7 +63,7 @@ final class TvInputHal { int generation); private static native void nativeClose(long ptr); - private long mPtr = 0l; + private volatile long mPtr = 0; private final Callback mCallback; private final HandlerThread mThread = new HandlerThread("TV input HAL event thread"); private final Handler mHandler; @@ -60,21 +73,23 @@ final class TvInputHal { public TvInputHal(Callback callback) { mCallback = callback; mThread.start(); - mHandler = new Handler(mThread.getLooper()); + mHandler = new Handler(mThread.getLooper(), this); } public void init() { mPtr = nativeOpen(); + mHandler.sendEmptyMessage(EVENT_OPEN); } public int setSurface(int deviceId, Surface surface, TvStreamConfig streamConfig) { - if (mPtr == 0) { + long ptr = mPtr; + if (ptr == 0) { return ERROR_NO_INIT; } if (mStreamConfigGeneration != streamConfig.getGeneration()) { return ERROR_STALE_CONFIG; } - if (nativeSetSurface(mPtr, deviceId, streamConfig.getStreamId(), surface) == 0) { + if (nativeSetSurface(ptr, deviceId, streamConfig.getStreamId(), surface) == 0) { return SUCCESS; } else { return ERROR_UNKNOWN; @@ -82,44 +97,81 @@ final class TvInputHal { } public void close() { - if (mPtr != 0l) { - nativeClose(mPtr); + long ptr = mPtr; + if (ptr != 0l) { + nativeClose(ptr); mThread.quitSafely(); } } - private synchronized void retrieveStreamConfigs(int deviceId) { + private synchronized void retrieveStreamConfigs(long ptr, int deviceId) { ++mStreamConfigGeneration; - mStreamConfigs = nativeGetStreamConfigs(mPtr, deviceId, mStreamConfigGeneration); + mStreamConfigs = nativeGetStreamConfigs(ptr, deviceId, mStreamConfigGeneration); } // Called from native - private void deviceAvailableFromNative(final TvInputHardwareInfo info) { - mHandler.post(new Runnable() { - @Override - public void run() { - retrieveStreamConfigs(info.getDeviceId()); + private void deviceAvailableFromNative(TvInputHardwareInfo info) { + mHandler.sendMessage( + mHandler.obtainMessage(EVENT_DEVICE_AVAILABLE, info)); + } + + private void deviceUnavailableFromNative(int deviceId) { + mHandler.sendMessage( + mHandler.obtainMessage(EVENT_DEVICE_UNAVAILABLE, deviceId, 0)); + } + + private void streamConfigsChangedFromNative(int deviceId) { + mHandler.sendMessage( + mHandler.obtainMessage(EVENT_STREAM_CONFIGURATION_CHANGED, deviceId, 0)); + } + + // Handler.Callback implementation + + private Queue<Message> mPendingMessageQueue = new LinkedList<Message>(); + + @Override + public boolean handleMessage(Message msg) { + long ptr = mPtr; + if (ptr == 0) { + mPendingMessageQueue.add(msg); + return true; + } + while (!mPendingMessageQueue.isEmpty()) { + handleMessageInternal(ptr, mPendingMessageQueue.remove()); + } + handleMessageInternal(ptr, msg); + return true; + } + + private void handleMessageInternal(long ptr, Message msg) { + switch (msg.what) { + case EVENT_OPEN: + // No-op + break; + + case EVENT_DEVICE_AVAILABLE: { + TvInputHardwareInfo info = (TvInputHardwareInfo)msg.obj; + retrieveStreamConfigs(ptr, info.getDeviceId()); mCallback.onDeviceAvailable(info, mStreamConfigs); + break; } - }); - } - private void deviceUnavailableFromNative(final int deviceId) { - mHandler.post(new Runnable() { - @Override - public void run() { + case EVENT_DEVICE_UNAVAILABLE: { + int deviceId = msg.arg1; mCallback.onDeviceUnavailable(deviceId); + break; } - }); - } - private void streamConfigsChangedFromNative(final int deviceId) { - mHandler.post(new Runnable() { - @Override - public void run() { - retrieveStreamConfigs(deviceId); + case EVENT_STREAM_CONFIGURATION_CHANGED: { + int deviceId = msg.arg1; + retrieveStreamConfigs(ptr, deviceId); mCallback.onStreamConfigurationChanged(deviceId, mStreamConfigs); + break; } - }); + + default: + Slog.e(TAG, "Unknown event: " + msg); + break; + } } } diff --git a/services/core/jni/com_android_server_tv_TvInputHal.cpp b/services/core/jni/com_android_server_tv_TvInputHal.cpp index 9cecdf0612d9..7b8e6fdb4d06 100644 --- a/services/core/jni/com_android_server_tv_TvInputHal.cpp +++ b/services/core/jni/com_android_server_tv_TvInputHal.cpp @@ -75,7 +75,6 @@ public: static JTvInputHal* createInstance(JNIEnv* env, jobject thiz); int setSurface(int deviceId, int streamId, const sp<Surface>& surface); - void getStreamConfigs(int deviceId, jobjectArray* array); const tv_stream_config_t* getStreamConfigs(int deviceId, int* numConfigs); private: |