aboutsummaryrefslogtreecommitdiff
path: root/src/com/android/tv/MainActivity.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/tv/MainActivity.java')
-rw-r--r--src/com/android/tv/MainActivity.java1498
1 files changed, 420 insertions, 1078 deletions
diff --git a/src/com/android/tv/MainActivity.java b/src/com/android/tv/MainActivity.java
index 58850b5f..ed5f79a1 100644
--- a/src/com/android/tv/MainActivity.java
+++ b/src/com/android/tv/MainActivity.java
@@ -27,14 +27,7 @@ import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.database.Cursor;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.Point;
import android.hardware.display.DisplayManager;
-import android.media.AudioManager;
-import android.media.MediaMetadata;
-import android.media.session.MediaSession;
-import android.media.session.PlaybackState;
import android.media.tv.TvContentRating;
import android.media.tv.TvContract;
import android.media.tv.TvContract.Channels;
@@ -44,7 +37,6 @@ import android.media.tv.TvInputManager.TvInputCallback;
import android.media.tv.TvTrackInfo;
import android.media.tv.TvView.OnUnhandledInputEventListener;
import android.net.Uri;
-import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
@@ -71,7 +63,6 @@ import android.view.accessibility.AccessibilityManager;
import android.widget.FrameLayout;
import android.widget.Toast;
-import com.android.tv.analytics.DurationTimer;
import com.android.tv.analytics.SendChannelStatusRunnable;
import com.android.tv.analytics.SendConfigInfoRunnable;
import com.android.tv.analytics.Tracker;
@@ -91,26 +82,30 @@ import com.android.tv.data.ProgramDataManager;
import com.android.tv.data.StreamInfo;
import com.android.tv.data.WatchedHistoryManager;
import com.android.tv.data.epg.EpgFetcher;
+import com.android.tv.dialog.HalfSizedDialogFragment;
import com.android.tv.dialog.PinDialogFragment;
+import com.android.tv.dialog.PinDialogFragment.OnPinCheckedListener;
import com.android.tv.dialog.SafeDismissDialogFragment;
-import com.android.tv.dvr.ConflictChecker;
import com.android.tv.dvr.DvrManager;
-import com.android.tv.dvr.DvrUiHelper;
-import com.android.tv.dvr.ScheduledRecording;
+import com.android.tv.dvr.data.ScheduledRecording;
+import com.android.tv.dvr.recorder.ConflictChecker;
import com.android.tv.dvr.ui.DvrStopRecordingFragment;
-import com.android.tv.dvr.ui.HalfSizedDialogFragment;
-import com.android.tv.experiments.Experiments;
+import com.android.tv.dvr.ui.DvrUiHelper;
import com.android.tv.menu.Menu;
import com.android.tv.onboarding.OnboardingActivity;
import com.android.tv.parental.ContentRatingsManager;
import com.android.tv.parental.ParentalControlSettings;
-import com.android.tv.receiver.AudioCapabilitiesReceiver;
+import com.android.tv.perf.EventNames;
+import com.android.tv.perf.PerformanceMonitor;
+import com.android.tv.perf.StubPerformanceMonitor;
+import com.android.tv.perf.TimerEvent;
+import com.android.tv.recommendation.ChannelPreviewUpdater;
import com.android.tv.recommendation.NotificationService;
import com.android.tv.search.ProgramGuideSearchFragment;
+import com.android.tv.tuner.TunerInputController;
import com.android.tv.tuner.TunerPreferences;
import com.android.tv.tuner.setup.TunerSetupActivity;
import com.android.tv.tuner.tvinput.TunerTvInputService;
-import com.android.tv.ui.AppLayerTvView;
import com.android.tv.ui.ChannelBannerView;
import com.android.tv.ui.InputBannerView;
import com.android.tv.ui.KeypadChannelSwitchView;
@@ -128,23 +123,22 @@ import com.android.tv.ui.sidepanel.DisplayModeFragment;
import com.android.tv.ui.sidepanel.MultiAudioFragment;
import com.android.tv.ui.sidepanel.SettingsFragment;
import com.android.tv.ui.sidepanel.SideFragment;
+import com.android.tv.ui.sidepanel.parentalcontrols.ParentalControlsFragment;
import com.android.tv.util.AccountHelper;
import com.android.tv.util.CaptionSettings;
+import com.android.tv.util.Debug;
+import com.android.tv.util.DurationTimer;
import com.android.tv.util.ImageCache;
-import com.android.tv.util.ImageLoader;
import com.android.tv.util.OnboardingUtils;
import com.android.tv.util.PermissionUtils;
-import com.android.tv.util.PipInputManager;
-import com.android.tv.util.PipInputManager.PipInput;
import com.android.tv.util.RecurringRunner;
-import com.android.tv.util.SearchManagerHelper;
import com.android.tv.util.SetupUtils;
import com.android.tv.util.SystemProperties;
import com.android.tv.util.TvInputManagerHelper;
import com.android.tv.util.TvSettings;
-import com.android.tv.util.TvSettings.PipSound;
import com.android.tv.util.TvTrackInfoUtils;
import com.android.tv.util.Utils;
+import com.android.tv.util.ViewCache;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -159,8 +153,7 @@ import java.util.concurrent.TimeUnit;
/**
* The main activity for the Live TV app.
*/
-public class MainActivity extends Activity implements AudioManager.OnAudioFocusChangeListener,
- OnActionClickListener {
+public class MainActivity extends Activity implements OnActionClickListener, OnPinCheckedListener {
private static final String TAG = "MainActivity";
private static final boolean DEBUG = false;
@@ -175,18 +168,11 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
private static final boolean USE_BACK_KEY_LONG_PRESS = false;
- private static final float AUDIO_MAX_VOLUME = 1.0f;
- private static final float AUDIO_MIN_VOLUME = 0.0f;
- private static final float AUDIO_DUCKING_VOLUME = 0.3f;
private static final float FRAME_RATE_FOR_FILM = 23.976f;
private static final float FRAME_RATE_EPSILON = 0.1f;
- private static final float MEDIA_SESSION_STOPPED_SPEED = 0.0f;
- private static final float MEDIA_SESSION_PLAYING_SPEED = 1.0f;
-
private static final int PERMISSIONS_REQUEST_READ_TV_LISTINGS = 1;
- private static final int PERMISSIONS_REQUEST_ACCESS_COARSE_LOCATION = 2;
private static final String PERMISSION_READ_TV_LISTINGS = "android.permission.READ_TV_LISTINGS";
// Tracker screen names.
@@ -211,49 +197,26 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
}
+ private static final IntentFilter SYSTEM_INTENT_FILTER = new IntentFilter();
+ static {
+ SYSTEM_INTENT_FILTER.addAction(TvInputManager.ACTION_PARENTAL_CONTROLS_ENABLED_CHANGED);
+ SYSTEM_INTENT_FILTER.addAction(Intent.ACTION_SCREEN_OFF);
+ SYSTEM_INTENT_FILTER.addAction(Intent.ACTION_SCREEN_ON);
+ SYSTEM_INTENT_FILTER.addAction(Intent.ACTION_TIME_CHANGED);
+ }
+
private static final int REQUEST_CODE_START_SETUP_ACTIVITY = 1;
- private static final int REQUEST_CODE_START_SYSTEM_CAPTIONING_SETTINGS = 2;
private static final String KEY_INIT_CHANNEL_ID = "com.android.tv.init_channel_id";
- private static final String MEDIA_SESSION_TAG = "com.android.tv.mediasession";
-
// Change channels with key long press.
private static final int CHANNEL_CHANGE_NORMAL_SPEED_DURATION_MS = 3000;
private static final int CHANNEL_CHANGE_DELAY_MS_IN_MAX_SPEED = 50;
private static final int CHANNEL_CHANGE_DELAY_MS_IN_NORMAL_SPEED = 200;
private static final int CHANNEL_CHANGE_INITIAL_DELAY_MILLIS = 500;
- private static final int FIRST_STREAM_INFO_UPDATE_DELAY_MILLIS = 500;
private static final int MSG_CHANNEL_DOWN_PRESSED = 1000;
private static final int MSG_CHANNEL_UP_PRESSED = 1001;
- private static final int MSG_UPDATE_CHANNEL_BANNER_BY_INFO_UPDATE = 1002;
-
- @Retention(RetentionPolicy.SOURCE)
- @IntDef({UPDATE_CHANNEL_BANNER_REASON_FORCE_SHOW, UPDATE_CHANNEL_BANNER_REASON_TUNE,
- UPDATE_CHANNEL_BANNER_REASON_TUNE_FAST, UPDATE_CHANNEL_BANNER_REASON_UPDATE_INFO,
- UPDATE_CHANNEL_BANNER_REASON_LOCK_OR_UNLOCK})
- private @interface ChannelBannerUpdateReason {}
- /**
- * Updates channel banner because the channel banner is forced to show.
- */
- private static final int UPDATE_CHANNEL_BANNER_REASON_FORCE_SHOW = 1;
- /**
- * Updates channel banner because of tuning.
- */
- private static final int UPDATE_CHANNEL_BANNER_REASON_TUNE = 2;
- /**
- * Updates channel banner because of fast tuning.
- */
- private static final int UPDATE_CHANNEL_BANNER_REASON_TUNE_FAST = 3;
- /**
- * Updates channel banner because of info updating.
- */
- private static final int UPDATE_CHANNEL_BANNER_REASON_UPDATE_INFO = 4;
- /**
- * Updates channel banner because the current watched channel is locked or unlocked.
- */
- private static final int UPDATE_CHANNEL_BANNER_REASON_LOCK_OR_UNLOCK = 5;
private static final int TVVIEW_SET_MAIN_TIMEOUT_MS = 3000;
@@ -261,12 +224,14 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
// Delay 1 second in order not to interrupt the first tune.
private static final long LAZY_INITIALIZATION_DELAY = TimeUnit.SECONDS.toMillis(1);
+ private static final int UNDEFINED_TRACK_INDEX = -1;
+ private static final long START_UP_TIMER_RESET_THRESHOLD_MS = TimeUnit.SECONDS.toMillis(3);
+
private AccessibilityManager mAccessibilityManager;
private ChannelDataManager mChannelDataManager;
private ProgramDataManager mProgramDataManager;
private TvInputManagerHelper mTvInputManagerHelper;
private ChannelTuner mChannelTuner;
- private PipInputManager mPipInputManager;
private final TvOptionsManager mTvOptionsManager = new TvOptionsManager(this);
private TvViewUiManager mTvViewUiManager;
private TimeShiftManager mTimeShiftManager;
@@ -278,12 +243,7 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
private View mContentView;
private TunableTvView mTvView;
- private TunableTvView mPipView;
private Bundle mTuneParams;
- private boolean mChannelBannerHiddenBySideFragment;
- // TODO: Move the scene views into TvTransitionManager or TvOverlayManager.
- private ChannelBannerView mChannelBannerView;
- private KeypadChannelSwitchView mKeypadChannelSwitchView;
@Nullable
private Uri mInitChannelUri;
@Nullable
@@ -293,20 +253,13 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
private boolean mShowSelectInputView;
private TvInputInfo mInputToSetUp;
private final List<MemoryManageable> mMemoryManageables = new ArrayList<>();
- private MediaSession mMediaSession;
- private int mNowPlayingCardWidth;
- private int mNowPlayingCardHeight;
+ private MediaSessionWrapper mMediaSessionWrapper;
private final MyOnTuneListener mOnTuneListener = new MyOnTuneListener();
private String mInputIdUnderSetup;
private boolean mIsSetupActivityCalledByPopup;
- private AudioManager mAudioManager;
- private int mAudioFocusStatus;
+ private AudioManagerHelper mAudioManagerHelper;
private boolean mTunePending;
- private boolean mPipEnabled;
- private Channel mPipChannel;
- private boolean mPipSwap;
- @PipSound private int mPipSound = TvSettings.PIP_SOUND_MAIN; // Default
private boolean mDebugNonFullSizeScreen;
private boolean mActivityResumed;
private boolean mActivityStarted;
@@ -316,10 +269,10 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
private boolean mBackKeyPressed;
private boolean mNeedShowBackKeyGuide;
private boolean mVisibleBehind;
- private boolean mAc3PassthroughSupported;
private boolean mShowNewSourcesFragment = true;
private String mTunerInputId;
private boolean mOtherActivityLaunched;
+ private PerformanceMonitor mPerformanceMonitor;
private boolean mIsFilmModeSet;
private float mDefaultRefreshRate;
@@ -331,11 +284,8 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
private boolean mIsCurrentChannelUnblockedByUser;
private boolean mWasChannelUnblockedBeforeShrunkenByUser;
private Channel mChannelBeforeShrunkenTvView;
- private Channel mPipChannelBeforeShrunkenTvView;
private boolean mIsCompletingShrunkenTvView;
- // TODO: Need to consider the case that TIS explicitly request PIN code while TV view is
- // shrunken.
private TvContentRating mLastAllowedRatingForCurrentChannel;
private TvContentRating mAllowedRatingBeforeShrunken;
@@ -346,42 +296,46 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
private static final int MAX_RECENT_CHANNELS = 5;
private final ArrayDeque<Long> mRecentChannels = new ArrayDeque<>(MAX_RECENT_CHANNELS);
- private AudioCapabilitiesReceiver mAudioCapabilitiesReceiver;
private RecurringRunner mSendConfigInfoRecurringRunner;
private RecurringRunner mChannelStatusRecurringRunner;
- // A caller which started this activity. (e.g. TvSearch)
- private String mSource;
-
private final Handler mHandler = new MainActivityHandler(this);
private final Set<OnActionClickListener> mOnActionClickListeners = new ArraySet<>();
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
- if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
- if (DEBUG) Log.d(TAG, "Received ACTION_SCREEN_OFF");
- // We need to stop TvView, when the screen is turned off. If not and TIS uses
- // MediaPlayer, a device may not go to the sleep mode and audio can be heard,
- // because MediaPlayer keeps playing media by its wake lock.
- mScreenOffIntentReceived = true;
- markCurrentChannelDuringScreenOff();
- stopAll(true);
- } else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
- if (DEBUG) Log.d(TAG, "Received ACTION_SCREEN_ON");
- if (!mActivityResumed && mVisibleBehind) {
- // ACTION_SCREEN_ON is usually called after onResume. But, if media is played
- // under launcher with requestVisibleBehind(true), onResume will not be called.
- // In this case, we need to resume TvView and PipView explicitly.
- resumeTvIfNeeded();
- resumePipIfNeeded();
- }
- } else if (intent.getAction().equals(
- TvInputManager.ACTION_PARENTAL_CONTROLS_ENABLED_CHANGED)) {
- if (DEBUG) Log.d(TAG, "Received parental control settings change");
- checkChannelLockNeeded(mTvView);
- checkChannelLockNeeded(mPipView);
- applyParentalControlSettings();
+ switch (intent.getAction()) {
+ case Intent.ACTION_SCREEN_OFF:
+ if (DEBUG) Log.d(TAG, "Received ACTION_SCREEN_OFF");
+ // We need to stop TvView, when the screen is turned off. If not and TIS uses
+ // MediaPlayer, a device may not go to the sleep mode and audio can be heard,
+ // because MediaPlayer keeps playing media by its wake lock.
+ mScreenOffIntentReceived = true;
+ markCurrentChannelDuringScreenOff();
+ stopAll(true);
+ break;
+ case Intent.ACTION_SCREEN_ON:
+ if (DEBUG) Log.d(TAG, "Received ACTION_SCREEN_ON");
+ if (!mActivityResumed && mVisibleBehind) {
+ // ACTION_SCREEN_ON is usually called after onResume. But, if media is
+ // played under launcher with requestVisibleBehind(true), onResume will
+ // not be called. In this case, we need to resume TvView explicitly.
+ resumeTvIfNeeded();
+ }
+ break;
+ case TvInputManager.ACTION_PARENTAL_CONTROLS_ENABLED_CHANGED:
+ if (DEBUG) Log.d(TAG, "Received parental control settings change");
+ applyParentalControlSettings();
+ checkChannelLockNeeded(mTvView, null);
+ break;
+ case Intent.ACTION_TIME_CHANGED:
+ // Re-tune the current channel to prevent incorrect behavior of trick-play.
+ // See: b/37393628
+ if (mChannelTuner.getCurrentChannel() != null) {
+ tune(true);
+ }
+ break;
}
}
};
@@ -397,8 +351,9 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
}
Channel channel = mTvView.getCurrentChannel();
if (channel != null && channel.getId() == channelId) {
- updateChannelBannerAndShowIfNeeded(UPDATE_CHANNEL_BANNER_REASON_UPDATE_INFO);
- updateMediaSession();
+ mOverlayManager.updateChannelBannerAndShowIfNeeded(
+ TvOverlayManager.UPDATE_CHANNEL_BANNER_REASON_UPDATE_INFO);
+ mMediaSessionWrapper.update(mTvView.isBlocked(), channel, program);
}
}
};
@@ -407,36 +362,39 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
new ChannelTuner.Listener() {
@Override
public void onLoadFinished() {
+ Debug.getTimer(Debug.TAG_START_UP_TIMER).log(
+ "MainActivity.mChannelTunerListener.onLoadFinished");
SetupUtils.getInstance(MainActivity.this).markNewChannelsBrowsable();
if (mActivityResumed) {
resumeTvIfNeeded();
- resumePipIfNeeded();
}
- mKeypadChannelSwitchView.setChannels(mChannelTuner.getBrowsableChannelList());
+ mOverlayManager.onBrowsableChannelsUpdated();
}
@Override
public void onBrowsableChannelListChanged() {
- mKeypadChannelSwitchView.setChannels(mChannelTuner.getBrowsableChannelList());
+ mOverlayManager.onBrowsableChannelsUpdated();
}
@Override
public void onCurrentChannelUnavailable(Channel channel) {
- // TODO: handle the case that a channel is suddenly removed from DB.
+ if (mChannelTuner.moveToAdjacentBrowsableChannel(true)) {
+ tune(true);
+ } else {
+ stopTv("onCurrentChannelUnavailable()", false);
+ }
}
@Override
- public void onChannelChanged(Channel previousChannel, Channel currentChannel) {
- }
+ public void onChannelChanged(Channel previousChannel, Channel currentChannel) {}
};
- private final Runnable mRestoreMainViewRunnable =
- new Runnable() {
- @Override
- public void run() {
- restoreMainTvView();
- }
- };
+ private final Runnable mRestoreMainViewRunnable = new Runnable() {
+ @Override
+ public void run() {
+ restoreMainTvView();
+ }
+ };
private ProgramGuideSearchFragment mSearchFragment;
private final TvInputCallback mTvInputCallback = new TvInputCallback() {
@@ -456,54 +414,54 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
boolean parentalControlEnabled = mTvInputManagerHelper.getParentalControlSettings()
.isParentalControlsEnabled();
mTvView.onParentalControlChanged(parentalControlEnabled);
- mPipView.onParentalControlChanged(parentalControlEnabled);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ ChannelPreviewUpdater.getInstance(this).updatePreviewDataForChannelsImmediately();
+ }
}
@Override
protected void onCreate(Bundle savedInstanceState) {
+ TimerEvent timer = StubPerformanceMonitor.startBootstrapTimer();
+ DurationTimer startUpDebugTimer = Debug.getTimer(Debug.TAG_START_UP_TIMER);
+ if (!startUpDebugTimer.isStarted()
+ || startUpDebugTimer.getDuration() > START_UP_TIMER_RESET_THRESHOLD_MS) {
+ // TvApplication can start by other reason before MainActivty is launched.
+ // In this case, we restart the timer.
+ startUpDebugTimer.start();
+ }
+ startUpDebugTimer.log("MainActivity.onCreate");
if (DEBUG) Log.d(TAG,"onCreate()");
TvApplication.setCurrentRunningProcess(this, true);
super.onCreate(savedInstanceState);
+ ApplicationSingletons applicationSingletons = TvApplication.getSingletons(this);
+ if (!applicationSingletons.getTvInputManagerHelper().hasTvInputManager()) {
+ Log.wtf(TAG, "Stopping because device does not have a TvInputManager");
+ finishAndRemoveTask();
+ return;
+ }
+ mPerformanceMonitor = applicationSingletons.getPerformanceMonitor();
- boolean isPassthroughInput = TvContract.isChannelUriForPassthroughInput(getIntent()
- .getData());
- boolean skipToShowOnboarding = Intent.ACTION_VIEW.equals(getIntent().getAction())
+ TvApplication tvApplication = (TvApplication) getApplication();
+ mChannelDataManager = tvApplication.getChannelDataManager();
+ // In API 23, TvContract.isChannelUriForPassthroughInput is hidden.
+ boolean isPassthroughInput =
+ TvContract.isChannelUriForPassthroughInput(getIntent().getData());
+ boolean tuneToPassthroughInput = Intent.ACTION_VIEW.equals(getIntent().getAction())
&& isPassthroughInput;
- if (OnboardingUtils.needToShowOnboarding(this) && !skipToShowOnboarding
+ boolean channelLoadedAndNoChannelAvailable = mChannelDataManager.isDbLoadFinished()
+ && mChannelDataManager.getChannelCount() <= 0;
+ if ((OnboardingUtils.isFirstRunWithCurrentVersion(this)
+ || channelLoadedAndNoChannelAvailable)
+ && !tuneToPassthroughInput
&& !TvCommonUtils.isRunningInTest()) {
- // TODO: The onboarding is turned off in test, because tests are broken by the
- // onboarding. We need to enable the feature for tests later.
- startActivity(OnboardingActivity.buildIntent(this, getIntent()));
- finish();
+ startOnboardingActivity();
return;
}
-
- // Check this permission for the EPG fetch.
- // TODO: check {@link shouldShowRequestPermissionRationale}.
- // While testing, no way to allow the permission when the dialog shows up. So we'd better
- // not show the dialog.
- if (!TvCommonUtils.isRunningInTest() && Utils.hasInternalTvInputs(this, true)
- && checkSelfPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION)
- != PackageManager.PERMISSION_GRANTED) {
- requestPermissions(new String[] {android.Manifest.permission.ACCESS_COARSE_LOCATION},
- PERMISSIONS_REQUEST_ACCESS_COARSE_LOCATION);
- }
-
- DisplayManager displayManager = (DisplayManager) getSystemService(Context.DISPLAY_SERVICE);
- Display display = displayManager.getDisplay(Display.DEFAULT_DISPLAY);
- Point size = new Point();
- display.getSize(size);
- int screenWidth = size.x;
- int screenHeight = size.y;
- mDefaultRefreshRate = display.getRefreshRate();
-
setContentView(R.layout.activity_tv);
- mContentView = findViewById(android.R.id.content);
+ mProgramDataManager = tvApplication.getProgramDataManager();
+ mTvInputManagerHelper = tvApplication.getTvInputManagerHelper();
mTvView = (TunableTvView) findViewById(R.id.main_tunable_tv_view);
- int shrunkenTvViewHeight = getResources().getDimensionPixelSize(
- R.dimen.shrunken_tvview_height);
- mTvView.initialize((AppLayerTvView) findViewById(R.id.main_tv_view), false, screenHeight,
- shrunkenTvViewHeight);
+ mTvView.initialize(mProgramDataManager, mTvInputManagerHelper);
mTvView.setOnUnhandledInputEventListener(new OnUnhandledInputEventListener() {
@Override
public boolean onUnhandledInputEvent(InputEvent event) {
@@ -526,7 +484,6 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
return false;
}
});
-
long channelId = Utils.getLastWatchedChannelId(this);
String inputId = Utils.getLastWatchedTunerInputId(this);
if (!isPassthroughInput && inputId != null
@@ -534,27 +491,21 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
mTvView.warmUpInput(inputId, TvContract.buildChannelUri(channelId));
}
- TvApplication tvApplication = (TvApplication) getApplication();
tvApplication.getMainActivityWrapper().onMainActivityCreated(this);
if (BuildConfig.ENG && SystemProperties.ALLOW_STRICT_MODE.getValue()) {
Toast.makeText(this, "Using Strict Mode for eng builds", Toast.LENGTH_SHORT).show();
}
mTracker = tvApplication.getTracker();
- mTvInputManagerHelper = tvApplication.getTvInputManagerHelper();
if (Features.TUNER.isEnabled(this)) {
mTvInputManagerHelper.addCallback(mTvInputCallback);
}
mTunerInputId = TunerTvInputService.getInputId(this);
- mChannelDataManager = tvApplication.getChannelDataManager();
- mProgramDataManager = tvApplication.getProgramDataManager();
mProgramDataManager.addOnCurrentProgramUpdatedListener(Channel.INVALID_ID,
mOnCurrentProgramUpdatedListener);
mProgramDataManager.setPrefetchEnabled(true);
mChannelTuner = new ChannelTuner(mChannelDataManager, mTvInputManagerHelper);
mChannelTuner.addListener(mChannelTunerListener);
mChannelTuner.start();
- mPipInputManager = new PipInputManager(this, mTvInputManagerHelper, mChannelTuner);
- mPipInputManager.start();
mMemoryManageables.add(mProgramDataManager);
mMemoryManageables.add(ImageCache.getInstance());
mMemoryManageables.add(TvContentRatingCache.getInstance());
@@ -565,28 +516,29 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
new OnCurrentProgramUpdatedListener() {
@Override
public void onCurrentProgramUpdated(long channelId, Program program) {
- updateMediaSession();
+ mMediaSessionWrapper.update(mTvView.isBlocked(), getCurrentChannel(),
+ program);
switch (mTimeShiftManager.getLastActionId()) {
case TimeShiftManager.TIME_SHIFT_ACTION_ID_REWIND:
case TimeShiftManager.TIME_SHIFT_ACTION_ID_FAST_FORWARD:
case TimeShiftManager.TIME_SHIFT_ACTION_ID_JUMP_TO_PREVIOUS:
case TimeShiftManager.TIME_SHIFT_ACTION_ID_JUMP_TO_NEXT:
- updateChannelBannerAndShowIfNeeded(
- UPDATE_CHANNEL_BANNER_REASON_FORCE_SHOW);
+ mOverlayManager.updateChannelBannerAndShowIfNeeded(
+ TvOverlayManager.UPDATE_CHANNEL_BANNER_REASON_FORCE_SHOW);
break;
case TimeShiftManager.TIME_SHIFT_ACTION_ID_PAUSE:
case TimeShiftManager.TIME_SHIFT_ACTION_ID_PLAY:
default:
- updateChannelBannerAndShowIfNeeded(
- UPDATE_CHANNEL_BANNER_REASON_UPDATE_INFO);
+ mOverlayManager.updateChannelBannerAndShowIfNeeded(
+ TvOverlayManager.UPDATE_CHANNEL_BANNER_REASON_UPDATE_INFO);
break;
}
}
});
- mPipView = (TunableTvView) findViewById(R.id.pip_tunable_tv_view);
- mPipView.initialize((AppLayerTvView) findViewById(R.id.pip_tv_view), true, screenHeight,
- shrunkenTvViewHeight);
+ DisplayManager displayManager = (DisplayManager) getSystemService(Context.DISPLAY_SERVICE);
+ Display display = displayManager.getDisplay(Display.DEFAULT_DISPLAY);
+ mDefaultRefreshRate = display.getRefreshRate();
if (!PermissionUtils.hasAccessWatchedHistory(this)) {
WatchedHistoryManager watchedHistoryManager = new WatchedHistoryManager(
@@ -594,17 +546,15 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
watchedHistoryManager.start();
mTvView.setWatchedHistoryManager(watchedHistoryManager);
}
- mTvViewUiManager = new TvViewUiManager(this, mTvView, mPipView,
+ mTvViewUiManager = new TvViewUiManager(this, mTvView,
(FrameLayout) findViewById(android.R.id.content), mTvOptionsManager);
- mPipView.setFixedSurfaceSize(screenWidth / 2, screenHeight / 2);
- mPipView.setBlockScreenType(TunableTvView.BLOCK_SCREEN_TYPE_SHRUNKEN_TV_VIEW);
-
+ mContentView = findViewById(android.R.id.content);
ViewGroup sceneContainer = (ViewGroup) findViewById(R.id.scene_container);
- mChannelBannerView = (ChannelBannerView) getLayoutInflater().inflate(
+ ChannelBannerView channelBannerView = (ChannelBannerView) getLayoutInflater().inflate(
R.layout.channel_banner, sceneContainer, false);
- mKeypadChannelSwitchView = (KeypadChannelSwitchView) getLayoutInflater().inflate(
- R.layout.keypad_channel_switch, sceneContainer, false);
+ KeypadChannelSwitchView keypadChannelSwitchView = (KeypadChannelSwitchView)
+ getLayoutInflater().inflate(R.layout.keypad_channel_switch, sceneContainer, false);
InputBannerView inputBannerView = (InputBannerView) getLayoutInflater()
.inflate(R.layout.input_banner, sceneContainer, false);
SelectInputView selectInputView = (SelectInputView) getLayoutInflater()
@@ -641,26 +591,12 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
}
});
mSearchFragment = new ProgramGuideSearchFragment();
- mOverlayManager = new TvOverlayManager(this, mChannelTuner, mTvView,
- mKeypadChannelSwitchView, mChannelBannerView, inputBannerView,
+ mOverlayManager = new TvOverlayManager(this, mChannelTuner, mTvView, mTvOptionsManager,
+ keypadChannelSwitchView, channelBannerView, inputBannerView,
selectInputView, sceneContainer, mSearchFragment);
- mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
- mAudioFocusStatus = AudioManager.AUDIOFOCUS_LOSS;
-
- mMediaSession = new MediaSession(this, MEDIA_SESSION_TAG);
- mMediaSession.setCallback(new MediaSession.Callback() {
- @Override
- public boolean onMediaButtonEvent(@NonNull Intent mediaButtonIntent) {
- // Consume the media button event here. Should not send it to other apps.
- return true;
- }
- });
- mMediaSession.setFlags(MediaSession.FLAG_HANDLES_MEDIA_BUTTONS |
- MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS);
- mNowPlayingCardWidth = getResources().getDimensionPixelSize(
- R.dimen.notif_card_img_max_width);
- mNowPlayingCardHeight = getResources().getDimensionPixelSize(R.dimen.notif_card_img_height);
+ mAudioManagerHelper = new AudioManagerHelper(this, mTvView);
+ mMediaSessionWrapper = new MediaSessionWrapper(this);
mTvViewUiManager.restoreDisplayMode(false);
if (!handleIntent(getIntent())) {
@@ -668,15 +604,6 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
return;
}
- mAudioCapabilitiesReceiver = new AudioCapabilitiesReceiver(this,
- new AudioCapabilitiesReceiver.OnAc3PassthroughCapabilityChangeListener() {
- @Override
- public void onAc3PassthroughCapabilityChange(boolean capability) {
- mAc3PassthroughSupported = capability;
- }
- });
- mAudioCapabilitiesReceiver.register();
-
mAccessibilityManager =
(AccessibilityManager) getSystemService(Context.ACCESSIBILITY_SERVICE);
mSendConfigInfoRecurringRunner = new RecurringRunner(this, TimeUnit.DAYS.toMillis(1),
@@ -692,6 +619,13 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
mDvrConflictChecker = new ConflictChecker(this);
}
initForTest();
+ Debug.getTimer(Debug.TAG_START_UP_TIMER).log("MainActivity.onCreate end");
+ mPerformanceMonitor.stopTimer(timer, EventNames.MAIN_ACTIVITY_ONCREATE);
+ }
+
+ private void startOnboardingActivity() {
+ startActivity(OnboardingActivity.buildIntent(this, getIntent()));
+ finish();
}
@Override
@@ -705,32 +639,21 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
- switch (requestCode) {
- case PERMISSIONS_REQUEST_READ_TV_LISTINGS:
- if (grantResults.length > 0
- && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
- // Start reload of dependent data
- mChannelDataManager.reload();
- mProgramDataManager.reload();
-
- // Restart live channels.
- Intent intent = getIntent();
- finish();
- startActivity(intent);
- } else {
- Toast.makeText(this, R.string.msg_read_tv_listing_permission_denied,
- Toast.LENGTH_LONG).show();
- finish();
- }
- break;
- case PERMISSIONS_REQUEST_ACCESS_COARSE_LOCATION:
- if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED
- && Experiments.CLOUD_EPG.get()) {
- EpgFetcher.getInstance(this).startImmediately();
- } else {
- EpgFetcher.getInstance(this).stop();
- }
- break;
+ if (requestCode == PERMISSIONS_REQUEST_READ_TV_LISTINGS) {
+ if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
+ // Start reload of dependent data
+ mChannelDataManager.reload();
+ mProgramDataManager.reload();
+
+ // Restart live channels.
+ Intent intent = getIntent();
+ finish();
+ startActivity(intent);
+ } else {
+ Toast.makeText(this, R.string.msg_read_tv_listing_permission_denied,
+ Toast.LENGTH_LONG).show();
+ finish();
+ }
}
}
@@ -781,6 +704,7 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
@Override
protected void onStart() {
+ TimerEvent timer = mPerformanceMonitor.startTimer();
if (DEBUG) Log.d(TAG,"onStart()");
super.onStart();
mScreenOffIntentReceived = false;
@@ -789,23 +713,25 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
mMainDurationTimer.start();
applyParentalControlSettings();
- IntentFilter intentFilter = new IntentFilter();
- intentFilter.addAction(TvInputManager.ACTION_PARENTAL_CONTROLS_ENABLED_CHANGED);
- intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
- intentFilter.addAction(Intent.ACTION_SCREEN_ON);
- registerReceiver(mBroadcastReceiver, intentFilter);
+ registerReceiver(mBroadcastReceiver, SYSTEM_INTENT_FILTER);
- Intent notificationIntent = new Intent(this, NotificationService.class);
- notificationIntent.setAction(NotificationService.ACTION_SHOW_RECOMMENDATION);
- startService(notificationIntent);
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
+ Intent notificationIntent = new Intent(this, NotificationService.class);
+ notificationIntent.setAction(NotificationService.ACTION_SHOW_RECOMMENDATION);
+ startService(notificationIntent);
+ }
+ TunerInputController.executeNetworkTunerDiscoveryAsyncTask(this);
+
+ EpgFetcher.getInstance(this).fetchImmediatelyIfNeeded();
+ mPerformanceMonitor.stopTimer(timer, EventNames.MAIN_ACTIVITY_ONSTART);
}
@Override
protected void onResume() {
+ TimerEvent timer = mPerformanceMonitor.startTimer();
+ Debug.getTimer(Debug.TAG_START_UP_TIMER).log("MainActivity.onResume start");
if (DEBUG) Log.d(TAG, "onResume()");
super.onResume();
- // Refresh the remote config, it is throttled automatically.
- TvApplication.getSingletons(this).getRemoteConfig().fetch(null);
if (!PermissionUtils.hasAccessAllEpg(this)
&& checkSelfPermission(PERMISSION_READ_TV_LISTINGS)
!= PackageManager.PERMISSION_GRANTED) {
@@ -819,23 +745,23 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
mActivityResumed = true;
mShowNewSourcesFragment = true;
mOtherActivityLaunched = false;
- int result = mAudioManager.requestAudioFocus(MainActivity.this,
- AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
- mAudioFocusStatus = (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) ?
- AudioManager.AUDIOFOCUS_GAIN : AudioManager.AUDIOFOCUS_LOSS;
- setVolumeByAudioFocusStatus();
+ mAudioManagerHelper.requestAudioFocus();
if (mTvView.isPlaying()) {
// Every time onResume() is called the activity will be assumed to not have requested
// visible behind.
requestVisibleBehind(true);
}
- if (Utils.hasRecordingFailedReason(getApplicationContext(),
- TvInputManager.RECORDING_ERROR_INSUFFICIENT_SPACE)) {
+ Set<String> failedScheduledRecordingInfoSet =
+ Utils.getFailedScheduledRecordingInfoSet(getApplicationContext());
+ if (Utils.hasRecordingFailedReason(
+ getApplicationContext(), TvInputManager.RECORDING_ERROR_INSUFFICIENT_SPACE)
+ && !failedScheduledRecordingInfoSet.isEmpty()) {
runAfterAttachedToWindow(new Runnable() {
@Override
public void run() {
- DvrUiHelper.showDvrInsufficientSpaceErrorDialog(MainActivity.this);
+ DvrUiHelper.showDvrInsufficientSpaceErrorDialog(MainActivity.this,
+ failedScheduledRecordingInfoSet);
}
});
}
@@ -843,13 +769,11 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
if (mChannelTuner.areAllChannelsLoaded()) {
SetupUtils.getInstance(this).markNewChannelsBrowsable();
resumeTvIfNeeded();
- resumePipIfNeeded();
}
mOverlayManager.showMenuWithTimeShiftPauseIfNeeded();
- // Note: The following codes are related to pop up an overlay UI after resume.
- // When the following code is changed, please check the variable
- // willShowOverlayUiAfterResume in updateChannelBannerAndShowIfNeeded.
+ // NOTE: The following codes are related to pop up an overlay UI after resume. When
+ // the following code is changed, please modify willShowOverlayUiWhenResume() accordingly.
if (mInputToSetUp != null) {
startSetupActivity(mInputToSetUp, false);
mInputToSetUp = null;
@@ -881,6 +805,8 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
if (mDvrConflictChecker != null) {
mDvrConflictChecker.start();
}
+ Debug.getTimer(Debug.TAG_START_UP_TIMER).log("MainActivity.onResume end");
+ mPerformanceMonitor.stopTimer(timer, EventNames.MAIN_ACTIVITY_ONRESUME);
}
@Override
@@ -893,18 +819,12 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
mActivityResumed = false;
mOverlayManager.hideOverlays(TvOverlayManager.FLAG_HIDE_OVERLAYS_DEFAULT);
mTvView.setBlockScreenType(TunableTvView.BLOCK_SCREEN_TYPE_NO_UI);
- if (mPipEnabled) {
- mTvViewUiManager.hidePipForPause();
- }
mBackKeyPressed = false;
mShowLockedChannelsTemporarily = false;
mShouldTuneToTunerChannel = false;
if (!mVisibleBehind) {
- mAudioFocusStatus = AudioManager.AUDIOFOCUS_LOSS;
- mAudioManager.abandonAudioFocus(this);
- if (mMediaSession.isActive()) {
- mMediaSession.setActive(false);
- }
+ mAudioManagerHelper.abandonAudioFocus();
+ mMediaSessionWrapper.setPlaybackState(false);
mTracker.sendScreenView("");
} else {
mTracker.sendScreenView(SCREEN_BEHIND_NAME);
@@ -933,6 +853,32 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
return state;
}
+ @Override
+ public void onPinChecked(boolean checked, int type, String rating) {
+ if (checked) {
+ switch (type) {
+ case PinDialogFragment.PIN_DIALOG_TYPE_UNLOCK_CHANNEL:
+ blockOrUnblockScreen(mTvView, false);
+ mIsCurrentChannelUnblockedByUser = true;
+ break;
+ case PinDialogFragment.PIN_DIALOG_TYPE_UNLOCK_PROGRAM:
+ TvContentRating unblockedRating = TvContentRating.unflattenFromString(rating);
+ mLastAllowedRatingForCurrentChannel = unblockedRating;
+ mTvView.unblockContent(unblockedRating);
+ break;
+ case PinDialogFragment.PIN_DIALOG_TYPE_ENTER_PIN:
+ mOverlayManager.getSideFragmentManager()
+ .show(new ParentalControlsFragment(), false);
+ // Pass through.
+ case PinDialogFragment.PIN_DIALOG_TYPE_NEW_PIN:
+ mOverlayManager.getSideFragmentManager().showSidePanel(true);
+ break;
+ }
+ } else if (type == PinDialogFragment.PIN_DIALOG_TYPE_ENTER_PIN) {
+ mOverlayManager.getSideFragmentManager().hideAll(false);
+ }
+ }
+
private void resumeTvIfNeeded() {
if (DEBUG) Log.d(TAG, "resumeTvIfNeeded()");
if (!mTvView.isPlaying() || mInitChannelUri != null
@@ -962,21 +908,6 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
mTvView.setBlockScreenType(getDesiredBlockScreenType());
}
- private void resumePipIfNeeded() {
- if (mPipEnabled && !(mPipView.isPlaying() && mPipView.isShown())) {
- if (mPipInputManager.areInSamePipInput(
- mChannelTuner.getCurrentChannel(), mPipChannel)) {
- enablePipView(false, false);
- } else {
- if (!mPipView.isPlaying()) {
- startPip(false);
- } else {
- mTvViewUiManager.showPipForResume();
- }
- }
- }
- }
-
private void startTv(Uri channelUri) {
if (DEBUG) Log.d(TAG, "startTv Uri=" + channelUri);
if ((channelUri == null || !TvContract.isChannelUriForPassthroughInput(channelUri))
@@ -993,7 +924,7 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
// TV has already started.
if (channelUri == null || channelUri.equals(mChannelTuner.getCurrentChannelUri())) {
// Simply adjust the volume without tune.
- setVolumeByAudioFocusStatus();
+ mAudioManagerHelper.setVolumeByAudioFocusStatus();
return;
}
stopTv();
@@ -1027,9 +958,9 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
}
}
- mTvView.start(mTvInputManagerHelper);
- setVolumeByAudioFocusStatus();
- tune();
+ mTvView.start();
+ mAudioManagerHelper.setVolumeByAudioFocusStatus();
+ tune(true);
}
@Override
@@ -1072,7 +1003,6 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
private void stopAll(boolean keepVisibleBehind) {
mOverlayManager.hideOverlays(TvOverlayManager.FLAG_HIDE_OVERLAYS_WITHOUT_ANIMATION);
stopTv("stopAll()", keepVisibleBehind);
- stopPip();
}
public TvInputManagerHelper getTvInputManagerHelper() {
@@ -1127,10 +1057,8 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
public void startSystemCaptioningSettingsActivity() {
Intent intent = new Intent(Settings.ACTION_CAPTIONING_SETTINGS);
- mOverlayManager.hideOverlays(TvOverlayManager.FLAG_HIDE_OVERLAYS_WITHOUT_ANIMATION
- | TvOverlayManager.FLAG_HIDE_OVERLAYS_KEEP_SIDE_PANEL_HISTORY);
try {
- startActivityForResultSafe(intent, REQUEST_CODE_START_SYSTEM_CAPTIONING_SETTINGS);
+ startActivitySafe(intent);
} catch (ActivityNotFoundException e) {
Toast.makeText(this, getString(R.string.msg_unable_to_start_system_captioning_settings),
Toast.LENGTH_SHORT).show();
@@ -1145,10 +1073,6 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
return mProgramDataManager;
}
- public PipInputManager getPipInputManager() {
- return mPipInputManager;
- }
-
public TvOptionsManager getTvOptionsManager() {
return mTvOptionsManager;
}
@@ -1185,13 +1109,6 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
}
/**
- * Returns true if the current connected TV supports AC3 passthough.
- */
- public boolean isAc3PassthroughSupported() {
- return mAc3PassthroughSupported;
- }
-
- /**
* Returns the current program which the user is watching right now.<p>
*
* It might be a live program. If the time shifting is available, it can be a past program, too.
@@ -1218,8 +1135,6 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
}
private Channel getBrowsableChannel() {
- // TODO: mChannelMap could be dirty for a while when the browsablity of channels
- // are changed. In that case, we shouldn't use the value from mChannelMap.
Channel curChannel = mChannelTuner.getCurrentChannel();
if (curChannel != null && curChannel.isBrowsable()) {
return curChannel;
@@ -1254,9 +1169,7 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
// Show ChannelSourcesFragment only if all the channels are loaded.
return;
}
- Channel currentChannel = mChannelTuner.getCurrentChannel();
- long channelId = currentChannel == null ? Channel.INVALID_ID : currentChannel.getId();
- mOverlayManager.getSideFragmentManager().show(new SettingsFragment(channelId));
+ mOverlayManager.getSideFragmentManager().show(new SettingsFragment());
}
public void showMerchantCollection() {
@@ -1272,19 +1185,11 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
mChannelBeforeShrunkenTvView = mTvView.getCurrentChannel();
mWasChannelUnblockedBeforeShrunkenByUser = mIsCurrentChannelUnblockedByUser;
mAllowedRatingBeforeShrunken = mLastAllowedRatingForCurrentChannel;
-
- if (willMainViewBeTunerInput && mChannelTuner.isCurrentChannelPassthrough()
- && mPipEnabled) {
- mPipChannelBeforeShrunkenTvView = mPipChannel;
- enablePipView(false, false);
- } else {
- mPipChannelBeforeShrunkenTvView = null;
- }
mTvViewUiManager.startShrunkenTvView();
if (showLockedChannelsTemporarily) {
mShowLockedChannelsTemporarily = true;
- checkChannelLockNeeded(mTvView);
+ checkChannelLockNeeded(mTvView, null);
}
mTvView.setBlockScreenType(getDesiredBlockScreenType());
@@ -1320,23 +1225,15 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
mIsCompletingShrunkenTvView = false;
mIsCurrentChannelUnblockedByUser = mWasChannelUnblockedBeforeShrunkenByUser;
mTvView.setBlockScreenType(getDesiredBlockScreenType());
- if (mPipChannelBeforeShrunkenTvView != null) {
- enablePipView(true, false);
- mPipChannelBeforeShrunkenTvView = null;
- }
}
};
mTvViewUiManager.fadeOutTvView(tuneAction);
// Will automatically fade-in when video becomes available.
} else {
- checkChannelLockNeeded(mTvView);
+ checkChannelLockNeeded(mTvView, null);
mIsCompletingShrunkenTvView = false;
mIsCurrentChannelUnblockedByUser = mWasChannelUnblockedBeforeShrunkenByUser;
mTvView.setBlockScreenType(getDesiredBlockScreenType());
- if (mPipChannelBeforeShrunkenTvView != null) {
- enablePipView(true, false);
- mPipChannelBeforeShrunkenTvView = null;
- }
}
}
@@ -1344,37 +1241,41 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
return mTvViewUiManager.isUnderShrunkenTvView() || mIsCompletingShrunkenTvView;
}
+ /**
+ * Returns {@code true} if the tunable tv view is blocked by resource conflict or by parental
+ * control, otherwise {@code false}.
+ */
+ public boolean isScreenBlockedByResourceConflictOrParentalControl() {
+ return mTvView.getVideoUnavailableReason()
+ == TunableTvView.VIDEO_UNAVAILABLE_REASON_NO_RESOURCE || mTvView.isBlocked();
+ }
+
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
- switch (requestCode) {
- case REQUEST_CODE_START_SETUP_ACTIVITY:
- if (resultCode == RESULT_OK) {
- int count = mChannelDataManager.getChannelCountForInput(mInputIdUnderSetup);
- String text;
- if (count > 0) {
- text = getResources().getQuantityString(R.plurals.msg_channel_added,
- count, count);
- } else {
- text = getString(R.string.msg_no_channel_added);
- }
- Toast.makeText(MainActivity.this, text, Toast.LENGTH_SHORT).show();
- mInputIdUnderSetup = null;
- if (mChannelTuner.getCurrentChannel() == null) {
- mChannelTuner.moveToAdjacentBrowsableChannel(true);
- }
- if (mTunePending) {
- tune();
- }
+ if (requestCode == REQUEST_CODE_START_SETUP_ACTIVITY) {
+ if (resultCode == RESULT_OK) {
+ int count = mChannelDataManager.getChannelCountForInput(mInputIdUnderSetup);
+ String text;
+ if (count > 0) {
+ text = getResources().getQuantityString(R.plurals.msg_channel_added,
+ count, count);
} else {
- mInputIdUnderSetup = null;
+ text = getString(R.string.msg_no_channel_added);
}
- if (!mIsSetupActivityCalledByPopup) {
- mOverlayManager.getSideFragmentManager().showSidePanel(false);
+ Toast.makeText(MainActivity.this, text, Toast.LENGTH_SHORT).show();
+ mInputIdUnderSetup = null;
+ if (mChannelTuner.getCurrentChannel() == null) {
+ mChannelTuner.moveToAdjacentBrowsableChannel(true);
}
- break;
- case REQUEST_CODE_START_SYSTEM_CAPTIONING_SETTINGS:
+ if (mTunePending) {
+ tune(true);
+ }
+ } else {
+ mInputIdUnderSetup = null;
+ }
+ if (!mIsSetupActivityCalledByPopup) {
mOverlayManager.getSideFragmentManager().showSidePanel(false);
- break;
+ }
}
if (data != null) {
String errorMessage = data.getStringExtra(LauncherActivity.ERROR_MESSAGE);
@@ -1418,18 +1319,12 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
// while gamepads support DPAD_CENTER and BACK by fallback.
// Since we don't expect that TIS want to handle gamepad buttons now,
// blacklist gamepad buttons and wait for next fallback keys.
- // TODO) Need to consider other fallback keys (e.g. ESCAPE)
+ // TODO: Need to consider other fallback keys (e.g. ESCAPE)
return super.dispatchKeyEvent(event);
}
return dispatchKeyEventToSession(event) || super.dispatchKeyEvent(event);
}
- @Override
- public void onAudioFocusChange(int focusChange) {
- mAudioFocusStatus = focusChange;
- setVolumeByAudioFocusStatus();
- }
-
/**
* Notifies the key input focus is changed to the TV view.
*/
@@ -1449,18 +1344,6 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
if (!mTvView.isPlaying()) {
mCaptionSettings = new CaptionSettings(this);
}
-
- // Handle the passed key press, if any. Note that only the key codes that are currently
- // handled in the TV app will be handled via Intent.
- // TODO: Consider defining a separate intent filter as passing data of mime type
- // vnd.android.cursor.item/channel isn't really necessary here.
- int keyCode = intent.getIntExtra(Utils.EXTRA_KEY_KEYCODE, KeyEvent.KEYCODE_UNKNOWN);
- if (keyCode != KeyEvent.KEYCODE_UNKNOWN) {
- if (DEBUG) Log.d(TAG, "Got an intent with keycode: " + keyCode);
- KeyEvent event = new KeyEvent(KeyEvent.ACTION_UP, keyCode);
- onKeyUp(keyCode, event);
- return true;
- }
mShouldTuneToTunerChannel = intent.getBooleanExtra(Utils.EXTRA_KEY_FROM_LAUNCHER, false);
mInitChannelUri = null;
@@ -1476,9 +1359,6 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
}
}
- // TODO: remove the checkState once N API is finalized.
- SoftPreconditions.checkState(TvInputManager.ACTION_SETUP_INPUTS.equals(
- "android.media.tv.action.SETUP_INPUTS"));
if (TvInputManager.ACTION_SETUP_INPUTS.equals(intent.getAction())) {
runAfterAttachedToWindow(new Runnable() {
@Override
@@ -1488,17 +1368,12 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
});
} else if (Intent.ACTION_VIEW.equals(intent.getAction())) {
Uri uri = intent.getData();
- try {
- mSource = uri.getQueryParameter(Utils.PARAM_SOURCE);
- } catch (UnsupportedOperationException e) {
- // ignore this exception.
- }
- // When the URI points to the programs (directory, not an individual item), go to the
- // program guide. The intention here is to respond to
- // "content://android.media.tv/program", not "content://android.media.tv/program/XXX".
- // Later, we might want to add handling of individual programs too.
if (Utils.isProgramsUri(uri)) {
- // The given data is a programs URI. Open the Program Guide.
+ // When the URI points to the programs (directory, not an individual item), go to
+ // the program guide. The intention here is to respond to
+ // "content://android.media.tv/program", not
+ // "content://android.media.tv/program/XXX".
+ // Later, we might want to add handling of individual programs too.
mShowProgramGuide = true;
return true;
}
@@ -1541,17 +1416,19 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
}
} else if (mInitChannelUri != null) {
// Handle the URI built by TvContract.buildChannelsUriForInput().
- // TODO: Change hard-coded "input" to TvContract.PARAM_INPUT.
String inputId = mInitChannelUri.getQueryParameter("input");
long channelId = Utils.getLastWatchedChannelIdForInput(this, inputId);
if (channelId == Channel.INVALID_ID) {
String[] projection = { Channels._ID };
+ long time = System.currentTimeMillis();
try (Cursor cursor = getContentResolver().query(uri, projection,
null, null, null)) {
if (cursor != null && cursor.moveToNext()) {
channelId = cursor.getLong(0);
}
}
+ Debug.getTimer(Debug.TAG_START_UP_TIMER).log("MainActivity queries DB for "
+ + "last channel check (" + (System.currentTimeMillis() - time) + "ms)");
}
if (channelId == Channel.INVALID_ID) {
// Couldn't find any channel probably because the input hasn't been set up.
@@ -1567,41 +1444,6 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
return true;
}
- private void setVolumeByAudioFocusStatus() {
- if (mPipSound == TvSettings.PIP_SOUND_MAIN) {
- setVolumeByAudioFocusStatus(mTvView);
- } else { // mPipSound == TvSettings.PIP_SOUND_PIP_WINDOW
- setVolumeByAudioFocusStatus(mPipView);
- }
- }
-
- private void setVolumeByAudioFocusStatus(TunableTvView tvView) {
- SoftPreconditions.checkState(tvView == mTvView || tvView == mPipView);
- if (tvView.isPlaying()) {
- switch (mAudioFocusStatus) {
- case AudioManager.AUDIOFOCUS_GAIN:
- tvView.setStreamVolume(AUDIO_MAX_VOLUME);
- break;
- case AudioManager.AUDIOFOCUS_LOSS:
- case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
- tvView.setStreamVolume(AUDIO_MIN_VOLUME);
- break;
- case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
- tvView.setStreamVolume(AUDIO_DUCKING_VOLUME);
- break;
- }
- }
- if (tvView == mTvView) {
- if (mPipView != null && mPipView.isPlaying()) {
- mPipView.setStreamVolume(AUDIO_MIN_VOLUME);
- }
- } else { // tvView == mPipView
- if (mTvView != null && mTvView.isPlaying()) {
- mTvView.setStreamVolume(AUDIO_MIN_VOLUME);
- }
- }
- }
-
private void stopTv() {
stopTv(null, false);
}
@@ -1617,10 +1459,8 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
if (!keepVisibleBehind) {
requestVisibleBehind(false);
}
- mAudioManager.abandonAudioFocus(this);
- if (mMediaSession.isActive()) {
- mMediaSession.setActive(false);
- }
+ mAudioManagerHelper.abandonAudioFocus();
+ mMediaSessionWrapper.setPlaybackState(false);
}
TvApplication.getSingletons(this).getMainActivityWrapper()
.notifyCurrentChannelChange(this, null);
@@ -1628,99 +1468,11 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
mTunePending = false;
}
- private boolean isPlaying() {
- return mTvView.isPlaying() && mTvView.getCurrentChannel() != null;
- }
-
- private void startPip(final boolean fromUserInteraction) {
- if (mPipChannel == null) {
- Log.w(TAG, "PIP channel id is an invalid id.");
- return;
- }
- if (DEBUG) Log.d(TAG, "startPip() " + mPipChannel);
- mPipView.start(mTvInputManagerHelper);
- boolean success = mPipView.tuneTo(mPipChannel, null, new OnTuneListener() {
- @Override
- public void onUnexpectedStop(Channel channel) {
- Log.w(TAG, "The PIP is Unexpectedly stopped");
- enablePipView(false, false);
- }
-
- @Override
- public void onTuneFailed(Channel channel) {
- Log.w(TAG, "Fail to start the PIP during channel tuning");
- if (fromUserInteraction) {
- Toast.makeText(MainActivity.this, R.string.msg_no_pip_support,
- Toast.LENGTH_SHORT).show();
- enablePipView(false, false);
- }
- }
-
- @Override
- public void onStreamInfoChanged(StreamInfo info) {
- mTvViewUiManager.updatePipView();
- mHandler.removeCallbacks(mRestoreMainViewRunnable);
- restoreMainTvView();
- }
-
- @Override
- public void onChannelRetuned(Uri channel) {
- if (channel == null) {
- return;
- }
- Channel currentChannel =
- mChannelDataManager.getChannel(ContentUris.parseId(channel));
- if (currentChannel == null) {
- Log.e(TAG, "onChannelRetuned is called from PIP input but can't find a channel"
- + " with the URI " + channel);
- return;
- }
- if (isChannelChangeKeyDownReceived()) {
- // Ignore this message if the user is changing the channel.
- return;
- }
- mPipChannel = currentChannel;
- mPipView.setCurrentChannel(mPipChannel);
- }
-
- @Override
- public void onContentBlocked() {
- updateMediaSession();
- }
-
- @Override
- public void onContentAllowed() {
- updateMediaSession();
- }
- });
- if (!success) {
- Log.w(TAG, "Fail to start the PIP");
- return;
- }
- if (fromUserInteraction) {
- checkChannelLockNeeded(mPipView);
- }
- // Explicitly make the PIP view main to make the selected input an HDMI-CEC active source.
- mPipView.setMain();
- scheduleRestoreMainTvView();
- mTvViewUiManager.onPipStart();
- setVolumeByAudioFocusStatus();
- }
-
private void scheduleRestoreMainTvView() {
mHandler.removeCallbacks(mRestoreMainViewRunnable);
mHandler.postDelayed(mRestoreMainViewRunnable, TVVIEW_SET_MAIN_TIMEOUT_MS);
}
- private void stopPip() {
- if (DEBUG) Log.d(TAG, "stopPip");
- if (mPipView.isPlaying()) {
- mPipView.stop();
- mPipSwap = false;
- mTvViewUiManager.onPipStop();
- }
- }
-
/**
* Says {@code text} when accessibility is turned on.
*/
@@ -1735,7 +1487,7 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
}
}
- private void tune() {
+ private void tune(boolean updateChannelBanner) {
if (DEBUG) Log.d(TAG, "tune()");
mTuneDurationTimer.start();
@@ -1748,6 +1500,10 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
}
mTunePending = false;
final Channel channel = mChannelTuner.getCurrentChannel();
+ SoftPreconditions.checkState(channel != null);
+ if (channel == null) {
+ return;
+ }
if (!mChannelTuner.isCurrentChannelPassthrough()) {
if (mTvInputManagerHelper.getTunerTvInputSize() == 0) {
Toast.makeText(this, R.string.msg_no_input, Toast.LENGTH_SHORT).show();
@@ -1763,23 +1519,11 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
}
if (mChannelDataManager.getChannelCount() > 0) {
mOverlayManager.showIntroDialog();
+ } else {
+ startOnboardingActivity();
+ return;
}
}
- if (!TvCommonUtils.isRunningInTest() && mShowNewSourcesFragment
- && setupUtils.hasUnrecognizedInput(mTvInputManagerHelper)) {
- // Show new channel sources fragment.
- runAfterAttachedToWindow(new Runnable() {
- @Override
- public void run() {
- mOverlayManager.runAfterOverlaysAreClosed(new Runnable() {
- @Override
- public void run() {
- mOverlayManager.showNewSourcesFragment();
- }
- });
- }
- });
- }
mShowNewSourcesFragment = false;
if (mChannelTuner.getBrowsableChannelCount() == 0
&& mChannelDataManager.getChannelCount() > 0
@@ -1791,24 +1535,24 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
mOverlayManager.getSideFragmentManager().show(
new CustomizeChannelListFragment());
} else {
- showSettingsFragment();
+ mOverlayManager.showSetupFragment();
}
return;
}
- // TODO: need to refactor the following code to put in startTv.
- if (channel == null) {
- // There is no channel to tune to.
- stopTv("tune()", false);
- if (!mChannelDataManager.isDbLoadFinished()) {
- // Wait until channel data is loaded in order to know the number of channels.
- // tune() will be retried, once the channel data is loaded.
- return;
- }
- if (mOverlayManager.getSideFragmentManager().isActive()) {
- return;
- }
- mOverlayManager.showSetupFragment();
- return;
+ if (!TvCommonUtils.isRunningInTest() && mShowNewSourcesFragment
+ && setupUtils.hasUnrecognizedInput(mTvInputManagerHelper)) {
+ // Show new channel sources fragment.
+ runAfterAttachedToWindow(new Runnable() {
+ @Override
+ public void run() {
+ mOverlayManager.runAfterOverlaysAreClosed(new Runnable() {
+ @Override
+ public void run() {
+ mOverlayManager.showNewSourcesFragment();
+ }
+ });
+ }
+ });
}
setupUtils.onTuned();
if (mTuneParams != null) {
@@ -1825,7 +1569,6 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
if (!isUnderShrunkenTvView()) {
mLastAllowedRatingForCurrentChannel = null;
}
- mHandler.removeMessages(MSG_UPDATE_CHANNEL_BANNER_BY_INFO_UPDATE);
// For every tune, we need to inform the tuned channel or input to a user,
// if Talkback is turned on.
sendAccessibilityText(!mChannelTuner.isCurrentChannelPassthrough() ?
@@ -1852,15 +1595,21 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
TvApplication.getSingletons(this).getMainActivityWrapper()
.notifyCurrentChannelChange(this, channel);
}
- checkChannelLockNeeded(mTvView);
- updateChannelBannerAndShowIfNeeded(UPDATE_CHANNEL_BANNER_REASON_TUNE);
+ // We have to provide channel here instead of using TvView's channel, because TvView's
+ // channel might be null when there's tuner conflict. In that case, TvView will resets
+ // its current channel onConnectionFailed().
+ checkChannelLockNeeded(mTvView, channel);
+ if (updateChannelBanner) {
+ mOverlayManager.updateChannelBannerAndShowIfNeeded(
+ TvOverlayManager.UPDATE_CHANNEL_BANNER_REASON_TUNE);
+ }
if (mActivityResumed) {
// requestVisibleBehind should be called after onResume() is called. But, when
// launcher is over the TV app and the screen is turned off and on, tune() can
// be called during the pause state by mBroadcastReceiver (Intent.ACTION_SCREEN_ON).
requestVisibleBehind(true);
}
- updateMediaSession();
+ mMediaSessionWrapper.update(mTvView.isBlocked(), getCurrentChannel(), getCurrentProgram());
}
// Runs the runnable after the activity is attached to window to show the fragment transition
@@ -1895,136 +1644,11 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
}
}
- private void updateMediaSession() {
- if (getCurrentChannel() == null) {
- mMediaSession.setActive(false);
- return;
- }
-
- // If the channel is blocked, display a lock and a short text on the Now Playing Card
- if (mTvView.isScreenBlocked() || mTvView.getBlockedContentRating() != null) {
- setMediaSessionPlaybackState(false);
-
- Bitmap art = BitmapFactory.decodeResource(
- getResources(), R.drawable.ic_message_lock_preview);
- updateMediaMetadata(
- getResources().getString(R.string.channel_banner_locked_channel_title), art);
- mMediaSession.setActive(true);
- return;
- }
-
- final Program currentProgram = getCurrentProgram();
- String cardTitleText = null;
- String posterArtUri = null;
- if (currentProgram != null) {
- cardTitleText = currentProgram.getTitle();
- posterArtUri = currentProgram.getPosterArtUri();
- }
- if (TextUtils.isEmpty(cardTitleText)) {
- cardTitleText = getCurrentChannelName();
- }
- updateMediaMetadata(cardTitleText, null);
- setMediaSessionPlaybackState(true);
-
- if (posterArtUri == null) {
- posterArtUri = TvContract.buildChannelLogoUri(getCurrentChannelId()).toString();
- }
- updatePosterArt(getCurrentChannel(), currentProgram, cardTitleText, null, posterArtUri);
- mMediaSession.setActive(true);
- }
-
- private void updatePosterArt(Channel currentChannel, Program currentProgram,
- String cardTitleText, @Nullable Bitmap posterArt, @Nullable String posterArtUri) {
- if (posterArt != null) {
- updateMediaMetadata(cardTitleText, posterArt);
- } else if (posterArtUri != null) {
- ImageLoader.loadBitmap(this, posterArtUri, mNowPlayingCardWidth, mNowPlayingCardHeight,
- new ProgramPosterArtCallback(this, currentChannel,
- currentProgram, cardTitleText));
- } else {
- updateMediaMetadata(cardTitleText, R.drawable.default_now_card);
- }
- }
-
- private static class ProgramPosterArtCallback extends
- ImageLoader.ImageLoaderCallback<MainActivity> {
- private final Channel mChannel;
- private final Program mProgram;
- private final String mCardTitleText;
-
- public ProgramPosterArtCallback(MainActivity mainActivity, Channel channel, Program program,
- String cardTitleText) {
- super(mainActivity);
- mChannel = channel;
- mProgram = program;
- mCardTitleText = cardTitleText;
- }
-
- @Override
- public void onBitmapLoaded(MainActivity mainActivity, @Nullable Bitmap posterArt) {
- if (mainActivity.isNowPlayingProgram(mChannel, mProgram)) {
- mainActivity.updatePosterArt(mChannel, mProgram, mCardTitleText, posterArt, null);
- }
- }
- }
-
- private boolean isNowPlayingProgram(Channel channel, Program program) {
+ boolean isNowPlayingProgram(Channel channel, Program program) {
return program == null ? (channel != null && getCurrentProgram() == null
&& channel.equals(getCurrentChannel())) : program.equals(getCurrentProgram());
}
- private void updateMediaMetadata(final String title, final Bitmap posterArt) {
- new AsyncTask<Void, Void, Void> () {
- @Override
- protected Void doInBackground(Void... arg0) {
- MediaMetadata.Builder builder = new MediaMetadata.Builder();
- builder.putString(MediaMetadata.METADATA_KEY_TITLE, title);
- if (posterArt != null) {
- builder.putBitmap(MediaMetadata.METADATA_KEY_ART, posterArt);
- }
- mMediaSession.setMetadata(builder.build());
- return null;
- }
- }.execute();
- }
-
- private void updateMediaMetadata(final String title, final int imageResId) {
- new AsyncTask<Void, Void, Void> () {
- @Override
- protected Void doInBackground(Void... arg0) {
- MediaMetadata.Builder builder = new MediaMetadata.Builder();
- builder.putString(MediaMetadata.METADATA_KEY_TITLE, title);
- Bitmap posterArt = BitmapFactory.decodeResource(getResources(), imageResId);
- if (posterArt != null) {
- builder.putBitmap(MediaMetadata.METADATA_KEY_ART, posterArt);
- }
- mMediaSession.setMetadata(builder.build());
- return null;
- }
- }.execute();
- }
-
- private String getCurrentChannelName() {
- Channel channel = getCurrentChannel();
- if (channel == null) {
- return "";
- }
- if (channel.isPassthrough()) {
- TvInputInfo input = getTvInputManagerHelper().getTvInputInfo(channel.getInputId());
- return Utils.loadLabel(this, input);
- } else {
- return channel.getDisplayName();
- }
- }
-
- private void setMediaSessionPlaybackState(boolean isPlaying) {
- PlaybackState.Builder builder = new PlaybackState.Builder();
- builder.setState(isPlaying ? PlaybackState.STATE_PLAYING : PlaybackState.STATE_STOPPED,
- PlaybackState.PLAYBACK_POSITION_UNKNOWN,
- isPlaying ? MEDIA_SESSION_PLAYING_SPEED : MEDIA_SESSION_STOPPED_SPEED);
- mMediaSession.setPlaybackState(builder.build());
- }
-
private void addToRecentChannels(long channelId) {
if (!mRecentChannels.remove(channelId)) {
if (mRecentChannels.size() >= MAX_RECENT_CHANNELS) {
@@ -2042,106 +1666,35 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
return mRecentChannels;
}
- private void checkChannelLockNeeded(TunableTvView tvView) {
- Channel channel = tvView.getCurrentChannel();
- if (tvView.isPlaying() && channel != null) {
+ private void checkChannelLockNeeded(TunableTvView tvView, Channel currentChannel) {
+ if (currentChannel == null) {
+ currentChannel = tvView.getCurrentChannel();
+ }
+ if (tvView.isPlaying() && currentChannel != null) {
if (getParentalControlSettings().isParentalControlsEnabled()
- && channel.isLocked()
+ && currentChannel.isLocked()
&& !mShowLockedChannelsTemporarily
&& !(isUnderShrunkenTvView()
- && channel.equals(mChannelBeforeShrunkenTvView)
+ && currentChannel.equals(mChannelBeforeShrunkenTvView)
&& mWasChannelUnblockedBeforeShrunkenByUser)) {
- if (DEBUG) Log.d(TAG, "Channel " + channel.getId() + " is locked");
- blockScreen(tvView);
+ if (DEBUG) Log.d(TAG, "Channel " + currentChannel.getId() + " is locked");
+ blockOrUnblockScreen(tvView, true);
} else {
- unblockScreen(tvView);
+ blockOrUnblockScreen(tvView, false);
}
}
}
- private void blockScreen(TunableTvView tvView) {
- tvView.blockScreen();
+ private void blockOrUnblockScreen(TunableTvView tvView, boolean blockOrUnblock) {
+ tvView.blockOrUnblockScreen(blockOrUnblock);
if (tvView == mTvView) {
- updateChannelBannerAndShowIfNeeded(UPDATE_CHANNEL_BANNER_REASON_LOCK_OR_UNLOCK);
- updateMediaSession();
- }
- }
-
- private void unblockScreen(TunableTvView tvView) {
- tvView.unblockScreen();
- if (tvView == mTvView) {
- updateChannelBannerAndShowIfNeeded(UPDATE_CHANNEL_BANNER_REASON_LOCK_OR_UNLOCK);
- updateMediaSession();
+ mOverlayManager.updateChannelBannerAndShowIfNeeded(
+ TvOverlayManager.UPDATE_CHANNEL_BANNER_REASON_LOCK_OR_UNLOCK);
+ mMediaSessionWrapper.update(blockOrUnblock, getCurrentChannel(), getCurrentProgram());
}
}
/**
- * Shows the channel banner if it was hidden from the side fragment.
- *
- * <p>When the side fragment is visible, showing the channel banner should be put off until the
- * side fragment is closed even though the channel changes.
- */
- public void showChannelBannerIfHiddenBySideFragment() {
- if (mChannelBannerHiddenBySideFragment) {
- updateChannelBannerAndShowIfNeeded(UPDATE_CHANNEL_BANNER_REASON_FORCE_SHOW);
- }
- }
-
- private void updateChannelBannerAndShowIfNeeded(@ChannelBannerUpdateReason int reason) {
- if(DEBUG) Log.d(TAG, "updateChannelBannerAndShowIfNeeded(reason=" + reason + ")");
- if (!mChannelTuner.isCurrentChannelPassthrough()) {
- int lockType = ChannelBannerView.LOCK_NONE;
- if (mTvView.isScreenBlocked()) {
- lockType = ChannelBannerView.LOCK_CHANNEL_INFO;
- } else if (mTvView.getBlockedContentRating() != null
- || (getParentalControlSettings().isParentalControlsEnabled()
- && !mTvView.isVideoAvailable())) {
- // If the parental control is enabled, do not show the program detail until the
- // video becomes available.
- lockType = ChannelBannerView.LOCK_PROGRAM_DETAIL;
- }
- if (lockType == ChannelBannerView.LOCK_NONE) {
- if (reason == UPDATE_CHANNEL_BANNER_REASON_TUNE_FAST) {
- // Do not show detailed program information while fast-tuning.
- lockType = ChannelBannerView.LOCK_PROGRAM_DETAIL;
- } else if (reason == UPDATE_CHANNEL_BANNER_REASON_TUNE
- && getParentalControlSettings().isParentalControlsEnabled()) {
- // If parental control is turned on,
- // assumes that program is locked by default and waits for onContentAllowed.
- lockType = ChannelBannerView.LOCK_PROGRAM_DETAIL;
- }
- }
- // If lock type is not changed, we don't need to update channel banner by parental
- // control.
- if (!mChannelBannerView.setLockType(lockType)
- && reason == UPDATE_CHANNEL_BANNER_REASON_LOCK_OR_UNLOCK) {
- return;
- }
-
- mChannelBannerView.updateViews(mTvView);
- }
- boolean needToShowBanner = (reason == UPDATE_CHANNEL_BANNER_REASON_FORCE_SHOW
- || reason == UPDATE_CHANNEL_BANNER_REASON_TUNE
- || reason == UPDATE_CHANNEL_BANNER_REASON_TUNE_FAST);
- boolean noOverlayUiWhenResume =
- mInputToSetUp == null && !mShowProgramGuide && !mShowSelectInputView;
- if (needToShowBanner && noOverlayUiWhenResume
- && mOverlayManager.getCurrentDialog() == null
- && !mOverlayManager.isSetupFragmentActive()
- && !mOverlayManager.isNewSourcesFragmentActive()) {
- if (mChannelTuner.getCurrentChannel() == null) {
- mChannelBannerHiddenBySideFragment = false;
- } else if (mOverlayManager.getSideFragmentManager().isActive()) {
- mChannelBannerHiddenBySideFragment = true;
- } else {
- mChannelBannerHiddenBySideFragment = false;
- mOverlayManager.showBanner();
- }
- }
- updateAvailabilityToast();
- }
-
- /**
* Hide the overlays when tuning to a channel from the menu (e.g. Channels).
*/
public void hideOverlaysForTune() {
@@ -2197,7 +1750,7 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
if (bestTrack != null) {
String selectedTrack = getSelectedTrack(TvTrackInfo.TYPE_AUDIO);
if (!bestTrack.getId().equals(selectedTrack)) {
- selectTrack(TvTrackInfo.TYPE_AUDIO, bestTrack);
+ selectTrack(TvTrackInfo.TYPE_AUDIO, bestTrack, UNDEFINED_TRACK_INDEX);
} else {
mTvOptionsManager.onMultiAudioChanged(
Utils.getMultiAudioString(this, bestTrack, false));
@@ -2210,7 +1763,7 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
private void applyClosedCaption() {
List<TvTrackInfo> tracks = getTracks(TvTrackInfo.TYPE_SUBTITLE);
if (tracks == null) {
- mTvOptionsManager.onClosedCaptionsChanged(null);
+ mTvOptionsManager.onClosedCaptionsChanged(null, UNDEFINED_TRACK_INDEX);
return;
}
@@ -2219,17 +1772,19 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
String selectedTrackId = getSelectedTrack(TvTrackInfo.TYPE_SUBTITLE);
TvTrackInfo alternativeTrack = null;
+ int alternativeTrackIndex = UNDEFINED_TRACK_INDEX;
if (enabled) {
String language = mCaptionSettings.getLanguage();
String trackId = mCaptionSettings.getTrackId();
- for (TvTrackInfo track : tracks) {
+ for (int i = 0; i < tracks.size(); i++) {
+ TvTrackInfo track = tracks.get(i);
if (Utils.isEqualLanguage(track.getLanguage(), language)) {
if (track.getId().equals(trackId)) {
if (!track.getId().equals(selectedTrackId)) {
- selectTrack(TvTrackInfo.TYPE_SUBTITLE, track);
+ selectTrack(TvTrackInfo.TYPE_SUBTITLE, track, i);
} else {
// Already selected. Update the option string only.
- mTvOptionsManager.onClosedCaptionsChanged(track);
+ mTvOptionsManager.onClosedCaptionsChanged(track, i);
}
if (DEBUG) {
Log.d(TAG, "Subtitle Track Selected {id=" + track.getId()
@@ -2238,14 +1793,16 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
return;
} else if (alternativeTrack == null) {
alternativeTrack = track;
+ alternativeTrackIndex = i;
}
}
}
if (alternativeTrack != null) {
if (!alternativeTrack.getId().equals(selectedTrackId)) {
- selectTrack(TvTrackInfo.TYPE_SUBTITLE, alternativeTrack);
+ selectTrack(TvTrackInfo.TYPE_SUBTITLE, alternativeTrack, alternativeTrackIndex);
} else {
- mTvOptionsManager.onClosedCaptionsChanged(alternativeTrack);
+ mTvOptionsManager
+ .onClosedCaptionsChanged(alternativeTrack, alternativeTrackIndex);
}
if (DEBUG) {
Log.d(TAG, "Subtitle Track Selected {id=" + alternativeTrack.getId()
@@ -2255,29 +1812,11 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
}
}
if (selectedTrackId != null) {
- selectTrack(TvTrackInfo.TYPE_SUBTITLE, null);
+ selectTrack(TvTrackInfo.TYPE_SUBTITLE, null, UNDEFINED_TRACK_INDEX);
if (DEBUG) Log.d(TAG, "Subtitle Track Unselected");
return;
}
- mTvOptionsManager.onClosedCaptionsChanged(null);
- }
-
- /**
- * Pops up the KeypadChannelSwitchView with the given key input event.
- *
- * @param keyCode A key code of the key event.
- */
- public void showKeypadChannelSwitchView(int keyCode) {
- if (mChannelTuner.areAllChannelsLoaded()) {
- mOverlayManager.showKeypadChannelSwitch();
- mKeypadChannelSwitchView.onNumberKeyUp(keyCode - KeyEvent.KEYCODE_0);
- }
- }
-
- public void showSearchActivity() {
- // HACK: Once we moved the window layer to TYPE_APPLICATION_SUB_PANEL,
- // the voice button doesn't work. So we directly call the voice action.
- SearchManagerHelper.getInstance(this).launchAssistAction();
+ mTvOptionsManager.onClosedCaptionsChanged(null, UNDEFINED_TRACK_INDEX);
}
public void showProgramGuideSearchFragment() {
@@ -2295,13 +1834,12 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
@Override
protected void onDestroy() {
if (DEBUG) Log.d(TAG, "onDestroy()");
- SideFragment.releasePreloadedRecycledViews();
+ Debug.getTimer(Debug.TAG_START_UP_TIMER).reset();
+ SideFragment.releaseRecycledViewPool();
+ ViewCache.getInstance().clear();
if (mTvView != null) {
mTvView.release();
}
- if (mPipView != null) {
- mPipView.release();
- }
if (mChannelTuner != null) {
mChannelTuner.removeListener(mChannelTunerListener);
mChannelTuner.stop();
@@ -2314,21 +1852,15 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
mProgramDataManager.setPrefetchEnabled(false);
}
}
- if (mPipInputManager != null) {
- mPipInputManager.stop();
- }
if (mOverlayManager != null) {
mOverlayManager.release();
}
- if (mKeypadChannelSwitchView != null) {
- mKeypadChannelSwitchView.setChannels(null);
- }
mMemoryManageables.clear();
- if (mMediaSession != null) {
- mMediaSession.release();
+ if (mMediaSessionWrapper != null) {
+ mMediaSessionWrapper.release();
}
- if (mAudioCapabilitiesReceiver != null) {
- mAudioCapabilitiesReceiver.unregister();
+ if (mAudioManagerHelper != null) {
+ mAudioManagerHelper.release();
}
mHandler.removeCallbacksAndMessages(null);
application.getMainActivityWrapper().onMainActivityDestroyed(this);
@@ -2340,8 +1872,11 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
mChannelStatusRecurringRunner.stop();
mChannelStatusRecurringRunner = null;
}
- if (mTvInputManagerHelper != null && Features.TUNER.isEnabled(this)) {
- mTvInputManagerHelper.removeCallback(mTvInputCallback);
+ if (mTvInputManagerHelper != null) {
+ mTvInputManagerHelper.clearTvInputLabels();
+ if (Features.TUNER.isEnabled(this)) {
+ mTvInputManagerHelper.removeCallback(mTvInputCallback);
+ }
}
super.onDestroy();
}
@@ -2410,7 +1945,6 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
* G debug: refresh cloud epg
* I KEYCODE_TV_INPUT
* O debug: show display mode option
- * P debug: togglePipView
* S KEYCODE_CAPTIONS: select subtitle
* W debug: toggle screen size
* V KEYCODE_MEDIA_RECORD debug: record the current channel for 30 sec
@@ -2422,8 +1956,9 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
finishChannelChangeIfNeeded();
if (event.getKeyCode() == KeyEvent.KEYCODE_SEARCH) {
- showSearchActivity();
- return true;
+ // Prevent MainActivity from being closed by onVisibleBehindCanceled()
+ mOtherActivityLaunched = true;
+ return false;
}
switch (mOverlayManager.onKeyUp(keyCode, event)) {
case KEY_EVENT_HANDLER_RESULT_DISPATCH_TO_OVERLAY:
@@ -2467,12 +2002,12 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
}
} else {
if (KeypadChannelSwitchView.isChannelNumberKey(keyCode)) {
- showKeypadChannelSwitchView(keyCode);
+ mOverlayManager.showKeypadChannelSwitch(keyCode);
return true;
}
switch (keyCode) {
case KeyEvent.KEYCODE_DPAD_RIGHT:
- if (!mTvView.isVideoAvailable()
+ if (!mTvView.isVideoOrAudioAvailable()
&& mTvView.getVideoUnavailableReason()
== TunableTvView.VIDEO_UNAVAILABLE_REASON_NO_RESOURCE) {
DvrUiHelper.startSchedulesActivityForTuneConflict(this,
@@ -2480,35 +2015,16 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
return true;
}
if (!PermissionUtils.hasModifyParentalControls(this)) {
- // TODO: support this feature for non-system LC app. b/23939816
return true;
}
PinDialogFragment dialog = null;
if (mTvView.isScreenBlocked()) {
- dialog = new PinDialogFragment(
- PinDialogFragment.PIN_DIALOG_TYPE_UNLOCK_CHANNEL,
- new PinDialogFragment.ResultListener() {
- @Override
- public void done(boolean success) {
- if (success) {
- unblockScreen(mTvView);
- mIsCurrentChannelUnblockedByUser = true;
- }
- }
- });
- } else if (mTvView.getBlockedContentRating() != null) {
- final TvContentRating rating = mTvView.getBlockedContentRating();
- dialog = new PinDialogFragment(
- PinDialogFragment.PIN_DIALOG_TYPE_UNLOCK_PROGRAM,
- new PinDialogFragment.ResultListener() {
- @Override
- public void done(boolean success) {
- if (success) {
- mLastAllowedRatingForCurrentChannel = rating;
- mTvView.unblockContent(rating);
- }
- }
- });
+ dialog = PinDialogFragment
+ .create(PinDialogFragment.PIN_DIALOG_TYPE_UNLOCK_CHANNEL);
+ } else if (mTvView.isContentBlocked()) {
+ dialog = PinDialogFragment
+ .create(PinDialogFragment.PIN_DIALOG_TYPE_UNLOCK_PROGRAM,
+ mTvView.getBlockedContentRating().flattenToString());
}
if (dialog != null) {
mOverlayManager.showDialogFragment(PinDialogFragment.DIALOG_TAG, dialog,
@@ -2531,7 +2047,8 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
return true;
}
if (keyCode != KeyEvent.KEYCODE_MENU) {
- updateChannelBannerAndShowIfNeeded(UPDATE_CHANNEL_BANNER_REASON_FORCE_SHOW);
+ mOverlayManager.updateChannelBannerAndShowIfNeeded(
+ TvOverlayManager.UPDATE_CHANNEL_BANNER_REASON_FORCE_SHOW);
}
if (keyCode != KeyEvent.KEYCODE_E) {
mOverlayManager.showMenu(Menu.REASON_NONE);
@@ -2547,6 +2064,7 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
if (!SystemProperties.USE_DEBUG_KEYS.getValue()) {
break;
}
+ // Pass through.
case KeyEvent.KEYCODE_CAPTIONS: {
mOverlayManager.getSideFragmentManager().show(new ClosedCaptionFragment());
return true;
@@ -2555,14 +2073,11 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
if (!SystemProperties.USE_DEBUG_KEYS.getValue()) {
break;
}
+ // Pass through.
case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: {
mOverlayManager.getSideFragmentManager().show(new MultiAudioFragment());
return true;
}
- case KeyEvent.KEYCODE_GUIDE: {
- mOverlayManager.showProgramGuide();
- return true;
- }
case KeyEvent.KEYCODE_INFO: {
mOverlayManager.showBanner();
return true;
@@ -2578,22 +2093,17 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
Toast.makeText(this, R.string.dvr_msg_cannot_record_program,
Toast.LENGTH_SHORT).show();
} else {
- if (!DvrUiHelper.checkStorageStatusAndShowErrorMessage(this,
- currentChannel.getInputId())) {
- return true;
- }
Program program = mProgramDataManager
.getCurrentProgram(currentChannel.getId());
- if (program == null) {
- DvrUiHelper
- .showChannelRecordDurationOptions(this, currentChannel);
- } else if (DvrUiHelper.handleCreateSchedule(this, program)) {
- String msg = getString(
- R.string.dvr_msg_current_program_scheduled,
- program.getTitle(), Utils.toTimeString(
- program.getEndTimeUtcMillis(), false));
- Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
- }
+ DvrUiHelper.checkStorageStatusAndShowErrorMessage(this,
+ currentChannel.getInputId(), new Runnable() {
+ @Override
+ public void run() {
+ DvrUiHelper.requestRecordingCurrentProgram(
+ MainActivity.this,
+ currentChannel, program, false);
+ }
+ });
}
} else {
DvrUiHelper.showStopRecordingDialog(this, currentChannel.getId(),
@@ -2624,7 +2134,7 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
}
if (SystemProperties.USE_DEBUG_KEYS.getValue() || BuildConfig.ENG) {
switch (keyCode) {
- case KeyEvent.KEYCODE_W: {
+ case KeyEvent.KEYCODE_W:
mDebugNonFullSizeScreen = !mDebugNonFullSizeScreen;
if (mDebugNonFullSizeScreen) {
FrameLayout.LayoutParams params =
@@ -2632,30 +2142,23 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
params.width = 960;
params.height = 540;
params.gravity = Gravity.START;
- mTvView.setLayoutParams(params);
+ mTvView.setTvViewLayoutParams(params);
} else {
FrameLayout.LayoutParams params =
(FrameLayout.LayoutParams) mTvView.getLayoutParams();
params.width = ViewGroup.LayoutParams.MATCH_PARENT;
params.height = ViewGroup.LayoutParams.MATCH_PARENT;
params.gravity = Gravity.CENTER;
- mTvView.setLayoutParams(params);
+ mTvView.setTvViewLayoutParams(params);
}
return true;
- }
- case KeyEvent.KEYCODE_P: {
- togglePipView();
- return true;
- }
case KeyEvent.KEYCODE_CTRL_LEFT:
- case KeyEvent.KEYCODE_CTRL_RIGHT: {
+ case KeyEvent.KEYCODE_CTRL_RIGHT:
mUseKeycodeBlacklist = !mUseKeycodeBlacklist;
return true;
- }
- case KeyEvent.KEYCODE_O: {
+ case KeyEvent.KEYCODE_O:
mOverlayManager.getSideFragmentManager().show(new DisplayModeFragment());
return true;
- }
case KeyEvent.KEYCODE_D:
mOverlayManager.getSideFragmentManager().show(new DeveloperOptionFragment());
return true;
@@ -2681,22 +2184,6 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
}
@Override
- public void onBackPressed() {
- // The activity should be returned to the caller of this activity
- // when the mSource is not null.
- if (!mOverlayManager.getSideFragmentManager().isActive() && isPlaying()
- && mSource == null) {
- // If back key would exit TV app,
- // show McLauncher instead so we can get benefit of McLauncher's shyMode.
- Intent startMain = new Intent(Intent.ACTION_MAIN);
- startMain.addCategory(Intent.CATEGORY_HOME);
- startActivity(startMain);
- } else {
- super.onBackPressed();
- }
- }
-
- @Override
public void onUserInteraction() {
super.onUserInteraction();
if (mOverlayManager != null) {
@@ -2725,66 +2212,10 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
}
}
- public void togglePipView() {
- enablePipView(!mPipEnabled, true);
- mOverlayManager.getMenu().update();
- }
-
- public boolean isPipEnabled() {
- return mPipEnabled;
- }
-
- public void tuneToChannelForPip(Channel channel) {
- if (!mPipEnabled) {
- throw new IllegalStateException("tuneToChannelForPip is called when PIP is off");
- }
- if (mPipChannel.equals(channel)) {
- return;
- }
- mPipChannel = channel;
- startPip(true);
- }
-
- private void enablePipView(boolean enable, boolean fromUserInteraction) {
- if (enable == mPipEnabled) {
- return;
- }
- if (enable) {
- List<PipInput> pipAvailableInputs = mPipInputManager.getPipInputList(true);
- if (pipAvailableInputs.isEmpty()) {
- Toast.makeText(this, R.string.msg_no_available_input_by_pip, Toast.LENGTH_SHORT)
- .show();
- return;
- }
- // TODO: choose the last pip input.
- Channel pipChannel = pipAvailableInputs.get(0).getChannel();
- if (pipChannel != null) {
- mPipEnabled = true;
- mPipChannel = pipChannel;
- startPip(fromUserInteraction);
- mTvViewUiManager.restorePipSize();
- mTvViewUiManager.restorePipLayout();
- mTvOptionsManager.onPipChanged(mPipEnabled);
- } else {
- Toast.makeText(this, R.string.msg_no_available_input_by_pip, Toast.LENGTH_SHORT)
- .show();
- }
- } else {
- mPipEnabled = false;
- mPipChannel = null;
- // Recover the stream volume of the main TV view, if needed.
- if (mPipSound == TvSettings.PIP_SOUND_PIP_WINDOW) {
- setVolumeByAudioFocusStatus(mTvView);
- mPipSound = TvSettings.PIP_SOUND_MAIN;
- mTvOptionsManager.onPipSoundChanged(mPipSound);
- }
- stopPip();
- mTvViewUiManager.restoreDisplayMode(false);
- mTvOptionsManager.onPipChanged(mPipEnabled);
- }
- }
-
- private boolean isChannelChangeKeyDownReceived() {
+ /**
+ * Returns {@code true} if one of the channel changing keys are pressed and not released yet.
+ */
+ public boolean isChannelChangeKeyDownReceived() {
return mHandler.hasMessages(MSG_CHANNEL_UP_PRESSED)
|| mHandler.hasMessages(MSG_CHANNEL_DOWN_PRESSED);
}
@@ -2811,10 +2242,6 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
if (SystemProperties.LOG_KEYEVENT.getValue()) {
Log.d(TAG, "dispatchKeyEventToSession(" + event + ")");
}
- if (mPipEnabled && mChannelTuner.isCurrentChannelPassthrough()) {
- // If PIP is enabled, key events will be used by UI.
- return false;
- }
boolean handled = false;
if (mTvView != null) {
handled = mTvView.dispatchKeyEvent(event);
@@ -2832,21 +2259,15 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
}
private boolean isKeyEventBlocked() {
- // If the current channel is passthrough channel without a PIP view,
- // we always don't handle the key events in TV activity. Instead, the key event will
- // be handled by the passthrough TV input.
- return mChannelTuner.isCurrentChannelPassthrough() && !mPipEnabled;
+ // 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();
}
private void tuneToLastWatchedChannelForTunerInput() {
if (!mChannelTuner.isCurrentChannelPassthrough()) {
return;
}
- if (mPipEnabled) {
- if (!mPipChannel.isPassthrough()) {
- enablePipView(false, true);
- }
- }
stopTv();
startTv(null);
}
@@ -2857,16 +2278,17 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
mTvView.reset();
}
} else {
- if (mPipEnabled && mPipInputManager.areInSamePipInput(channel, mPipChannel)) {
- enablePipView(false, true);
- }
if (!mTvView.isPlaying()) {
startTv(channel.getUri());
} else if (channel.equals(mTvView.getCurrentChannel())) {
- updateChannelBannerAndShowIfNeeded(UPDATE_CHANNEL_BANNER_REASON_TUNE);
+ mOverlayManager.updateChannelBannerAndShowIfNeeded(
+ TvOverlayManager.UPDATE_CHANNEL_BANNER_REASON_TUNE);
+ } else if (channel == mChannelTuner.getCurrentChannel()) {
+ // Channel banner is already updated in moveToAdjacentChannel
+ tune(false);
} else if (mChannelTuner.moveToChannel(channel)) {
// Channel banner would be updated inside of tune.
- tune();
+ tune(true);
} else {
showSettingsFragment();
}
@@ -2883,107 +2305,25 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
*/
private void moveToAdjacentChannel(boolean channelUp, boolean fastTuning) {
if (mChannelTuner.moveToAdjacentBrowsableChannel(channelUp)) {
- updateChannelBannerAndShowIfNeeded(fastTuning ? UPDATE_CHANNEL_BANNER_REASON_TUNE_FAST
- : UPDATE_CHANNEL_BANNER_REASON_TUNE);
- }
- }
-
- public Channel getPipChannel() {
- return mPipChannel;
- }
-
- /**
- * Swap the main and the sub screens while in the PIP mode.
- */
- public void swapPip() {
- if (!mPipEnabled || mTvView == null || mPipView == null) {
- Log.e(TAG, "swapPip() - not in PIP");
- mPipSwap = false;
- return;
- }
-
- Channel channel = mTvView.getCurrentChannel();
- boolean tvViewBlocked = mTvView.isScreenBlocked();
- boolean pipViewBlocked = mPipView.isScreenBlocked();
- if (channel == null || !mTvView.isPlaying()) {
- // If the TV view is not currently playing or its current channel is null, swapping here
- // basically means disabling the PIP mode and getting back to the full screen since
- // there's no point of keeping a blank PIP screen at the bottom which is not tune-able.
- enablePipView(false, true);
- mOverlayManager.hideOverlays(TvOverlayManager.FLAG_HIDE_OVERLAYS_DEFAULT);
- mPipSwap = false;
- return;
- }
-
- // Reset the TV view and tune the PIP view to the previous channel of the TV view.
- mTvView.reset();
- mPipView.reset();
- Channel oldPipChannel = mPipChannel;
- tuneToChannelForPip(channel);
- if (tvViewBlocked) {
- mPipView.blockScreen();
- } else {
- mPipView.unblockScreen();
+ mOverlayManager.updateChannelBannerAndShowIfNeeded(fastTuning ?
+ TvOverlayManager.UPDATE_CHANNEL_BANNER_REASON_TUNE_FAST
+ : TvOverlayManager.UPDATE_CHANNEL_BANNER_REASON_TUNE);
}
-
- if (oldPipChannel != null) {
- // Tune the TV view to the previous PIP channel.
- tuneToChannel(oldPipChannel);
- }
- if (pipViewBlocked) {
- mTvView.blockScreen();
- } else {
- mTvView.unblockScreen();
- }
- if (mPipSound == TvSettings.PIP_SOUND_MAIN) {
- setVolumeByAudioFocusStatus(mTvView);
- } else { // mPipSound == TvSettings.PIP_SOUND_PIP_WINDOW
- setVolumeByAudioFocusStatus(mPipView);
- }
- mPipSwap = !mPipSwap;
- mTvOptionsManager.onPipSwapChanged(mPipSwap);
- }
-
- /**
- * Toggle where the sound is coming from when the user is watching the PIP.
- */
- public void togglePipSoundMode() {
- if (!mPipEnabled || mTvView == null || mPipView == null) {
- Log.e(TAG, "togglePipSoundMode() - not in PIP");
- return;
- }
- if (mPipSound == TvSettings.PIP_SOUND_MAIN) {
- setVolumeByAudioFocusStatus(mPipView);
- mPipSound = TvSettings.PIP_SOUND_PIP_WINDOW;
- } else { // mPipSound == TvSettings.PIP_SOUND_PIP_WINDOW
- setVolumeByAudioFocusStatus(mTvView);
- mPipSound = TvSettings.PIP_SOUND_MAIN;
- }
- restoreMainTvView();
- mTvOptionsManager.onPipSoundChanged(mPipSound);
}
/**
* Set the main TV view which holds HDMI-CEC active source based on the sound mode
*/
private void restoreMainTvView() {
- if (mPipSound == TvSettings.PIP_SOUND_MAIN) {
- mTvView.setMain();
- } else { // mPipSound == TvSettings.PIP_SOUND_PIP_WINDOW
- mPipView.setMain();
- }
+ mTvView.setMain();
}
@Override
public void onVisibleBehindCanceled() {
stopTv("onVisibleBehindCanceled()", false);
mTracker.sendScreenView("");
- mAudioFocusStatus = AudioManager.AUDIOFOCUS_LOSS;
- mAudioManager.abandonAudioFocus(this);
- if (mMediaSession.isActive()) {
- mMediaSession.setActive(false);
- }
- stopPip();
+ mAudioManagerHelper.abandonAudioFocus();
+ mMediaSessionWrapper.setPlaybackState(false);
mVisibleBehind = false;
if (!mOtherActivityLaunched && Build.VERSION.SDK_INT == Build.VERSION_CODES.M) {
// Workaround: in M, onStop is not called, even though it should be called after
@@ -3012,13 +2352,13 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
return mTvView.getSelectedTrack(type);
}
- private void selectTrack(int type, TvTrackInfo track) {
+ private void selectTrack(int type, TvTrackInfo track, int trackIndex) {
mTvView.selectTrack(type, track == null ? null : track.getId());
if (type == TvTrackInfo.TYPE_AUDIO) {
mTvOptionsManager.onMultiAudioChanged(track == null ? null :
Utils.getMultiAudioString(this, track, false));
} else if (type == TvTrackInfo.TYPE_SUBTITLE) {
- mTvOptionsManager.onClosedCaptionsChanged(track);
+ mTvOptionsManager.onClosedCaptionsChanged(track, trackIndex);
}
}
@@ -3073,16 +2413,12 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
}
private void updateAvailabilityToast() {
- updateAvailabilityToast(mTvView);
- }
-
- private void updateAvailabilityToast(StreamInfo info) {
- if (info.isVideoAvailable()) {
+ if (mTvView.isVideoAvailable()
+ || mTvView.getCurrentChannel() != mChannelTuner.getCurrentChannel()) {
return;
}
- int stringId;
- switch (info.getVideoUnavailableReason()) {
+ switch (mTvView.getVideoUnavailableReason()) {
case TunableTvView.VIDEO_UNAVAILABLE_REASON_NOT_TUNED:
case TunableTvView.VIDEO_UNAVAILABLE_REASON_NO_RESOURCE:
case TvInputManager.VIDEO_UNAVAILABLE_REASON_TUNING:
@@ -3092,13 +2428,22 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
return;
case TvInputManager.VIDEO_UNAVAILABLE_REASON_UNKNOWN:
default:
- stringId = R.string.msg_channel_unavailable_unknown;
+ Toast.makeText(this, R.string.msg_channel_unavailable_unknown,
+ Toast.LENGTH_SHORT).show();
break;
}
+ }
- Toast.makeText(this, stringId, Toast.LENGTH_SHORT).show();
+ /**
+ * Returns {@code true} if some overlay UI will be shown when the activity is resumed.
+ */
+ public boolean willShowOverlayUiWhenResume() {
+ return mInputToSetUp != null || mShowProgramGuide || mShowSelectInputView;
}
+ /**
+ * Returns the current parental control settings.
+ */
public ParentalControlSettings getParentalControlSettings() {
return mTvInputManagerHelper.getParentalControlSettings();
}
@@ -3110,6 +2455,9 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
return mTvInputManagerHelper.getContentRatingsManager();
}
+ /**
+ * Returns the current captioning settings.
+ */
public CaptionSettings getCaptionSettings() {
return mCaptionSettings;
}
@@ -3163,6 +2511,7 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
if (mActivityStarted) {
initAnimations();
initSideFragments();
+ initMenuItemViews();
}
}
}, LAZY_INITIALIZATION_DELAY);
@@ -3174,7 +2523,11 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
}
private void initSideFragments() {
- SideFragment.preloadRecycledViews(this);
+ SideFragment.preloadItemViews(this);
+ }
+
+ private void initMenuItemViews() {
+ mOverlayManager.getMenu().preloadItemViews();
}
@Override
@@ -3207,10 +2560,6 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
sendMessageDelayed(Message.obtain(msg), getDelay(startTime));
mainActivity.moveToAdjacentChannel(true, true);
break;
- case MSG_UPDATE_CHANNEL_BANNER_BY_INFO_UPDATE:
- mainActivity.updateChannelBannerAndShowIfNeeded(
- UPDATE_CHANNEL_BANNER_REASON_UPDATE_INFO);
- break;
}
}
@@ -3225,14 +2574,10 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
private class MyOnTuneListener implements OnTuneListener {
boolean mUnlockAllowedRatingBeforeShrunken = true;
boolean mWasUnderShrunkenTvView;
- long mStreamInfoUpdateTimeThresholdMs;
Channel mChannel;
- public MyOnTuneListener() { }
-
private void onTune(Channel channel, boolean wasUnderShrukenTvView) {
- mStreamInfoUpdateTimeThresholdMs =
- System.currentTimeMillis() + FIRST_STREAM_INFO_UPDATE_DELAY_MILLIS;
+ Debug.getTimer(Debug.TAG_START_UP_TIMER).log("MainActivity.MyOnTuneListener.onTune");
mChannel = channel;
mWasUnderShrunkenTvView = wasUnderShrukenTvView;
}
@@ -3249,7 +2594,8 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
if (mTvView.isFadedOut()) {
mTvView.removeFadeEffect();
}
- // TODO: show something to user about this error.
+ Toast.makeText(MainActivity.this, R.string.msg_channel_unavailable_unknown,
+ Toast.LENGTH_SHORT).show();
}
@Override
@@ -3258,29 +2604,21 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
mTracker.sendChannelTuneTime(info.getCurrentChannel(),
mTuneDurationTimer.reset());
}
- // If updateChannelBanner() is called without delay, the stream info seems flickering
- // when the channel is quickly changed.
- if (!mHandler.hasMessages(MSG_UPDATE_CHANNEL_BANNER_BY_INFO_UPDATE)
- && info.isVideoAvailable()) {
- if (System.currentTimeMillis() > mStreamInfoUpdateTimeThresholdMs) {
- updateChannelBannerAndShowIfNeeded(
- UPDATE_CHANNEL_BANNER_REASON_UPDATE_INFO);
- } else {
- mHandler.sendMessageDelayed(mHandler.obtainMessage(
- MSG_UPDATE_CHANNEL_BANNER_BY_INFO_UPDATE),
- mStreamInfoUpdateTimeThresholdMs - System.currentTimeMillis());
- }
+ if (info.isVideoOrAudioAvailable() && mChannel == getCurrentChannel()) {
+ mOverlayManager.updateChannelBannerAndShowIfNeeded(
+ TvOverlayManager.UPDATE_CHANNEL_BANNER_REASON_UPDATE_STREAM_INFO);
}
-
applyDisplayRefreshRate(info.getVideoFrameRate());
- mTvViewUiManager.updateTvView();
+ mTvViewUiManager.updateTvAspectRatio();
applyMultiAudio();
applyClosedCaption();
- // TODO: Send command to TIS with checking the settings in TV and CaptionManager.
mOverlayManager.getMenu().onStreamInfoChanged();
if (mTvView.isVideoAvailable()) {
mTvViewUiManager.fadeInTvView();
}
+ if (!mTvView.isContentBlocked() && !mTvView.isScreenBlocked()) {
+ updateAvailabilityToast();
+ }
mHandler.removeCallbacks(mRestoreMainViewRunnable);
restoreMainTvView();
}
@@ -3303,11 +2641,15 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
}
mChannelTuner.setCurrentChannel(currentChannel);
mTvView.setCurrentChannel(currentChannel);
- updateChannelBannerAndShowIfNeeded(UPDATE_CHANNEL_BANNER_REASON_TUNE);
+ mOverlayManager.updateChannelBannerAndShowIfNeeded(
+ TvOverlayManager.UPDATE_CHANNEL_BANNER_REASON_TUNE);
}
@Override
public void onContentBlocked() {
+ Debug.getTimer(Debug.TAG_START_UP_TIMER).log(
+ "MainActivity.MyOnTuneListener.onContentBlocked removes timer");
+ Debug.removeTimer(Debug.TAG_START_UP_TIMER);
mTuneDurationTimer.reset();
TvContentRating rating = mTvView.getBlockedContentRating();
// When tuneTo was called while TV view was shrunken, if the channel id is the same
@@ -3319,9 +2661,9 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
mUnlockAllowedRatingBeforeShrunken = isUnderShrunkenTvView();
mTvView.unblockContent(rating);
}
- mChannelBannerView.setBlockingContentRating(rating);
- updateChannelBannerAndShowIfNeeded(UPDATE_CHANNEL_BANNER_REASON_LOCK_OR_UNLOCK);
+ mOverlayManager.setBlockingContentRating(rating);
mTvViewUiManager.fadeInTvView();
+ mMediaSessionWrapper.update(true, getCurrentChannel(), getCurrentProgram());
}
@Override
@@ -3329,8 +2671,8 @@ public class MainActivity extends Activity implements AudioManager.OnAudioFocusC
if (!isUnderShrunkenTvView()) {
mUnlockAllowedRatingBeforeShrunken = false;
}
- mChannelBannerView.setBlockingContentRating(null);
- updateChannelBannerAndShowIfNeeded(UPDATE_CHANNEL_BANNER_REASON_LOCK_OR_UNLOCK);
+ mOverlayManager.setBlockingContentRating(null);
+ mMediaSessionWrapper.update(false, getCurrentChannel(), getCurrentProgram());
}
}
}