From ff04ae757a5542d2d5633e75b7adacc4fce1ce7e Mon Sep 17 00:00:00 2001 From: Youngsang Cho Date: Wed, 2 Jul 2014 17:08:23 +0900 Subject: [PATCH] Add a method in TIS to relayout SurfaceView Bug: 15389458 Change-Id: I7f740141e7cf59fea5d321099652e65bc9e5f7d1 --- media/java/android/media/tv/ITvInputClient.aidl | 1 + .../android/media/tv/ITvInputSessionCallback.aidl | 1 + media/java/android/media/tv/TvInputManager.java | 37 +++++++++++++++ media/java/android/media/tv/TvInputService.java | 53 +++++++++++++++++++++- media/java/android/media/tv/TvView.java | 31 ++++++++++++- .../android/server/tv/TvInputManagerService.java | 20 +++++++- 6 files changed, 140 insertions(+), 3 deletions(-) diff --git a/media/java/android/media/tv/ITvInputClient.aidl b/media/java/android/media/tv/ITvInputClient.aidl index 37c75531653f..7a023d6d8989 100644 --- a/media/java/android/media/tv/ITvInputClient.aidl +++ b/media/java/android/media/tv/ITvInputClient.aidl @@ -39,4 +39,5 @@ oneway interface ITvInputClient { void onVideoUnavailable(int reason, int seq); void onContentAllowed(int seq); void onContentBlocked(in String rating, int seq); + void onLayoutSurface(int left, int top, int right, int bottom, int seq); } diff --git a/media/java/android/media/tv/ITvInputSessionCallback.aidl b/media/java/android/media/tv/ITvInputSessionCallback.aidl index 8a918e1923d4..063d10de11c0 100644 --- a/media/java/android/media/tv/ITvInputSessionCallback.aidl +++ b/media/java/android/media/tv/ITvInputSessionCallback.aidl @@ -36,4 +36,5 @@ oneway interface ITvInputSessionCallback { void onVideoUnavailable(int reason); void onContentAllowed(); void onContentBlocked(in String rating); + void onLayoutSurface(int left, int top, int right, int bottom); } diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java index fdf0d9c0bcb2..d556369acd92 100644 --- a/media/java/android/media/tv/TvInputManager.java +++ b/media/java/android/media/tv/TvInputManager.java @@ -235,6 +235,21 @@ public final class TvInputManager { } /** + * This is called when {@link TvInputService.Session#layoutSurface} is called to + * change the layout of surface. + * + * @param session A {@link TvInputManager.Session} associated with this callback + * @param l Left position. + * @param t Top position. + * @param r Right position. + * @param b Bottom position. + * @hide + */ + @SystemApi + public void onLayoutSurface(Session session, int left, int top, int right, int bottom) { + } + + /** * This is called when a custom event has been sent from this session. * * @param session A {@link TvInputManager.Session} associated with this callback @@ -364,6 +379,16 @@ public final class TvInputManager { }); } + public void postLayoutSurface(final int left, final int top, final int right, + final int bottom) { + mHandler.post(new Runnable() { + @Override + public void run() { + mSessionCallback.onLayoutSurface(mSession, left, top, right, bottom); + } + }); + } + public void postSessionEvent(final String eventType, final Bundle eventArgs) { mHandler.post(new Runnable() { @Override @@ -574,6 +599,18 @@ public final class TvInputManager { } @Override + public void onLayoutSurface(int left, int top, int right, int bottom, int seq) { + synchronized (mSessionCallbackRecordMap) { + SessionCallbackRecord record = mSessionCallbackRecordMap.get(seq); + if (record == null) { + Log.e(TAG, "Callback not found for seq " + seq); + return; + } + record.postLayoutSurface(left, top, right, bottom); + } + } + + @Override public void onSessionEvent(String eventType, Bundle eventArgs, int seq) { synchronized (mSessionCallbackRecordMap) { SessionCallbackRecord record = mSessionCallbackRecordMap.get(seq); diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java index 642993a8458d..3a188abce590 100644 --- a/media/java/android/media/tv/TvInputService.java +++ b/media/java/android/media/tv/TvInputService.java @@ -42,6 +42,7 @@ import android.view.InputEventReceiver; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.Surface; +import android.view.SurfaceView; import android.view.View; import android.view.WindowManager; import android.view.accessibility.CaptioningManager; @@ -504,6 +505,35 @@ public abstract class TvInputService extends Service { } /** + * Assigns a position of the {@link Surface} passed by {@link #onSetSurface}. The position + * is relative to an overlay view. {@see #onOverlayViewSizeChanged}. + * + * @param left Left position in pixels, relative to the overlay view. + * @param top Top position in pixels, relative to the overlay view. + * @param right Right position in pixels, relative to the overlay view. + * @param bottm Bottom position in pixels, relative to the overlay view. + * @hide + */ + @SystemApi + public void layoutSurface(final int left, final int top, final int right, final int bottm) { + if (left > right || top > bottm) { + throw new IllegalArgumentException("Invalid parameter"); + } + mHandler.post(new Runnable() { + @Override + public void run() { + try { + if (DEBUG) Log.d(TAG, "layoutSurface (l=" + left + ", t=" + top + ", r=" + + right + ", b=" + bottm + ",)"); + mSessionCallback.onLayoutSurface(left, top, right, bottm); + } catch (RemoteException e) { + Log.w(TAG, "error in layoutSurface"); + } + } + }); + } + + /** * Called when the session is released. */ public abstract void onRelease(); @@ -556,6 +586,20 @@ public abstract class TvInputService extends Service { } /** + * Called when a size of an overlay view is changed by an application. Even when the overlay + * view is disabled by {@link #setOverlayViewEnabled}, this is called. The size is same as + * the size of {@link Surface} in general. Once {@link #layoutSurface} is called, the sizes + * of {@link Surface} and the overlay view can be different. + * + * @param width The width of the overlay view. + * @param height The height of the overlay view. + * @hide + */ + @SystemApi + public void onOverlayViewSizeChanged(int width, int height) { + } + + /** * Sets the relative stream volume of the current TV input session to handle the change of * audio focus by setting. * @@ -873,6 +917,7 @@ public abstract class TvInputService extends Service { if (DEBUG) Log.d(TAG, "create overlay view(" + frame + ")"); mWindowToken = windowToken; mOverlayFrame = frame; + onOverlayViewSizeChanged(frame.right - frame.left, frame.bottom - frame.top); if (!mOverlayViewEnabled) { return; } @@ -887,7 +932,7 @@ public abstract class TvInputService extends Service { // the application that owns the window token can decide whether to consume or // dispatch the input events. int flag = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE - | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN + | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; mWindowParams = new WindowManager.LayoutParams( frame.right - frame.left, frame.bottom - frame.top, @@ -906,6 +951,12 @@ public abstract class TvInputService extends Service { */ void relayoutOverlayView(Rect frame) { if (DEBUG) Log.d(TAG, "relayoutOverlayView(" + frame + ")"); + if (mOverlayFrame == null || mOverlayFrame.width() != frame.width() + || mOverlayFrame.height() != frame.height()) { + // Note: relayoutOverlayView is called whenever TvView's layout is changed + // regardless of setOverlayViewEnabled. + onOverlayViewSizeChanged(frame.right - frame.left, frame.bottom - frame.top); + } mOverlayFrame = frame; if (!mOverlayViewEnabled || mOverlayView == null) { return; diff --git a/media/java/android/media/tv/TvView.java b/media/java/android/media/tv/TvView.java index 82761ec37573..ad2a502858b4 100644 --- a/media/java/android/media/tv/TvView.java +++ b/media/java/android/media/tv/TvView.java @@ -91,6 +91,11 @@ public class TvView extends ViewGroup { private final AttributeSet mAttrs; private final int mDefStyleAttr; private int mWindowZOrder; + private boolean mUseRequestedSurfaceLayout; + private int mSurfaceViewLeft; + private int mSurfaceViewRight; + private int mSurfaceViewTop; + private int mSurfaceViewBottom; private final SurfaceHolder.Callback mSurfaceHolderCallback = new SurfaceHolder.Callback() { @Override @@ -535,7 +540,16 @@ public class TvView extends ViewGroup { @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { - mSurfaceView.layout(0, 0, right - left, bottom - top); + if (DEBUG) { + Log.d(TAG, "onLayout (left=" + left + ", top=" + top + ", right=" + right + + ", bottom=" + bottom + ",)"); + } + if (mUseRequestedSurfaceLayout) { + mSurfaceView.layout(mSurfaceViewLeft, mSurfaceViewTop, mSurfaceViewRight, + mSurfaceViewBottom); + } else { + mSurfaceView.layout(0, 0, right - left, bottom - top); + } } @Override @@ -583,6 +597,7 @@ public class TvView extends ViewGroup { private void release() { setSessionSurface(null); removeSessionOverlayView(); + mUseRequestedSurfaceLayout = false; mSession.release(); mSession = null; mSessionCallback = null; @@ -919,6 +934,20 @@ public class TvView extends ViewGroup { } @Override + public void onLayoutSurface(Session session, int left, int top, int right, int bottom) { + if (DEBUG) { + Log.d(TAG, "onLayoutSurface (left=" + left + ", top=" + top + ", right=" + + right + ", bottom=" + bottom + ",)"); + } + mSurfaceViewLeft = left; + mSurfaceViewTop = top; + mSurfaceViewRight = right; + mSurfaceViewBottom = bottom; + mUseRequestedSurfaceLayout = true; + requestLayout(); + } + + @Override public void onSessionEvent(Session session, String eventType, Bundle eventArgs) { if (this != mSessionCallback) { return; diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java index 18446aee4297..594e9d023090 100644 --- a/services/core/java/com/android/server/tv/TvInputManagerService.java +++ b/services/core/java/com/android/server/tv/TvInputManagerService.java @@ -52,7 +52,6 @@ import android.media.tv.TvContentRating; import android.media.tv.TvContract; import android.media.tv.TvInputHardwareInfo; import android.media.tv.TvInputInfo; -import android.media.tv.TvInputManager; import android.media.tv.TvInputService; import android.media.tv.TvStreamConfig; import android.media.tv.TvTrackInfo; @@ -636,6 +635,25 @@ public final class TvInputManagerService extends SystemService { } @Override + public void onLayoutSurface(int left, int top, int right, int bottom) { + synchronized (mLock) { + if (DEBUG) { + Slog.d(TAG, "onLayoutSurface (left=" + left + ", top=" + top + + ", right=" + right + ", bottom=" + bottom + ",)"); + } + if (sessionState.mSession == null || sessionState.mClient == null) { + return; + } + try { + sessionState.mClient.onLayoutSurface(left, top, right, bottom, + sessionState.mSeq); + } catch (RemoteException e) { + Slog.e(TAG, "error in onLayoutSurface"); + } + } + } + + @Override public void onSessionEvent(String eventType, Bundle eventArgs) { synchronized (mLock) { if (DEBUG) { -- 2.11.0