From b93ccca6139a7ee2dba5c110e5f8213a2bd231e5 Mon Sep 17 00:00:00 2001 From: Dongwon Kang Date: Thu, 26 Jun 2014 17:59:27 +0900 Subject: [PATCH] Add onChannelRetuned callback in TV Input Framework. Use cases: - Channel change from STB which is bound to a TV input. Bug: 14126559 Change-Id: Icddab61be6cb11162c03960fdb41fee8504bcd61 --- api/current.txt | 2 ++ .../java/android/media/tv/ITvInputClient.aidl | 2 ++ .../media/tv/ITvInputSessionCallback.aidl | 2 ++ .../java/android/media/tv/TvInputManager.java | 31 +++++++++++++++++++ .../java/android/media/tv/TvInputService.java | 19 ++++++++++++ media/java/android/media/tv/TvView.java | 20 ++++++++++++ .../server/tv/TvInputManagerService.java | 21 +++++++++++++ 7 files changed, 97 insertions(+) diff --git a/api/current.txt b/api/current.txt index 92dce76d12dd8..769657b3bbc8f 100644 --- a/api/current.txt +++ b/api/current.txt @@ -16098,6 +16098,7 @@ package android.media.tv { public abstract class TvInputService.Session implements android.view.KeyEvent.Callback { ctor public TvInputService.Session(); + method public void dispatchChannelRetuned(android.net.Uri); method public android.view.View onCreateOverlayView(); method public boolean onGenericMotionEvent(android.view.MotionEvent); method public boolean onKeyDown(int, android.view.KeyEvent); @@ -16135,6 +16136,7 @@ package android.media.tv { public static abstract class TvView.TvInputListener { ctor public TvView.TvInputListener(); + method public void onChannelRetuned(java.lang.String, android.net.Uri); method public void onError(java.lang.String, int); } diff --git a/media/java/android/media/tv/ITvInputClient.aidl b/media/java/android/media/tv/ITvInputClient.aidl index 011da35082fed..285400794bf9e 100644 --- a/media/java/android/media/tv/ITvInputClient.aidl +++ b/media/java/android/media/tv/ITvInputClient.aidl @@ -18,6 +18,7 @@ package android.media.tv; import android.content.ComponentName; import android.media.tv.ITvInputSession; +import android.net.Uri; import android.os.Bundle; import android.view.InputChannel; @@ -34,4 +35,5 @@ oneway interface ITvInputClient { void onVideoStreamChanged(int width, int height, boolean interlaced, int seq); void onAudioStreamChanged(int channelCount, int seq); void onClosedCaptionStreamChanged(boolean hasClosedCaption, int seq); + void onChannelRetuned(in Uri channelUri, int seq); } diff --git a/media/java/android/media/tv/ITvInputSessionCallback.aidl b/media/java/android/media/tv/ITvInputSessionCallback.aidl index 00f2922ad38a3..5a57ccd8e95ae 100644 --- a/media/java/android/media/tv/ITvInputSessionCallback.aidl +++ b/media/java/android/media/tv/ITvInputSessionCallback.aidl @@ -17,6 +17,7 @@ package android.media.tv; import android.media.tv.ITvInputSession; +import android.net.Uri; import android.os.Bundle; /** @@ -30,4 +31,5 @@ oneway interface ITvInputSessionCallback { void onVideoStreamChanged(int width, int height, boolean interlaced); void onAudioStreamChanged(int channelCount); void onClosedCaptionStreamChanged(boolean hasClosedCaption); + void onChannelRetuned(in Uri channelUri); } diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java index daa7009534667..834ce640ed125 100644 --- a/media/java/android/media/tv/TvInputManager.java +++ b/media/java/android/media/tv/TvInputManager.java @@ -124,6 +124,16 @@ public final class TvInputManager { public void onClosedCaptionStreamChanged(Session session, boolean hasClosedCaption) { } + /** + * This is called when the channel of this session is changed by the underlying TV input + * with out any {@link TvInputManager.Session#tune(Uri)} request. + * + * @param session A {@link TvInputManager.Session} associated with this callback + * @param channelUri The URI of a channel. + */ + public void onChannelRetuned(Session session, Uri channelUri) { + } + /** * This is called when a custom event has been sent from this session. * @@ -194,6 +204,15 @@ public final class TvInputManager { }); } + public void postChannelRetuned(final Uri channelUri) { + mHandler.post(new Runnable() { + @Override + public void run() { + mSessionCallback.onChannelRetuned(mSession, channelUri); + } + }); + } + public void postSessionEvent(final String eventType, final Bundle eventArgs) { mHandler.post(new Runnable() { @Override @@ -317,6 +336,18 @@ public final class TvInputManager { } } + @Override + public void onChannelRetuned(Uri channelUri, int seq) { + synchronized (mSessionCallbackRecordMap) { + SessionCallbackRecord record = mSessionCallbackRecordMap.get(seq); + if (record == null) { + Log.e(TAG, "Callback not found for seq " + seq); + return; + } + record.postChannelRetuned(channelUri); + } + } + @Override public void onSessionEvent(String eventType, Bundle eventArgs, int seq) { synchronized (mSessionCallbackRecordMap) { diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java index 0f4a9300893b4..1e512cd412130 100644 --- a/media/java/android/media/tv/TvInputService.java +++ b/media/java/android/media/tv/TvInputService.java @@ -285,6 +285,25 @@ public abstract class TvInputService extends Service { }); } + /** + * Notifies the channel of the session is retuned by TV input. + * + * @param channelUri The URI of a channel. + */ + public void dispatchChannelRetuned(final Uri channelUri) { + mHandler.post(new Runnable() { + @Override + public void run() { + try { + if (DEBUG) Log.d(TAG, "dispatchChannelRetuned"); + mSessionCallback.onChannelRetuned(channelUri); + } catch (RemoteException e) { + Log.w(TAG, "error in dispatchChannelRetuned"); + } + } + }); + } + /** * Called when the session is released. */ diff --git a/media/java/android/media/tv/TvView.java b/media/java/android/media/tv/TvView.java index a913e59c502b9..664a215f12803 100644 --- a/media/java/android/media/tv/TvView.java +++ b/media/java/android/media/tv/TvView.java @@ -455,6 +455,16 @@ public class TvView extends ViewGroup { public void onClosedCaptionStreamChanged(String inputId, boolean hasClosedCaption) { } + /** + * This is invoked when the channel of this TvView is changed by the underlying TV input + * with out any {@link TvView#tune(String, Uri)} request. + * + * @param inputId The ID of the TV input bound to this view. + * @param channelUri The URI of a channel. + */ + public void onChannelRetuned(String inputId, Uri channelUri) { + } + /** * This is invoked when a custom event from the bound TV input is sent to this view. * @@ -561,6 +571,16 @@ public class TvView extends ViewGroup { } } + @Override + public void onChannelRetuned(Session session, Uri channelUri) { + if (DEBUG) { + Log.d(TAG, "onChannelChangedByTvInput(" + channelUri + ")"); + } + if (mListener != null) { + mListener.onChannelRetuned(mInputId, channelUri); + } + } + @Override public void onSessionEvent(TvInputManager.Session session, String eventType, Bundle eventArgs) { diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java index 02dd1bf4dac0c..bf767e2376293 100644 --- a/services/core/java/com/android/server/tv/TvInputManagerService.java +++ b/services/core/java/com/android/server/tv/TvInputManagerService.java @@ -484,6 +484,27 @@ public final class TvInputManagerService extends SystemService { } } + @Override + public void onChannelRetuned(Uri channelUri) { + synchronized (mLock) { + if (DEBUG) { + Slog.d(TAG, "onChannelRetuned(" + channelUri + ")"); + } + if (sessionState.mSession == null || sessionState.mClient == null) { + return; + } + try { + // TODO: Consider adding this channel change in the watch log. When we do + // that, how we can protect the watch log from malicious tv inputs should + // be addressed. e.g. add a field which represents where the channel change + // originated from. + sessionState.mClient.onChannelRetuned(channelUri, sessionState.mSeq); + } catch (RemoteException e) { + Slog.e(TAG, "error in onChannelRetuned"); + } + } + } + @Override public void onSessionEvent(String eventType, Bundle eventArgs) { synchronized (mLock) {