From e821d711db1799dc51661a3ed6188f3cd942bae7 Mon Sep 17 00:00:00 2001 From: Youngsang Cho Date: Wed, 16 Jul 2014 14:22:19 -0700 Subject: TIF: Add a notification for surface change from TvView to TvInputService Bug: 15447352 Change-Id: I3e91609c5eb03be84cc7c88507457b9e74750de8 --- api/current.txt | 1 + media/java/android/media/tv/ITvInputManager.aidl | 2 ++ media/java/android/media/tv/ITvInputSession.aidl | 1 + .../android/media/tv/ITvInputSessionWrapper.java | 29 ++++++++++----- media/java/android/media/tv/TvInputManager.java | 21 +++++++++++ media/java/android/media/tv/TvInputService.java | 23 ++++++++++++ media/java/android/media/tv/TvView.java | 41 ++++++++++++++++++---- .../android/server/tv/TvInputManagerService.java | 21 +++++++++++ 8 files changed, 124 insertions(+), 15 deletions(-) diff --git a/api/current.txt b/api/current.txt index 8076d47d5b66..487200a1e23a 100644 --- a/api/current.txt +++ b/api/current.txt @@ -16545,6 +16545,7 @@ package android.media.tv { method public abstract void onSetCaptionEnabled(boolean); method public abstract void onSetStreamVolume(float); method public abstract boolean onSetSurface(android.view.Surface); + method public void onSurfaceChanged(int, int, int); method public boolean onTouchEvent(android.view.MotionEvent); method public boolean onTrackballEvent(android.view.MotionEvent); method public abstract boolean onTune(android.net.Uri); diff --git a/media/java/android/media/tv/ITvInputManager.aidl b/media/java/android/media/tv/ITvInputManager.aidl index 6a0c592aeff4..bd51c7733da0 100644 --- a/media/java/android/media/tv/ITvInputManager.aidl +++ b/media/java/android/media/tv/ITvInputManager.aidl @@ -42,6 +42,8 @@ interface ITvInputManager { void releaseSession(in IBinder sessionToken, int userId); void setSurface(in IBinder sessionToken, in Surface surface, int userId); + void dispatchSurfaceChanged(in IBinder sessionToken, int format, int width, int height, + int userId); void setVolume(in IBinder sessionToken, float volume, int userId); void tune(in IBinder sessionToken, in Uri channelUri, int userId); void setCaptionEnabled(in IBinder sessionToken, boolean enabled, int userId); diff --git a/media/java/android/media/tv/ITvInputSession.aidl b/media/java/android/media/tv/ITvInputSession.aidl index 875fa34246a3..9211dfc41c88 100644 --- a/media/java/android/media/tv/ITvInputSession.aidl +++ b/media/java/android/media/tv/ITvInputSession.aidl @@ -29,6 +29,7 @@ oneway interface ITvInputSession { void release(); void setSurface(in Surface surface); + void dispatchSurfaceChanged(int format, int width, int height); // TODO: Remove this once it becomes irrelevant for applications to handle audio focus. The plan // is to introduce some new concepts that will solve a number of problems in audio policy today. void setVolume(float volume); diff --git a/media/java/android/media/tv/ITvInputSessionWrapper.java b/media/java/android/media/tv/ITvInputSessionWrapper.java index 0c085903d058..c9c0768b1db4 100644 --- a/media/java/android/media/tv/ITvInputSessionWrapper.java +++ b/media/java/android/media/tv/ITvInputSessionWrapper.java @@ -42,14 +42,15 @@ public class ITvInputSessionWrapper extends ITvInputSession.Stub implements Hand private static final int DO_RELEASE = 1; private static final int DO_SET_SURFACE = 2; - private static final int DO_SET_VOLUME = 3; - private static final int DO_TUNE = 4; - private static final int DO_SET_CAPTION_ENABLED = 5; - private static final int DO_SELECT_TRACK = 6; - private static final int DO_UNSELECT_TRACK = 7; - private static final int DO_CREATE_OVERLAY_VIEW = 8; - private static final int DO_RELAYOUT_OVERLAY_VIEW = 9; - private static final int DO_REMOVE_OVERLAY_VIEW = 10; + private static final int DO_DISPATCH_SURFACE_CHANGED = 3; + private static final int DO_SET_VOLUME = 4; + private static final int DO_TUNE = 5; + 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 final HandlerCaller mCaller; @@ -91,6 +92,12 @@ public class ITvInputSessionWrapper extends ITvInputSession.Stub implements Hand mTvInputSessionImpl.setSurface((Surface) msg.obj); return; } + case DO_DISPATCH_SURFACE_CHANGED: { + SomeArgs args = (SomeArgs) msg.obj; + mTvInputSessionImpl.dispatchSurfaceChanged(args.argi1, args.argi2, args.argi3); + args.recycle(); + return; + } case DO_SET_VOLUME: { mTvInputSessionImpl.setVolume((Float) msg.obj); return; @@ -142,6 +149,12 @@ public class ITvInputSessionWrapper extends ITvInputSession.Stub implements Hand mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_SET_SURFACE, surface)); } + @Override + public void dispatchSurfaceChanged(int format, int width, int height) { + mCaller.executeOrSendMessage(mCaller.obtainMessageIIII(DO_DISPATCH_SURFACE_CHANGED, + format, width, height, 0)); + } + @Override public final void setVolume(float volume) { mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_SET_VOLUME, volume)); diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java index 79a83b0c6b2f..a34cecea8b7e 100644 --- a/media/java/android/media/tv/TvInputManager.java +++ b/media/java/android/media/tv/TvInputManager.java @@ -622,6 +622,27 @@ public final class TvInputManager { } } + /** + * Notifies of any structural changes (format or size) of the {@link Surface} + * passed by {@link #setSurface}. + * + * @param format The new PixelFormat of the {@link Surface}. + * @param width The new width of the {@link Surface}. + * @param height The new height of the {@link Surface}. + * @hide + */ + public void dispatchSurfaceChanged(int format, int width, int height) { + if (mToken == null) { + Log.w(TAG, "The session has been already released"); + return; + } + try { + mService.dispatchSurfaceChanged(mToken, format, width, height, mUserId); + } catch (RemoteException e) { + throw new RuntimeException(e); + } + } + /** * Sets the relative stream volume of this session to handle a change of audio focus. * diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java index 320632022a07..e0ef08aede22 100644 --- a/media/java/android/media/tv/TvInputService.java +++ b/media/java/android/media/tv/TvInputService.java @@ -312,6 +312,18 @@ public abstract class TvInputService extends Service { */ public abstract boolean onSetSurface(Surface surface); + /** + * Called after any structural changes (format or size) have been made to the + * {@link Surface} passed by {@link #onSetSurface}. This method is always called + * at least once, after {@link #onSetSurface} with non-null {@link Surface} is called. + * + * @param format The new PixelFormat of the {@link Surface}. + * @param width The new width of the {@link Surface}. + * @param height The new height of the {@link Surface}. + */ + public void onSurfaceChanged(int format, int width, int height) { + } + /** * Sets the relative stream volume of the current TV input session to handle the change of * audio focus by setting. @@ -525,6 +537,17 @@ public abstract class TvInputService extends Service { // TODO: Handle failure. } + /** + * Calls {@link #onSurfaceChanged}. + */ + void dispatchSurfaceChanged(int format, int width, int height) { + if (DEBUG) { + Log.d(TAG, "dispatchSurfaceChanged(format=" + format + ", width=" + width + + ", height=" + height + ")"); + } + onSurfaceChanged(format, width, height); + } + /** * Calls {@link #onSetStreamVolume}. */ diff --git a/media/java/android/media/tv/TvView.java b/media/java/android/media/tv/TvView.java index 4ac1ba422a7a..f8283dad6b67 100644 --- a/media/java/android/media/tv/TvView.java +++ b/media/java/android/media/tv/TvView.java @@ -75,17 +75,21 @@ public class TvView extends ViewGroup { private float mStreamVolume; private int mVideoWidth = VIDEO_SIZE_VALUE_UNKNOWN; private int mVideoHeight = VIDEO_SIZE_VALUE_UNKNOWN; + private boolean mSurfaceChanged; + private int mSurfaceFormat; + private int mSurfaceWidth; + private int mSurfaceHeight; private final SurfaceHolder.Callback mSurfaceHolderCallback = new SurfaceHolder.Callback() { @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { Log.d(TAG, "surfaceChanged(holder=" + holder + ", format=" + format + ", width=" + width + ", height=" + height + ")"); - if (holder.getSurface() == mSurface) { - return; - } - mSurface = holder.getSurface(); - setSessionSurface(mSurface); + mSurfaceFormat = format; + mSurfaceWidth = width; + mSurfaceHeight = height; + mSurfaceChanged = true; + dispatchSurfaceChanged(mSurfaceFormat, mSurfaceWidth, mSurfaceHeight); } @Override @@ -97,6 +101,7 @@ public class TvView extends ViewGroup { @Override public void surfaceDestroyed(SurfaceHolder holder) { mSurface = null; + mSurfaceChanged = false; setSessionSurface(null); } }; @@ -423,6 +428,13 @@ public class TvView extends ViewGroup { mSession.setSurface(surface); } + private void dispatchSurfaceChanged(int format, int width, int height) { + if (mSession == null) { + return; + } + mSession.dispatchSurfaceChanged(format, width, height); + } + private void createSessionOverlayView() { if (mSession == null || !isAttachedToWindow() || mOverlayViewCreated) { @@ -600,6 +612,9 @@ public class TvView extends ViewGroup { // setSessionSurface will be called in surfaceCreated. if (mSurface != null) { setSessionSurface(mSurface); + if (mSurfaceChanged) { + dispatchSurfaceChanged(mSurfaceFormat, mSurfaceWidth, mSurfaceHeight); + } } createSessionOverlayView(); mSession.tune(mChannelUri); @@ -615,9 +630,10 @@ public class TvView extends ViewGroup { @Override public void onSessionReleased(Session session) { - if (this == mSessionCallback) { - mSessionCallback = null; + if (this != mSessionCallback) { + return; } + mSessionCallback = null; mSession = null; if (mListener != null) { mListener.onError(mInputId, ERROR_TV_INPUT_DISCONNECTED); @@ -626,6 +642,9 @@ public class TvView extends ViewGroup { @Override public void onChannelRetuned(Session session, Uri channelUri) { + if (this != mSessionCallback) { + return; + } if (DEBUG) { Log.d(TAG, "onChannelChangedByTvInput(" + channelUri + ")"); } @@ -648,7 +667,11 @@ public class TvView extends ViewGroup { } } + @Override public void onVideoAvailable(Session session) { + if (this != mSessionCallback) { + return; + } if (DEBUG) { Log.d(TAG, "onVideoAvailable()"); } @@ -657,7 +680,11 @@ public class TvView extends ViewGroup { } } + @Override public void onVideoUnavailable(Session session, int reason) { + if (this != mSessionCallback) { + return; + } if (DEBUG) { Log.d(TAG, "onVideoUnavailable(" + reason + ")"); } diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java index 20fdefa32c7a..a6887fb01eb5 100644 --- a/services/core/java/com/android/server/tv/TvInputManagerService.java +++ b/services/core/java/com/android/server/tv/TvInputManagerService.java @@ -815,6 +815,27 @@ public final class TvInputManagerService extends SystemService { } } + @Override + public void dispatchSurfaceChanged(IBinder sessionToken, int format, int width, + int height, int userId) { + final int callingUid = Binder.getCallingUid(); + final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid, + userId, "dispatchSurfaceChanged"); + final long identity = Binder.clearCallingIdentity(); + try { + synchronized (mLock) { + try { + getSessionLocked(sessionToken, callingUid, resolvedUserId) + .dispatchSurfaceChanged(format, width, height); + } catch (RemoteException e) { + Slog.e(TAG, "error in dispatchSurfaceChanged", e); + } + } + } finally { + Binder.restoreCallingIdentity(identity); + } + } + @Override public void setVolume(IBinder sessionToken, float volume, int userId) { final int callingUid = Binder.getCallingUid(); -- cgit v1.2.3-59-g8ed1b