From a759b111a1c9cb00284038f8a1554bf29709b952 Mon Sep 17 00:00:00 2001 From: Jae Seo Date: Fri, 18 Jul 2014 22:16:08 -0700 Subject: [PATCH] TIF: Add sendAppPrivateCommand() Added a way to send a private command from the application to the TV input. This can be used to provide domain-specific features that are only known between certain TV inputs and their clients. Change-Id: I7548311a64147b8ff27562ec680b941e2ec10bc0 --- .../android/media/tv/ITvInputManager.aidl | 4 ++++ .../android/media/tv/ITvInputSession.aidl | 3 +++ .../media/tv/ITvInputSessionWrapper.java | 22 +++++++++++++---- .../java/android/media/tv/TvInputManager.java | 24 +++++++++++++++++++ .../java/android/media/tv/TvInputService.java | 22 +++++++++++++++++ media/java/android/media/tv/TvView.java | 21 ++++++++++++++++ .../server/tv/TvInputManagerService.java | 21 ++++++++++++++++ 7 files changed, 113 insertions(+), 4 deletions(-) diff --git a/media/java/android/media/tv/ITvInputManager.aidl b/media/java/android/media/tv/ITvInputManager.aidl index 7cf619dd51eac..ccfc4843d88c6 100644 --- a/media/java/android/media/tv/ITvInputManager.aidl +++ b/media/java/android/media/tv/ITvInputManager.aidl @@ -26,6 +26,7 @@ import android.media.tv.TvInputHardwareInfo; import android.media.tv.TvInputInfo; import android.media.tv.TvTrackInfo; import android.net.Uri; +import android.os.Bundle; import android.view.Surface; /** @@ -51,6 +52,9 @@ interface ITvInputManager { void selectTrack(in IBinder sessionToken, in TvTrackInfo track, int userId); void unselectTrack(in IBinder sessionToken, in TvTrackInfo track, int userId); + void sendAppPrivateCommand(in IBinder sessionToken, in String action, in Bundle data, + int userId); + void createOverlayView(in IBinder sessionToken, in IBinder windowToken, in Rect frame, int userId); void relayoutOverlayView(in IBinder sessionToken, in Rect frame, int userId); diff --git a/media/java/android/media/tv/ITvInputSession.aidl b/media/java/android/media/tv/ITvInputSession.aidl index efcb1c67dc663..c5c1f14b6d899 100644 --- a/media/java/android/media/tv/ITvInputSession.aidl +++ b/media/java/android/media/tv/ITvInputSession.aidl @@ -19,6 +19,7 @@ package android.media.tv; import android.graphics.Rect; import android.media.tv.TvTrackInfo; import android.net.Uri; +import android.os.Bundle; import android.view.Surface; /** @@ -38,6 +39,8 @@ oneway interface ITvInputSession { void selectTrack(in TvTrackInfo track); void unselectTrack(in TvTrackInfo track); + void appPrivateCommand(in String action, in Bundle data); + void createOverlayView(in IBinder windowToken, in Rect frame); void relayoutOverlayView(in Rect frame); void removeOverlayView(); diff --git a/media/java/android/media/tv/ITvInputSessionWrapper.java b/media/java/android/media/tv/ITvInputSessionWrapper.java index 9683040872873..bdc59aca3da92 100644 --- a/media/java/android/media/tv/ITvInputSessionWrapper.java +++ b/media/java/android/media/tv/ITvInputSessionWrapper.java @@ -19,6 +19,7 @@ package android.media.tv; import android.content.Context; import android.graphics.Rect; import android.net.Uri; +import android.os.Bundle; import android.os.IBinder; import android.os.Looper; import android.os.Message; @@ -48,10 +49,11 @@ public class ITvInputSessionWrapper extends ITvInputSession.Stub implements Hand private static final int DO_SET_CAPTION_ENABLED = 6; private static final int DO_SELECT_TRACK = 7; private static final int DO_UNSELECT_TRACK = 8; - private static final int DO_CREATE_OVERLAY_VIEW = 9; - private static final int DO_RELAYOUT_OVERLAY_VIEW = 10; - private static final int DO_REMOVE_OVERLAY_VIEW = 11; - private static final int DO_REQUEST_UNBLOCK_CONTENT = 12; + private static final int DO_APP_PRIVATE_COMMAND = 9; + private static final int DO_CREATE_OVERLAY_VIEW = 10; + private static final int DO_RELAYOUT_OVERLAY_VIEW = 11; + private static final int DO_REMOVE_OVERLAY_VIEW = 12; + private static final int DO_REQUEST_UNBLOCK_CONTENT = 13; private final HandlerCaller mCaller; @@ -119,6 +121,12 @@ public class ITvInputSessionWrapper extends ITvInputSession.Stub implements Hand mTvInputSessionImpl.unselectTrack((TvTrackInfo) msg.obj); return; } + case DO_APP_PRIVATE_COMMAND: { + SomeArgs args = (SomeArgs) msg.obj; + mTvInputSessionImpl.appPrivateCommand((String) args.arg1, (Bundle) args.arg2); + args.recycle(); + return; + } case DO_CREATE_OVERLAY_VIEW: { SomeArgs args = (SomeArgs) msg.obj; mTvInputSessionImpl.createOverlayView((IBinder) args.arg1, (Rect) args.arg2); @@ -185,6 +193,12 @@ public class ITvInputSessionWrapper extends ITvInputSession.Stub implements Hand mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_UNSELECT_TRACK, track)); } + @Override + public void appPrivateCommand(String action, Bundle data) { + mCaller.executeOrSendMessage(mCaller.obtainMessageOO(DO_APP_PRIVATE_COMMAND, action, + data)); + } + @Override public void createOverlayView(IBinder windowToken, Rect frame) { mCaller.executeOrSendMessage(mCaller.obtainMessageOO(DO_CREATE_OVERLAY_VIEW, windowToken, diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java index 200b3e9bc3b80..5235a531520d0 100644 --- a/media/java/android/media/tv/TvInputManager.java +++ b/media/java/android/media/tv/TvInputManager.java @@ -16,6 +16,7 @@ package android.media.tv; +import android.annotation.SystemApi; import android.graphics.Rect; import android.net.Uri; import android.os.Bundle; @@ -893,6 +894,29 @@ public final class TvInputManager { mTracks = tracks; } + /** + * Call {@link TvInputService.Session#appPrivateCommand(String, Bundle) + * TvInputService.Session.appPrivateCommand()} on the current TvView. + * + * @param action Name of the command to be performed. This must be a scoped name, + * i.e. prefixed with a package name you own, so that different developers will + * not create conflicting commands. + * @param data Any data to include with the command. + * @hide + */ + @SystemApi + public void sendAppPrivateCommand(String action, Bundle data) { + if (mToken == null) { + Log.w(TAG, "The session has been already released"); + return; + } + try { + mService.sendAppPrivateCommand(mToken, action, data, mUserId); + } catch (RemoteException e) { + throw new RuntimeException(e); + } + } + /** * Creates an overlay view. Once the overlay view is created, {@link #relayoutOverlayView} * should be called whenever the layout of its containing view is changed. diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java index bb9121053b18a..39e7f9dfae89e 100644 --- a/media/java/android/media/tv/TvInputService.java +++ b/media/java/android/media/tv/TvInputService.java @@ -518,6 +518,21 @@ public abstract class TvInputService extends Service { return false; } + /** + * Processes a private command sent from the application to the TV input. This can be used + * to provide domain-specific features that are only known between certain TV inputs and + * their clients. + * + * @param action Name of the command to be performed. This must be a scoped name, + * i.e. prefixed with a package name you own, so that different developers will + * not create conflicting commands. + * @param data Any data to include with the command. + * @hide + */ + @SystemApi + public void onAppPrivateCommand(String action, Bundle data) { + } + /** * Called when an application requests to create an overlay view. Each session * implementation can override this method and return its own view. @@ -725,6 +740,13 @@ public abstract class TvInputService extends Service { // TODO: Handle failure. } + /** + * Calls {@link #onAppPrivateCommand}. + */ + void appPrivateCommand(String action, Bundle data) { + onAppPrivateCommand(action, data); + } + /** * Creates an overlay view. This calls {@link #onCreateOverlayView} to get a view to attach * to the overlay window. diff --git a/media/java/android/media/tv/TvView.java b/media/java/android/media/tv/TvView.java index 4966e27cc5d77..0d36e847c740a 100644 --- a/media/java/android/media/tv/TvView.java +++ b/media/java/android/media/tv/TvView.java @@ -16,6 +16,7 @@ package android.media.tv; +import android.annotation.SystemApi; import android.content.Context; import android.graphics.Rect; import android.media.tv.TvInputManager.Session; @@ -290,6 +291,26 @@ public class TvView extends ViewGroup { return mSession.getTracks(); } + /** + * Call {@link TvInputService.Session#appPrivateCommand(String, Bundle) + * TvInputService.Session.appPrivateCommand()} on the current TvView. + * + * @param action Name of the command to be performed. This must be a scoped name, i.e. + * prefixed with a package name you own, so that different developers will not create + * conflicting commands. + * @param data Any data to include with the command. + * @hide + */ + @SystemApi + public void sendAppPrivateCommand(String action, Bundle data) { + if (TextUtils.isEmpty(action)) { + throw new IllegalArgumentException("action cannot be null or an empty string"); + } + if (mSession != null) { + mSession.sendAppPrivateCommand(action, data); + } + } + /** * Dispatches an unhandled input event to the next receiver. *

diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java index 0115366a963ac..c112b132497e0 100644 --- a/services/core/java/com/android/server/tv/TvInputManagerService.java +++ b/services/core/java/com/android/server/tv/TvInputManagerService.java @@ -1115,6 +1115,27 @@ public final class TvInputManagerService extends SystemService { } } + @Override + public void sendAppPrivateCommand(IBinder sessionToken, String command, Bundle data, + int userId) { + final int callingUid = Binder.getCallingUid(); + final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, + userId, "sendAppPrivateCommand"); + final long identity = Binder.clearCallingIdentity(); + try { + synchronized (mLock) { + try { + getSessionLocked(sessionToken, callingUid, resolvedUserId) + .appPrivateCommand(command, data); + } catch (RemoteException e) { + Slog.e(TAG, "error in sendAppPrivateCommand", e); + } + } + } finally { + Binder.restoreCallingIdentity(identity); + } + } + @Override public void createOverlayView(IBinder sessionToken, IBinder windowToken, Rect frame, int userId) {