aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorshubang <shubang@google.com>2023-05-11 23:53:54 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2023-05-11 23:53:54 +0000
commit6d925733a8e6d0d37ec00648fcabd11e8a63c78c (patch)
treee02a9710ddb9d73a15fdeefa96d55aba0be8f484
parent7a40b2c470927b312960435d937846d83b55b446 (diff)
parent1c307e0a270172580c8346360a33533bca3030dc (diff)
downloadTV-6d925733a8e6d0d37ec00648fcabd11e8a63c78c.tar.gz
[LiveTv] Improve TIAF features in LiveTv and sample TIAS am: 1c307e0a27
Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/apps/TV/+/23127243 Change-Id: Ic479974a778a95cfad05c4a3592c0aa83ba78167 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-rw-r--r--interactive/SampleTvInteractiveAppService/res/layout/sample_layout.xml3
-rw-r--r--interactive/SampleTvInteractiveAppService/src/com/android/tv/samples/sampletvinteractiveappservice/TiasSessionImpl.java276
-rw-r--r--src/com/android/tv/MainActivity.java16
-rwxr-xr-xsrc/com/android/tv/dialog/InteractiveAppDialogFragment.java4
-rw-r--r--src/com/android/tv/interactive/IAppManager.java45
5 files changed, 335 insertions, 9 deletions
diff --git a/interactive/SampleTvInteractiveAppService/res/layout/sample_layout.xml b/interactive/SampleTvInteractiveAppService/res/layout/sample_layout.xml
index d8659f9b..915c3526 100644
--- a/interactive/SampleTvInteractiveAppService/res/layout/sample_layout.xml
+++ b/interactive/SampleTvInteractiveAppService/res/layout/sample_layout.xml
@@ -59,5 +59,8 @@
<TextView
style="@style/overlay_text_item"
android:id="@+id/subtitle_track_selected"/>
+ <TextView
+ style="@style/overlay_text_item"
+ android:id="@+id/log_text"/>
</LinearLayout>
</RelativeLayout> \ No newline at end of file
diff --git a/interactive/SampleTvInteractiveAppService/src/com/android/tv/samples/sampletvinteractiveappservice/TiasSessionImpl.java b/interactive/SampleTvInteractiveAppService/src/com/android/tv/samples/sampletvinteractiveappservice/TiasSessionImpl.java
index 83b16ffc..0f185225 100644
--- a/interactive/SampleTvInteractiveAppService/src/com/android/tv/samples/sampletvinteractiveappservice/TiasSessionImpl.java
+++ b/interactive/SampleTvInteractiveAppService/src/com/android/tv/samples/sampletvinteractiveappservice/TiasSessionImpl.java
@@ -18,13 +18,22 @@ package com.android.tv.samples.sampletvinteractiveappservice;
import android.app.Presentation;
import android.content.Context;
+import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.hardware.display.DisplayManager;
import android.hardware.display.VirtualDisplay;
+import android.media.MediaPlayer;
+import android.media.tv.BroadcastInfoRequest;
+import android.media.tv.BroadcastInfoResponse;
+import android.media.tv.SectionRequest;
+import android.media.tv.SectionResponse;
+import android.media.tv.StreamEventRequest;
+import android.media.tv.StreamEventResponse;
import android.media.tv.TvTrackInfo;
import android.media.tv.interactive.TvInteractiveAppManager;
import android.media.tv.interactive.TvInteractiveAppService;
import android.net.Uri;
+import android.os.Bundle;
import android.os.Handler;
import android.util.DisplayMetrics;
import android.util.Log;
@@ -33,11 +42,15 @@ import android.view.LayoutInflater;
import android.view.Surface;
import android.view.View;
import android.view.ViewGroup;
+import android.view.WindowManager;
import android.widget.LinearLayout;
import android.widget.TextView;
+import android.widget.VideoView;
import androidx.annotation.NonNull;
+import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
public class TiasSessionImpl extends TvInteractiveAppService.Session {
@@ -46,6 +59,9 @@ public class TiasSessionImpl extends TvInteractiveAppService.Session {
private static final String VIRTUAL_DISPLAY_NAME = "sample_tias_display";
+ // For testing purposes, limit the number of response for a single request
+ private static final int MAX_HANDLED_RESPONSE = 3;
+
private final Context mContext;
private final Handler mHandler;
private final String mAppServiceId;
@@ -60,6 +76,22 @@ public class TiasSessionImpl extends TvInteractiveAppService.Session {
private TextView mVideoTrackView;
private TextView mAudioTrackView;
private TextView mSubtitleTrackView;
+ private TextView mLogView;
+
+ private VideoView mVideoView;
+ private int mWidth;
+ private int mHeight;
+ private int mScreenWidth;
+ private int mScreenHeight;
+ private String mCurrentTvInputId;
+ private Uri mCurrentChannelUri;
+ private String mSelectingAudioTrackId;
+ private String mFirstAudioTrackId;
+ private int mGeneratedRequestId = 0;
+ private boolean mRequestStreamEventFinished = false;
+ private int mSectionReceived = 0;
+ private List<String> mStreamDataList = new ArrayList<>();
+ private boolean mIsFullScreen = true;
public TiasSessionImpl(Context context, String iAppServiceId, int type) {
super(context);
@@ -99,6 +131,7 @@ public class TiasSessionImpl extends TvInteractiveAppService.Session {
if (mSurface != null) {
mSurface.release();
}
+ updateSurface(surface, mWidth, mHeight);
mSurface = surface;
return true;
}
@@ -111,6 +144,8 @@ public class TiasSessionImpl extends TvInteractiveAppService.Session {
}
if (mSurface != null) {
updateSurface(mSurface, width, height);
+ mWidth = width;
+ mHeight = height;
}
}
@@ -122,6 +157,7 @@ public class TiasSessionImpl extends TvInteractiveAppService.Session {
mHandler.post(
() -> {
initSampleView();
+ setMediaViewEnabled(true);
requestCurrentTvInputId();
requestCurrentChannelUri();
requestTrackInfoList();
@@ -151,10 +187,89 @@ public class TiasSessionImpl extends TvInteractiveAppService.Session {
@Override
public boolean onKeyDown(int keyCode, @NonNull KeyEvent event) {
+ // TODO: use a menu view instead of key events for the following tests
switch (keyCode) {
case KeyEvent.KEYCODE_PROG_RED:
tuneToNextChannel();
return true;
+ case KeyEvent.KEYCODE_A:
+ updateLogText("stop video broadcast begin");
+ tuneChannelByType(
+ TvInteractiveAppService.PLAYBACK_COMMAND_TYPE_STOP,
+ mCurrentTvInputId,
+ null);
+ updateLogText("stop video broadcast end");
+ return true;
+ case KeyEvent.KEYCODE_B:
+ updateLogText("resume video broadcast begin");
+ tuneChannelByType(
+ TvInteractiveAppService.PLAYBACK_COMMAND_TYPE_TUNE,
+ mCurrentTvInputId,
+ mCurrentChannelUri);
+ updateLogText("resume video broadcast end");
+ return true;
+ case KeyEvent.KEYCODE_C:
+ updateLogText("unselect audio track");
+ mSelectingAudioTrackId = null;
+ selectTrack(TvTrackInfo.TYPE_AUDIO, null);
+ return true;
+ case KeyEvent.KEYCODE_D:
+ updateLogText("select audio track " + mFirstAudioTrackId);
+ mSelectingAudioTrackId = mFirstAudioTrackId;
+ selectTrack(TvTrackInfo.TYPE_AUDIO, mFirstAudioTrackId);
+ return true;
+ case KeyEvent.KEYCODE_E:
+ if (mVideoView != null) {
+ if (mVideoView.isPlaying()) {
+ updateLogText("stop media");
+ mVideoView.stopPlayback();
+ mVideoView.setVisibility(View.GONE);
+ tuneChannelByType(
+ TvInteractiveAppService.PLAYBACK_COMMAND_TYPE_TUNE,
+ mCurrentTvInputId,
+ mCurrentChannelUri);
+ } else {
+ updateLogText("play media");
+ tuneChannelByType(
+ TvInteractiveAppService.PLAYBACK_COMMAND_TYPE_STOP,
+ mCurrentTvInputId,
+ null);
+ mVideoView.setVisibility(View.VISIBLE);
+ // TODO: put a file sample.mp4 in res/raw/ and use R.raw.sample for the URI
+ Uri uri = Uri.parse(
+ "android.resource://" + mContext.getPackageName() + "/");
+ mVideoView.setVideoURI(uri);
+ mVideoView.start();
+ updateLogText("media is playing");
+ }
+ }
+ return true;
+ case KeyEvent.KEYCODE_F:
+ updateLogText("request StreamEvent");
+ mRequestStreamEventFinished = false;
+ mStreamDataList.clear();
+ // TODO: build target URI instead of using channel URI
+ requestStreamEvent(
+ mCurrentChannelUri == null ? null : mCurrentChannelUri.toString(),
+ "event1");
+ return true;
+ case KeyEvent.KEYCODE_G:
+ updateLogText("change video bounds");
+ if (mIsFullScreen) {
+ setVideoBounds(new Rect(100, 150, 960, 540));
+ updateLogText("Change video broadcast size(100, 150, 960, 540)");
+ mIsFullScreen = false;
+ } else {
+ setVideoBounds(new Rect(0, 0, mScreenWidth, mScreenHeight));
+ updateLogText("Change video broadcast full screen");
+ mIsFullScreen = true;
+ }
+ return true;
+ case KeyEvent.KEYCODE_H:
+ updateLogText("request section");
+ mSectionReceived = 0;
+ requestSection(false, 0, 0x0, -1);
+ return true;
default:
return super.onKeyDown(keyCode, event);
}
@@ -164,12 +279,27 @@ public class TiasSessionImpl extends TvInteractiveAppService.Session {
public boolean onKeyUp(int keyCode, @NonNull KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_PROG_RED:
+ case KeyEvent.KEYCODE_A:
+ case KeyEvent.KEYCODE_B:
+ case KeyEvent.KEYCODE_C:
+ case KeyEvent.KEYCODE_D:
+ case KeyEvent.KEYCODE_E:
+ case KeyEvent.KEYCODE_F:
+ case KeyEvent.KEYCODE_G:
+ case KeyEvent.KEYCODE_H:
return true;
default:
return super.onKeyUp(keyCode, event);
}
}
+ public void updateLogText(String log) {
+ if (DEBUG) {
+ Log.d(TAG, log);
+ }
+ mLogView.setText(log);
+ }
+
private void updateSurface(Surface surface, int width, int height) {
mHandler.post(
() -> {
@@ -210,11 +340,32 @@ public class TiasSessionImpl extends TvInteractiveAppService.Session {
mVideoTrackView = sampleView.findViewById(R.id.video_track_selected);
mAudioTrackView = sampleView.findViewById(R.id.audio_track_selected);
mSubtitleTrackView = sampleView.findViewById(R.id.subtitle_track_selected);
+ mLogView = sampleView.findViewById(R.id.log_text);
// Set default values for the selected tracks, since we cannot request data on them directly
mVideoTrackView.setText("No video track selected");
mAudioTrackView.setText("No audio track selected");
mSubtitleTrackView.setText("No subtitle track selected");
+ mVideoView = new VideoView(mContext);
+ mVideoView.setVisibility(View.GONE);
+ mVideoView.setOnCompletionListener(
+ new MediaPlayer.OnCompletionListener() {
+ @Override
+ public void onCompletion(MediaPlayer mediaPlayer) {
+ mVideoView.setVisibility(View.GONE);
+ mLogView.setText("MediaPlayer onCompletion");
+ tuneChannelByType(
+ TvInteractiveAppService.PLAYBACK_COMMAND_TYPE_TUNE,
+ mCurrentTvInputId,
+ mCurrentChannelUri);
+ }
+ });
+ mWidth = 0;
+ mHeight = 0;
+ WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
+ mScreenWidth = wm.getDefaultDisplay().getWidth();
+ mScreenHeight = wm.getDefaultDisplay().getHeight();
+
mViewContainer.addView(sampleView);
}
@@ -267,9 +418,15 @@ public class TiasSessionImpl extends TvInteractiveAppService.Session {
);
}
- private void tuneToNextChannel() {
- sendPlaybackCommandRequest(TvInteractiveAppService.PLAYBACK_COMMAND_TYPE_TUNE_NEXT,
- null);
+ private void tuneChannelByType(String type, String inputId, Uri channelUri) {
+ Bundle parameters = new Bundle();
+ if (TvInteractiveAppService.PLAYBACK_COMMAND_TYPE_TUNE.equals(type)) {
+ parameters.putString(
+ TvInteractiveAppService.COMMAND_PARAMETER_KEY_CHANNEL_URI,
+ channelUri == null ? null : channelUri.toString());
+ parameters.putString(TvInteractiveAppService.COMMAND_PARAMETER_KEY_INPUT_ID, inputId);
+ }
+ mHandler.post(() -> sendPlaybackCommandRequest(type, parameters));
// Delay request for new information to give time to tune
mHandler.postDelayed(
() -> {
@@ -281,11 +438,16 @@ public class TiasSessionImpl extends TvInteractiveAppService.Session {
);
}
+ private void tuneToNextChannel() {
+ tuneChannelByType(TvInteractiveAppService.PLAYBACK_COMMAND_TYPE_TUNE_NEXT, null, null);
+ }
+
@Override
public void onCurrentChannelUri(Uri channelUri) {
if (DEBUG) {
Log.d(TAG, "onCurrentChannelUri uri=" + channelUri);
}
+ mCurrentChannelUri = channelUri;
mChannelUriView.setText("Channel URI: " + channelUri);
}
@@ -301,6 +463,12 @@ public class TiasSessionImpl extends TvInteractiveAppService.Session {
}
}
}
+ for (TvTrackInfo info : tracks) {
+ if (info.getType() == TvTrackInfo.TYPE_AUDIO) {
+ mFirstAudioTrackId = info.getId();
+ break;
+ }
+ }
mTracks = tracks;
}
@@ -325,6 +493,108 @@ public class TiasSessionImpl extends TvInteractiveAppService.Session {
if (DEBUG) {
Log.d(TAG, "onCurrentTvInputId id=" + inputId);
}
+ mCurrentTvInputId = inputId;
mTvInputIdView.setText("TV Input ID: " + inputId);
}
+
+ @Override
+ public void onTuned(Uri channelUri) {
+ mCurrentChannelUri = channelUri;
+ }
+
+ @Override
+ public void onBroadcastInfoResponse(BroadcastInfoResponse response) {
+ if (mGeneratedRequestId == response.getRequestId()) {
+ if (!mRequestStreamEventFinished && response instanceof StreamEventResponse) {
+ handleStreamEventResponse((StreamEventResponse) response);
+ } else if (mSectionReceived < MAX_HANDLED_RESPONSE
+ && response instanceof SectionResponse) {
+ handleSectionResponse((SectionResponse) response);
+ }
+ }
+ }
+
+ private void handleSectionResponse(SectionResponse response) {
+ mSectionReceived++;
+ byte[] data = null;
+ Bundle params = response.getSessionData();
+ if (params != null) {
+ // TODO: define the key
+ data = params.getByteArray("key_raw_data");
+ }
+ int version = response.getVersion();
+ updateLogText(
+ "Received section data version = "
+ + version
+ + ", data = "
+ + Arrays.toString(data));
+ }
+
+ private void handleStreamEventResponse(StreamEventResponse response) {
+ updateLogText("Received stream event response");
+ byte[] rData = response.getData();
+ if (rData == null) {
+ mRequestStreamEventFinished = true;
+ updateLogText("Received stream event data is null");
+ return;
+ }
+ // TODO: convert to Hex instead
+ String data = Arrays.toString(rData);
+ if (mStreamDataList.contains(data)) {
+ return;
+ }
+ mStreamDataList.add(data);
+ updateLogText(
+ "Received stream event data("
+ + (mStreamDataList.size() - 1)
+ + "): "
+ + data);
+ if (mStreamDataList.size() >= MAX_HANDLED_RESPONSE) {
+ mRequestStreamEventFinished = true;
+ updateLogText("Received stream event data finished");
+ }
+ }
+
+ private void selectTrack(int type, String trackId) {
+ Bundle params = new Bundle();
+ params.putInt(TvInteractiveAppService.COMMAND_PARAMETER_KEY_TRACK_TYPE, type);
+ params.putString(TvInteractiveAppService.COMMAND_PARAMETER_KEY_TRACK_ID, trackId);
+ mHandler.post(
+ () ->
+ sendPlaybackCommandRequest(
+ TvInteractiveAppService.PLAYBACK_COMMAND_TYPE_SELECT_TRACK,
+ params));
+ }
+
+ private int generateRequestId() {
+ return ++mGeneratedRequestId;
+ }
+
+ public void requestStreamEvent(String targetUri, String eventName) {
+ if (targetUri == null) {
+ return;
+ }
+ int requestId = generateRequestId();
+ BroadcastInfoRequest request =
+ new StreamEventRequest(
+ requestId,
+ BroadcastInfoRequest.REQUEST_OPTION_AUTO_UPDATE,
+ Uri.parse(targetUri),
+ eventName);
+ requestBroadcastInfo(request);
+ }
+
+ public void requestSection(boolean repeat, int tsPid, int tableId, int version) {
+ int requestId = generateRequestId();
+ BroadcastInfoRequest request =
+ new SectionRequest(
+ requestId,
+ repeat ?
+ BroadcastInfoRequest.REQUEST_OPTION_REPEAT :
+ BroadcastInfoRequest.REQUEST_OPTION_AUTO_UPDATE,
+ tsPid,
+ tableId,
+ version);
+ requestBroadcastInfo(request);
+ }
}
diff --git a/src/com/android/tv/MainActivity.java b/src/com/android/tv/MainActivity.java
index a7d59035..d0cfb30c 100644
--- a/src/com/android/tv/MainActivity.java
+++ b/src/com/android/tv/MainActivity.java
@@ -42,6 +42,7 @@ import android.media.tv.TvInputManager;
import android.media.tv.TvInputManager.TvInputCallback;
import android.media.tv.TvTrackInfo;
import android.media.tv.TvView.OnUnhandledInputEventListener;
+import android.media.tv.interactive.TvInteractiveAppManager;
import android.media.tv.interactive.TvInteractiveAppView;
import android.net.Uri;
import android.os.Build;
@@ -259,6 +260,7 @@ public class MainActivity extends Activity
static {
SYSTEM_INTENT_FILTER.addAction(TvInputManager.ACTION_PARENTAL_CONTROLS_ENABLED_CHANGED);
+ SYSTEM_INTENT_FILTER.addAction(TvInteractiveAppManager.ACTION_APP_LINK_COMMAND);
SYSTEM_INTENT_FILTER.addAction(Intent.ACTION_SCREEN_OFF);
SYSTEM_INTENT_FILTER.addAction(Intent.ACTION_SCREEN_ON);
SYSTEM_INTENT_FILTER.addAction(Intent.ACTION_TIME_CHANGED);
@@ -416,6 +418,13 @@ public class MainActivity extends Activity
tune(true);
}
break;
+ case TvInteractiveAppManager.ACTION_APP_LINK_COMMAND:
+ if (DEBUG) {
+ Log.d(TAG, "Received action link command");
+ }
+ // TODO: handle the command
+ break;
+
default: // fall out
}
}
@@ -753,8 +762,8 @@ public class MainActivity extends Activity
@TargetApi(Build.VERSION_CODES.TIRAMISU)
@Override
public void onInteractiveAppChecked(boolean checked) {
+ TvSettings.setTvIAppOn(getApplicationContext(), checked);
if (checked) {
- TvSettings.setTvIAppOn(getApplicationContext(), checked);
mIAppManager.processHeldAitInfo();
}
}
@@ -1452,6 +1461,9 @@ public class MainActivity extends Activity
if (DeveloperPreferences.LOG_KEYEVENT.get(this)) {
Log.d(TAG, "dispatchKeyEvent(" + event + ")");
}
+ if (mIAppManager != null && mIAppManager.dispatchKeyEvent(event)) {
+ return true;
+ }
// If an activity is closed on a back key down event, back key down events with none zero
// repeat count or a back key up event can be happened without the first back key down
// event which should be ignored in this activity.
@@ -2495,7 +2507,7 @@ public class MainActivity extends Activity
return handled;
}
- private boolean isKeyEventBlocked() {
+ public boolean isKeyEventBlocked() {
// If the current channel is a passthrough channel, we don't handle the key events in TV
// activity. Instead, the key event will be handled by the passthrough TV input.
return mChannelTuner.isCurrentChannelPassthrough();
diff --git a/src/com/android/tv/dialog/InteractiveAppDialogFragment.java b/src/com/android/tv/dialog/InteractiveAppDialogFragment.java
index 70adbe30..c5ffbaac 100755
--- a/src/com/android/tv/dialog/InteractiveAppDialogFragment.java
+++ b/src/com/android/tv/dialog/InteractiveAppDialogFragment.java
@@ -16,10 +16,11 @@
package com.android.tv.dialog;
+import android.annotation.TargetApi;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
-import android.media.tv.AitInfo;
+import android.os.Build;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
@@ -34,6 +35,7 @@ import java.util.function.Function;
import dagger.android.AndroidInjection;
+@TargetApi(Build.VERSION_CODES.TIRAMISU)
public class InteractiveAppDialogFragment extends SafeDismissDialogFragment {
private static final boolean DEBUG = false;
diff --git a/src/com/android/tv/interactive/IAppManager.java b/src/com/android/tv/interactive/IAppManager.java
index 29de5930..90a76415 100644
--- a/src/com/android/tv/interactive/IAppManager.java
+++ b/src/com/android/tv/interactive/IAppManager.java
@@ -33,7 +33,10 @@ import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.util.Log;
+import android.view.InputEvent;
+import android.view.KeyEvent;
import android.view.View;
+import android.view.ViewGroup;
import com.android.tv.MainActivity;
import com.android.tv.R;
@@ -87,6 +90,27 @@ public class IAppManager {
executor,
new MyInteractiveAppViewCallback()
);
+ mTvIAppView.setOnUnhandledInputEventListener(executor,
+ inputEvent -> {
+ if (mMainActivity.isKeyEventBlocked()) {
+ return true;
+ }
+ if (inputEvent instanceof KeyEvent) {
+ KeyEvent keyEvent = (KeyEvent) inputEvent;
+ if (keyEvent.getAction() == KeyEvent.ACTION_DOWN
+ && keyEvent.isLongPress()) {
+ if (mMainActivity.onKeyLongPress(keyEvent.getKeyCode(), keyEvent)) {
+ return true;
+ }
+ }
+ if (keyEvent.getAction() == KeyEvent.ACTION_UP) {
+ return mMainActivity.onKeyUp(keyEvent.getKeyCode(), keyEvent);
+ } else if (keyEvent.getAction() == KeyEvent.ACTION_DOWN) {
+ return mMainActivity.onKeyDown(keyEvent.getKeyCode(), keyEvent);
+ }
+ }
+ return false;
+ });
}
public void stop() {
@@ -104,6 +128,14 @@ public class IAppManager {
}
}
+ public boolean dispatchKeyEvent(KeyEvent event) {
+ if (mTvIAppView != null && mTvIAppView.getVisibility() == View.VISIBLE
+ && mTvIAppView.dispatchKeyEvent(event)){
+ return true;
+ }
+ return false;
+ }
+
public void onAitInfoUpdated(AitInfo aitInfo) {
if (mTvIAppManager == null || aitInfo == null) {
return;
@@ -204,7 +236,7 @@ public class IAppManager {
@Override
public void onPlaybackCommandRequest(String iAppServiceId, String cmdType,
Bundle parameters) {
- if (mTvView == null) {
+ if (mTvView == null || cmdType == null) {
return;
}
switch (cmdType) {
@@ -271,7 +303,8 @@ public class IAppManager {
}
@Override
- public void onStateChanged(String iAppServiceId, int state, int err) {}
+ public void onStateChanged(String iAppServiceId, int state, int err) {
+ }
@Override
public void onBiInteractiveAppCreated(String iAppServiceId, Uri biIAppUri,
@@ -281,7 +314,13 @@ public class IAppManager {
public void onTeletextAppStateChanged(String iAppServiceId, int state) {}
@Override
- public void onSetVideoBounds(String iAppServiceId, Rect rect) {}
+ public void onSetVideoBounds(String iAppServiceId, Rect rect) {
+ if (mTvView != null) {
+ ViewGroup.MarginLayoutParams layoutParams = mTvView.getTvViewLayoutParams();
+ layoutParams.setMargins(rect.left, rect.top, rect.right, rect.bottom);
+ mTvView.setTvViewLayoutParams(layoutParams);
+ }
+ }
@Override
public void onRequestCurrentChannelUri(String iAppServiceId) {