aboutsummaryrefslogtreecommitdiff
path: root/src/com/android/tv/TvApplication.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/tv/TvApplication.java')
-rw-r--r--src/com/android/tv/TvApplication.java230
1 files changed, 184 insertions, 46 deletions
diff --git a/src/com/android/tv/TvApplication.java b/src/com/android/tv/TvApplication.java
index ef105c94..0e18a259 100644
--- a/src/com/android/tv/TvApplication.java
+++ b/src/com/android/tv/TvApplication.java
@@ -22,9 +22,9 @@ import android.app.Application;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
-import android.media.tv.TvContract;
import android.media.tv.TvInputInfo;
import android.media.tv.TvInputManager;
import android.media.tv.TvInputManager.TvInputCallback;
@@ -32,7 +32,7 @@ import android.os.Build;
import android.os.Bundle;
import android.os.StrictMode;
import android.support.annotation.Nullable;
-import android.support.v4.os.BuildCompat;
+import android.text.TextUtils;
import android.util.Log;
import android.view.KeyEvent;
@@ -42,37 +42,47 @@ import com.android.tv.analytics.StubAnalytics;
import com.android.tv.analytics.Tracker;
import com.android.tv.common.BuildConfig;
import com.android.tv.common.SharedPreferencesUtils;
+import com.android.tv.common.SoftPreconditions;
import com.android.tv.common.TvCommonUtils;
import com.android.tv.common.feature.CommonFeatures;
import com.android.tv.common.ui.setup.animation.SetupAnimationHelper;
+import com.android.tv.config.DefaultConfigManager;
+import com.android.tv.config.RemoteConfig;
import com.android.tv.data.ChannelDataManager;
import com.android.tv.data.ProgramDataManager;
import com.android.tv.dvr.DvrDataManager;
import com.android.tv.dvr.DvrDataManagerImpl;
import com.android.tv.dvr.DvrManager;
import com.android.tv.dvr.DvrRecordingService;
-import com.android.tv.dvr.DvrSessionManager;
+import com.android.tv.dvr.DvrScheduleManager;
+import com.android.tv.dvr.DvrStorageStatusManager;
+import com.android.tv.dvr.DvrWatchedPositionManager;
+import com.android.tv.tuner.TunerPreferences;
+import com.android.tv.tuner.tvinput.TunerTvInputService;
+import com.android.tv.tuner.util.TunerInputInfoUtils;
+import com.android.tv.util.AccountHelper;
import com.android.tv.util.Clock;
import com.android.tv.util.SetupUtils;
import com.android.tv.util.SystemProperties;
import com.android.tv.util.TvInputManagerHelper;
import com.android.tv.util.Utils;
-import com.android.usbtuner.UsbTunerPreferences;
-import com.android.usbtuner.setup.TunerSetupActivity;
-import com.android.usbtuner.tvinput.UsbTunerTvInputService;
import java.util.List;
public class TvApplication extends Application implements ApplicationSingletons {
private static final String TAG = "TvApplication";
private static final boolean DEBUG = false;
+ private RemoteConfig mRemoteConfig;
/**
- * Returns the @{@link ApplicationSingletons} using the application context.
+ * Broadcast Action: The user has updated LC to a new version that supports tuner input.
+ * {@link TunerInputController} will recevice this intent to check the existence of tuner
+ * input when the new version is first launched.
*/
- public static ApplicationSingletons getSingletons(Context context) {
- return (ApplicationSingletons) context.getApplicationContext();
- }
+ public static final String ACTION_APPLICATION_FIRST_LAUNCHED =
+ "com.android.tv.action.APPLICATION_FIRST_LAUNCHED";
+ private static final String PREFERENCE_IS_FIRST_LAUNCH = "is_first_launch";
+
private String mVersionName = "";
private final MainActivityWrapper mMainActivityWrapper = new MainActivityWrapper();
@@ -84,14 +94,30 @@ public class TvApplication extends Application implements ApplicationSingletons
private ChannelDataManager mChannelDataManager;
private ProgramDataManager mProgramDataManager;
private DvrManager mDvrManager;
+ private DvrScheduleManager mDvrScheduleManager;
private DvrDataManager mDvrDataManager;
+ private DvrStorageStatusManager mDvrStorageStatusManager;
+ private DvrWatchedPositionManager mDvrWatchedPositionManager;
@Nullable
- private DvrSessionManager mDvrSessionManager;
+ private InputSessionManager mInputSessionManager;
+ private AccountHelper mAccountHelper;
+ // When this variable is null, we don't know in which process TvApplication runs.
+ private Boolean mRunningInMainProcess;
@Override
public void onCreate() {
super.onCreate();
- SharedPreferencesUtils.initialize(this);
+ SharedPreferencesUtils.initialize(this, new Runnable() {
+ @Override
+ public void run() {
+ if (mRunningInMainProcess != null && mRunningInMainProcess) {
+ checkTunerServiceOnFirstLaunch();
+ }
+ }
+ });
+ // TunerPreferences is used to enable/disable the tuner input even when TUNER feature is
+ // disabled.
+ TunerPreferences.initialize(this);
try {
PackageInfo pInfo = getPackageManager().getPackageInfo(getPackageName(), 0);
mVersionName = pInfo.versionName;
@@ -100,17 +126,21 @@ public class TvApplication extends Application implements ApplicationSingletons
mVersionName = "";
}
Log.i(TAG, "Starting Live TV " + getVersionName());
+
+
// Only set StrictMode for ENG builds because the build server only produces userdebug
// builds.
if (BuildConfig.ENG && SystemProperties.ALLOW_STRICT_MODE.getValue()) {
- StrictMode.setThreadPolicy(
- new StrictMode.ThreadPolicy.Builder().detectAll().penaltyLog().build());
- StrictMode.VmPolicy.Builder vmPolicyBuilder = new StrictMode.VmPolicy.Builder()
- .detectAll().penaltyLog();
- if (BuildConfig.ENG && SystemProperties.ALLOW_DEATH_PENALTY.getValue() &&
- !TvCommonUtils.isRunningInTest()) {
- // TODO turn on death penalty for tests when they stop leaking MainActivity
+ StrictMode.ThreadPolicy.Builder threadPolicyBuilder =
+ new StrictMode.ThreadPolicy.Builder().detectAll().penaltyLog();
+ StrictMode.VmPolicy.Builder vmPolicyBuilder =
+ new StrictMode.VmPolicy.Builder().detectAll().penaltyLog();
+ if (!TvCommonUtils.isRunningInTest()) {
+ threadPolicyBuilder.penaltyDialog();
+ // Turn off death penalty for tests b/23355898
+ vmPolicyBuilder.penaltyDeath();
}
+ StrictMode.setThreadPolicy(threadPolicyBuilder.build());
StrictMode.setVmPolicy(vmPolicyBuilder.build());
}
if (BuildConfig.ENG && !SystemProperties.ALLOW_ANALYTICS_IN_ENG.getValue()) {
@@ -121,27 +151,63 @@ public class TvApplication extends Application implements ApplicationSingletons
mTracker = mAnalytics.getDefaultTracker();
mTvInputManagerHelper = new TvInputManagerHelper(this);
mTvInputManagerHelper.start();
- mTvInputManagerHelper.addCallback(new TvInputCallback() {
- @Override
- public void onInputAdded(String inputId) {
- handleInputCountChanged();
- }
-
- @Override
- public void onInputRemoved(String inputId) {
- handleInputCountChanged();
- }
- });
- if (CommonFeatures.DVR.isEnabled(this) && BuildCompat.isAtLeastN()) {
- mDvrManager = new DvrManager(this);
- //NOTE: DvrRecordingService just keeps running.
- DvrRecordingService.startService(this);
- }
// In SetupFragment, transitions are set in the constructor. Because the fragment can be
// created in Activity.onCreate() by the framework, SetupAnimationHelper should be
// initialized here before Activity.onCreate() is called.
SetupAnimationHelper.initialize(this);
- if (DEBUG) Log.i(TAG, "Started Live TV " + mVersionName);
+ Log.i(TAG, "Started Live TV " + mVersionName);
+ }
+
+ private void setCurrentRunningProcess(boolean isMainProcess) {
+ if (mRunningInMainProcess != null) {
+ SoftPreconditions.checkState(isMainProcess == mRunningInMainProcess);
+ return;
+ }
+ mRunningInMainProcess = isMainProcess;
+ if (CommonFeatures.DVR.isEnabled(this)) {
+ mDvrStorageStatusManager = new DvrStorageStatusManager(this, mRunningInMainProcess);
+ }
+ if (mRunningInMainProcess) {
+ mTvInputManagerHelper.addCallback(new TvInputCallback() {
+ @Override
+ public void onInputAdded(String inputId) {
+ if (Features.TUNER.isEnabled(TvApplication.this) && TextUtils.equals(inputId,
+ TunerTvInputService.getInputId(TvApplication.this))) {
+ TunerInputInfoUtils.updateTunerInputInfo(TvApplication.this);
+ }
+ handleInputCountChanged();
+ }
+
+ @Override
+ public void onInputRemoved(String inputId) {
+ handleInputCountChanged();
+ }
+ });
+ if (Features.TUNER.isEnabled(this)) {
+ // If the tuner input service is added before the app is started, we need to
+ // handle it here.
+ TunerInputInfoUtils.updateTunerInputInfo(this);
+ }
+ if (CommonFeatures.DVR.isEnabled(this)) {
+ mDvrScheduleManager = new DvrScheduleManager(this);
+ mDvrManager = new DvrManager(this);
+ //NOTE: DvrRecordingService just keeps running.
+ DvrRecordingService.startService(this);
+ }
+ }
+ }
+
+ private void checkTunerServiceOnFirstLaunch() {
+ SharedPreferences sharedPreferences = this.getSharedPreferences(
+ SharedPreferencesUtils.SHARED_PREF_FEATURES, Context.MODE_PRIVATE);
+ boolean isFirstLaunch = sharedPreferences.getBoolean(PREFERENCE_IS_FIRST_LAUNCH, true);
+ if (isFirstLaunch) {
+ if (DEBUG) Log.d(TAG, "Congratulations, it's the first launch!");
+ sendBroadcast(new Intent(ACTION_APPLICATION_FIRST_LAUNCHED));
+ SharedPreferences.Editor editor = sharedPreferences.edit();
+ editor.putBoolean(PREFERENCE_IS_FIRST_LAUNCH, false);
+ editor.apply();
+ }
}
/**
@@ -152,13 +218,32 @@ public class TvApplication extends Application implements ApplicationSingletons
return mDvrManager;
}
+ /**
+ * Returns the {@link DvrScheduleManager}.
+ */
+ @Override
+ public DvrScheduleManager getDvrScheduleManager() {
+ return mDvrScheduleManager;
+ }
+
+ /**
+ * Returns the {@link DvrWatchedPositionManager}.
+ */
+ @Override
+ public DvrWatchedPositionManager getDvrWatchedPositionManager() {
+ if (mDvrWatchedPositionManager == null) {
+ mDvrWatchedPositionManager = new DvrWatchedPositionManager(this);
+ }
+ return mDvrWatchedPositionManager;
+ }
+
@Override
@TargetApi(Build.VERSION_CODES.N)
- public DvrSessionManager getDvrSessionManger() {
- if (mDvrSessionManager == null) {
- mDvrSessionManager = new DvrSessionManager(this);
+ public InputSessionManager getInputSessionManager() {
+ if (mInputSessionManager == null) {
+ mInputSessionManager = new InputSessionManager(this);
}
- return mDvrSessionManager;
+ return mInputSessionManager;
}
/**
@@ -177,7 +262,6 @@ public class TvApplication extends Application implements ApplicationSingletons
return mTracker;
}
-
/**
* Returns {@link ChannelDataManager}.
*/
@@ -209,14 +293,23 @@ public class TvApplication extends Application implements ApplicationSingletons
@Override
public DvrDataManager getDvrDataManager() {
if (mDvrDataManager == null) {
- DvrDataManagerImpl dvrDataManager = new DvrDataManagerImpl(this, Clock.SYSTEM);
- mDvrDataManager = dvrDataManager;
- dvrDataManager.start();
+ DvrDataManagerImpl dvrDataManager = new DvrDataManagerImpl(this, Clock.SYSTEM);
+ mDvrDataManager = dvrDataManager;
+ dvrDataManager.start();
}
return mDvrDataManager;
}
/**
+ * Returns {@link DvrStorageStatusManager}.
+ */
+ @TargetApi(Build.VERSION_CODES.N)
+ @Override
+ public DvrStorageStatusManager getDvrStorageStatusManager() {
+ return mDvrStorageStatusManager;
+ }
+
+ /**
* Returns {@link TvInputManagerHelper}.
*/
@Override
@@ -233,6 +326,26 @@ public class TvApplication extends Application implements ApplicationSingletons
}
/**
+ * Returns the {@link AccountHelper}.
+ */
+ @Override
+ public AccountHelper getAccountHelper() {
+ if (mAccountHelper == null) {
+ mAccountHelper = new AccountHelper(getApplicationContext());
+ }
+ return mAccountHelper;
+ }
+
+ @Override
+ public RemoteConfig getRemoteConfig() {
+ if (mRemoteConfig == null) {
+ // No need to synchronize this, it does not hurt to create two and throw one away.
+ mRemoteConfig = DefaultConfigManager.createInstance(this).getRemoteConfig();
+ }
+ return mRemoteConfig;
+ }
+
+ /**
* SelectInputActivity is set in {@link SelectInputActivity#onCreate} and cleared in
* {@link SelectInputActivity#onDestroy}.
*/
@@ -322,7 +435,7 @@ public class TvApplication extends Application implements ApplicationSingletons
* Checks the input counts and enable/disable TvActivity. Also updates the input list in
* {@link SetupUtils}.
*
- * @param calledByTunerServiceChanged true if it is called when UsbTunerTvInputService
+ * @param calledByTunerServiceChanged true if it is called when TunerTvInputService
* is enabled or disabled.
* @param tunerServiceEnabled it's available only when calledByTunerServiceChanged is true.
* @param dontKillApp when TvActivity is enabled or disabled by this method, the app restarts
@@ -340,7 +453,7 @@ public class TvApplication extends Application implements ApplicationSingletons
if (!skipTunerInputCheck) {
for (TvInputInfo input : inputs) {
if (calledByTunerServiceChanged && !tunerServiceEnabled
- && UsbTunerTvInputService.getInputId(this).equals(input.getId())) {
+ && TunerTvInputService.getInputId(this).equals(input.getId())) {
continue;
}
if (input.getType() == TvInputInfo.TYPE_TUNER) {
@@ -361,4 +474,29 @@ public class TvApplication extends Application implements ApplicationSingletons
}
SetupUtils.getInstance(TvApplication.this).onInputListUpdated(inputManager);
}
+
+ /**
+ * Returns the @{@link ApplicationSingletons} using the application context.
+ */
+ public static ApplicationSingletons getSingletons(Context context) {
+ return (ApplicationSingletons) context.getApplicationContext();
+ }
+
+ /**
+ * Sets true, if TvApplication is running on the main process. If TvApplication runs on
+ * tuner process or other process, it sets false.
+ *
+ * Note: it should be called at the beginning of Service.onCreate Activity.onCreate, or
+ * BroadcastReceiver.onCreate. When it is firstly called after launch, it runs process
+ * specific initializations.
+ */
+ public static void setCurrentRunningProcess(Context context, boolean isMainProcess) {
+ if (context.getApplicationContext() instanceof TvApplication) {
+ TvApplication tvApplication = (TvApplication) context.getApplicationContext();
+ tvApplication.setCurrentRunningProcess(isMainProcess);
+ } else {
+ // Application context can be MockTvApplication.
+ Log.w(TAG, "It is not a context of TvApplication");
+ }
+ }
}