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);
}
void onVideoUnavailable(int reason);
void onContentAllowed();
void onContentBlocked(in String rating);
+ void onLayoutSurface(int left, int top, int right, int bottom);
}
}
/**
+ * 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
});
}
+ 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
}
@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);
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;
}
/**
+ * 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();
}
/**
+ * 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.
*
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;
}
// 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,
*/
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;
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
@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
private void release() {
setSessionSurface(null);
removeSessionOverlayView();
+ mUseRequestedSurfaceLayout = false;
mSession.release();
mSession = null;
mSessionCallback = null;
}
@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;
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;
}
@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) {