diff options
Diffstat (limited to 'src/com/android')
-rw-r--r-- | src/com/android/tv/TvActivity.java | 24 | ||||
-rw-r--r-- | src/com/android/tv/notification/NotificationService.java | 33 | ||||
-rw-r--r-- | src/com/android/tv/ui/TunableTvView.java | 46 | ||||
-rw-r--r-- | src/com/android/tv/util/TvInputManagerHelper.java | 7 |
4 files changed, 65 insertions, 45 deletions
diff --git a/src/com/android/tv/TvActivity.java b/src/com/android/tv/TvActivity.java index b5671bfc..23cb4596 100644 --- a/src/com/android/tv/TvActivity.java +++ b/src/com/android/tv/TvActivity.java @@ -126,10 +126,13 @@ public class TvActivity extends Activity implements AudioManager.OnAudioFocusCha private static final int REQUEST_START_SETUP_ACTIIVTY = 0; private static final int REQUEST_START_SETTINGS_ACTIIVTY = 1; + private static final String KEY_INIT_CHANNEL_ID = "com.android.tv.init_channel_id"; + private static final HashSet<String> AVAILABLE_DIALOG_TAGS = new HashSet<String>(); private View mContentView; private TunableTvView mTvView; + private Bundle mTuneParams; private LinearLayout mControlGuide; private MainMenuView mMainMenuView; private ChannelBannerView mChannelBanner; @@ -344,6 +347,11 @@ public class TvActivity extends Activity implements AudioManager.OnAudioFocusCha if (Intent.ACTION_VIEW.equals(intent.getAction())) { // In case the channel is given explicitly, use it. mInitChannelId = ContentUris.parseId(intent.getData()); + mTuneParams = intent.getExtras(); + if (mTuneParams == null) { + mTuneParams = new Bundle(); + } + mTuneParams.putLong(KEY_INIT_CHANNEL_ID, mInitChannelId); } else { mInitChannelId = Channel.INVALID_ID; } @@ -428,6 +436,7 @@ public class TvActivity extends Activity implements AudioManager.OnAudioFocusCha if (TextUtils.isEmpty(inputId)) { // If the channel is invalid, try to use the last selected physical tv input. inputId = Utils.getLastSelectedPhysInputId(this); + channelId = Channel.INVALID_ID; if (TextUtils.isEmpty(inputId)) { // If failed to determine the input for that channel, try a different input. showInputPicker(BaseSideFragment.INITIATOR_UNKNOWN); @@ -838,7 +847,7 @@ public class TvActivity extends Activity implements AudioManager.OnAudioFocusCha } if (DEBUG) Log.d(TAG, "startPip()"); mPipView.start(mTvInputManagerHelper); - boolean success = mPipView.tuneTo(mPipChannelId, new OnTuneListener() { + boolean success = mPipView.tuneTo(mPipChannelId, null, new OnTuneListener() { @Override public void onUnexpectedStop(long channelId) { Log.w(TAG, "The PIP is Unexpectedly stopped"); @@ -888,7 +897,7 @@ public class TvActivity extends Activity implements AudioManager.OnAudioFocusCha } mChannelNumberView.setChannels( - (mChannelMap == null) ? null : mChannelMap.getChannelList(false)); + (mChannelMap == null) ? null : mChannelMap.getChannelList(true)); mMainMenuView.setChannelMap(mChannelMap); } }; @@ -910,7 +919,14 @@ public class TvActivity extends Activity implements AudioManager.OnAudioFocusCha return; } - mTvView.tuneTo(channelId, new OnTuneListener() { + if (mTuneParams != null) { + if (channelId == mTuneParams.getLong(KEY_INIT_CHANNEL_ID)) { + mTuneParams.remove(KEY_INIT_CHANNEL_ID); + } else { + mTuneParams = null; + } + } + mTvView.tuneTo(channelId, mTuneParams, new OnTuneListener() { @Override public void onUnexpectedStop(long channelId) { stopTv(); @@ -939,6 +955,7 @@ public class TvActivity extends Activity implements AudioManager.OnAudioFocusCha // TODO: update {@code mChannelMap} and the banner. } }); + mTuneParams = null; updateChannelBanner(true); if (mChildActivityCanceled) { displayMainMenu(false); @@ -1064,6 +1081,7 @@ public class TvActivity extends Activity implements AudioManager.OnAudioFocusCha protected void onDestroy() { if (DEBUG) Log.d(TAG, "onDestroy()"); mTvInputManagerHelper.stop(); + super.onDestroy(); } diff --git a/src/com/android/tv/notification/NotificationService.java b/src/com/android/tv/notification/NotificationService.java index 01998065..5b2a77c8 100644 --- a/src/com/android/tv/notification/NotificationService.java +++ b/src/com/android/tv/notification/NotificationService.java @@ -32,6 +32,7 @@ import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.Rect; import android.net.Uri; +import android.media.tv.TvContract; import android.media.tv.TvInputInfo; import android.media.tv.TvInputManager; import android.os.Handler; @@ -44,6 +45,7 @@ import android.util.Log; import com.android.tv.R; import com.android.tv.data.Program; import com.android.tv.recommendation.RandomRecommender; +import com.android.tv.recommendation.RoutineWatchRecommender; import com.android.tv.recommendation.TvRecommendation; import com.android.tv.recommendation.TvRecommendation.ChannelRecord; import com.android.tv.util.TvInputManagerHelper; @@ -60,7 +62,7 @@ import java.net.URL; * A local service for notify recommendation at home launcher. */ public class NotificationService extends Service { - private static final boolean DEBUG = false; + private static final boolean DEBUG = true; private static final String TAG = "NotificationService"; public static final String ACTION_SHOW_RECOMMENDATION = @@ -68,6 +70,11 @@ public class NotificationService extends Service { public static final String ACTION_HIDE_RECOMMENDATION = "com.android.tv.notification.ACTION_HIDE_RECOMMENDATION"; + private static final String TUNE_PARAMS_RECOMMENDATION_TYPE = + "com.android.tv.recommendation_type"; + private static final String TYPE_RANDOM_RECOMMENDATION = "random"; + private static final String TYPE_ROUTINE_WATCH_RECOMMENDATION = "routine_watch"; + private static final String NOTIFY_TAG = "tv_recommendation"; // TODO: find out proper number of notifications and whether to make it dynamically // configurable from system property or etc. @@ -88,6 +95,7 @@ public class NotificationService extends Service { private NotificationManager mNotificationManager; private final HandlerThread mHandlerThread; private final Handler mHandler; + private final String mRecommendationType; private float mNotificationCardMaxWidth; private float mNotificationCardHeight; @@ -124,6 +132,7 @@ public class NotificationService extends Service { } } }; + mRecommendationType = TYPE_RANDOM_RECOMMENDATION; } @Override @@ -136,9 +145,15 @@ public class NotificationService extends Service { R.dimen.notif_card_img_height); mTvRecommendation = new TvRecommendation(this, mHandler, true); - mTvRecommendation.registerTvRecommender(new RandomRecommender()); - mNotificationManager = (NotificationManager) getSystemService( - Context.NOTIFICATION_SERVICE); + if (TYPE_RANDOM_RECOMMENDATION.equals(mRecommendationType)) { + mTvRecommendation.registerTvRecommender(new RandomRecommender()); + } else if (TYPE_ROUTINE_WATCH_RECOMMENDATION.equals(mRecommendationType)) { + mTvRecommendation.registerTvRecommender(new RoutineWatchRecommender(this)); + } else { + throw new IllegalStateException("Undefined recommendation type: " + + mRecommendationType); + } + mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); mTvInputManager = (TvInputManager) getSystemService(Context.TV_INPUT_SERVICE); mTvInputManagerHelper = new TvInputManagerHelper(mTvInputManager); mTvInputManagerHelper.start(); @@ -152,11 +167,11 @@ public class NotificationService extends Service { if (ACTION_SHOW_RECOMMENDATION.equals(action)) { mHandler.removeMessages(MSG_SHOW_RECOMMENDATION); mHandler.removeMessages(MSG_HIDE_RECOMMENDATION); - mHandler.obtainMessage(MSG_SHOW_RECOMMENDATION).sendToTarget();; + mHandler.obtainMessage(MSG_SHOW_RECOMMENDATION).sendToTarget(); } else if (ACTION_HIDE_RECOMMENDATION.equals(action)) { mHandler.removeMessages(MSG_SHOW_RECOMMENDATION); mHandler.removeMessages(MSG_HIDE_RECOMMENDATION); - mHandler.obtainMessage(MSG_HIDE_RECOMMENDATION).sendToTarget();; + mHandler.obtainMessage(MSG_HIDE_RECOMMENDATION).sendToTarget(); } } return START_STICKY; @@ -196,6 +211,7 @@ public class NotificationService extends Service { if (DEBUG) Log.d(TAG, "sendNotification (" + cr.getChannel().getDisplayName() + " notifyId=" + notifyId + ")"); Intent intent = new Intent(Intent.ACTION_VIEW, cr.getChannelUri()); + intent.putExtra(TUNE_PARAMS_RECOMMENDATION_TYPE, mRecommendationType); PendingIntent notificationIntent = PendingIntent.getActivity(this, 0, intent, 0); // TODO: Move some checking logic into TvRecommendation. @@ -216,7 +232,8 @@ public class NotificationService extends Service { } long programDurationMs = program.getEndTimeUtcMillis() - program.getStartTimeUtcMillis(); long programLeftTimsMs = program.getEndTimeUtcMillis() - System.currentTimeMillis(); - int programProgress = 100 - (int) (programLeftTimsMs * 100 / programDurationMs); + int programProgress = (programDurationMs <= 0) ? -1 + : 100 - (int) (programLeftTimsMs * 100 / programDurationMs); // We doesn't trust TIS to provide us with proper sized image Bitmap posterArtBitmap = BitmapUtils.decodeSampledBitmapFromUriString(this, @@ -239,7 +256,7 @@ public class NotificationService extends Service { .setLargeIcon(largeIconBitmap) .setSmallIcon(R.drawable.ic_launcher_s) .setCategory(Notification.CATEGORY_RECOMMENDATION) - .setProgress(100, programProgress, false) + .setProgress((programProgress > 0) ? 100 : 0, programProgress, false) .build(); notification.color = getResources().getColor(R.color.recommendation_card_background); diff --git a/src/com/android/tv/ui/TunableTvView.java b/src/com/android/tv/ui/TunableTvView.java index 90e73122..b0db3a1d 100644 --- a/src/com/android/tv/ui/TunableTvView.java +++ b/src/com/android/tv/ui/TunableTvView.java @@ -9,11 +9,11 @@ import android.media.tv.TvView; import android.media.tv.TvView.OnUnhandledInputEventListener; import android.media.tv.TvView.TvInputListener; import android.net.Uri; +import android.os.Bundle; import android.util.AttributeSet; import android.util.Log; import android.view.KeyEvent; import android.view.MotionEvent; -import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.ViewGroup; import android.widget.FrameLayout; @@ -24,14 +24,15 @@ import com.android.tv.data.StreamInfo; import com.android.tv.util.TvInputManagerHelper; import com.android.tv.util.Utils; +import java.util.HashMap; import java.util.List; +import java.util.Map; public class TunableTvView extends FrameLayout implements StreamInfo { // STOPSHIP: Turn debugging off private static final boolean DEBUG = true; private static final String TAG = "TunableTvView"; - private static final int DELAY_FOR_SURFACE_RELEASE = 300; public static final String PERMISSION_RECEIVE_INPUT_EVENT = "android.permission.RECEIVE_INPUT_EVENT"; @@ -52,27 +53,7 @@ public class TunableTvView extends FrameLayout implements StreamInfo { private boolean mCanReceiveInputEvent; private boolean mIsMuted; private float mVolume; - - private final SurfaceHolder.Callback mSurfaceHolderCallback = new SurfaceHolder.Callback() { - @Override - public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } - - @Override - public void surfaceCreated(SurfaceHolder holder) { } - - @Override - public void surfaceDestroyed(SurfaceHolder holder) { - // TODO: It is a hack to wait to release a surface at TIS. If there is a way to - // know when the surface is released at TIS, we don't need this hack. - try { - if (DEBUG) Log.d(TAG, "Sleep to wait destroying a surface"); - Thread.sleep(DELAY_FOR_SURFACE_RELEASE); - if (DEBUG) Log.d(TAG, "Wake up from sleeping"); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - }; + private final Map<Long, String> mChannelToInputMap = new HashMap<Long, String>(); private final TvInputListener mListener = new TvInputListener() { @@ -205,7 +186,7 @@ public class TunableTvView extends FrameLayout implements StreamInfo { return mStarted; } - public boolean tuneTo(long channelId, OnTuneListener listener) { + public boolean tuneTo(long channelId, Bundle params, OnTuneListener listener) { if (!mStarted) { throw new IllegalStateException("TvView isn't started"); } @@ -215,7 +196,12 @@ public class TunableTvView extends FrameLayout implements StreamInfo { mVideoFormat = StreamInfo.VIDEO_DEFINITION_LEVEL_UNKNOWN; mAudioChannelCount = StreamInfo.AUDIO_CHANNEL_COUNT_UNKNOWN; mHasClosedCaption = false; - String inputId = Utils.getInputIdForChannel(getContext(), channelId); + String inputId = null; + inputId = mChannelToInputMap.get(channelId); + if (inputId == null) { + inputId = Utils.getInputIdForChannel(getContext(), channelId); + mChannelToInputMap.put(channelId, inputId); + } TvInputInfo inputInfo = mInputManagerHelper.getTvInputInfo(inputId); if (inputInfo == null || mInputManagerHelper.getInputState(inputInfo) == @@ -226,20 +212,13 @@ public class TunableTvView extends FrameLayout implements StreamInfo { mChannelId = channelId; if (!inputInfo.equals(mInputInfo)) { mTvView.reset(); - // TODO: It is a hack to wait to release a surface at TIS. If there is a way to - // know when the surface is released at TIS, we don't need this hack. - try { - Thread.sleep(DELAY_FOR_SURFACE_RELEASE); - } catch (InterruptedException e) { - e.printStackTrace(); - } mInputInfo = inputInfo; mCanReceiveInputEvent = getContext().getPackageManager().checkPermission( PERMISSION_RECEIVE_INPUT_EVENT, mInputInfo.getComponent().getPackageName()) == PackageManager.PERMISSION_GRANTED; } mTvView.setTvInputListener(mListener); - mTvView.tune(mInputInfo.getId(), Utils.getChannelUri(mChannelId)); + mTvView.tune(mInputInfo.getId(), Utils.getChannelUri(mChannelId), params); if (mOnTuneListener != null) { // TODO: Add a callback for tune complete and call onTuned when it was successful. mOnTuneListener.onTuned(true, mChannelId); @@ -384,7 +363,6 @@ public class TunableTvView extends FrameLayout implements StreamInfo { for (int i = 0; i < view.getChildCount(); ++i) { if (view.getChildAt(i) instanceof SurfaceView) { SurfaceView surfaceView = (SurfaceView) mTvView.getChildAt(i); - surfaceView.getHolder().addCallback(mSurfaceHolderCallback); return surfaceView; } } diff --git a/src/com/android/tv/util/TvInputManagerHelper.java b/src/com/android/tv/util/TvInputManagerHelper.java index 6e152970..6ce7a42c 100644 --- a/src/com/android/tv/util/TvInputManagerHelper.java +++ b/src/com/android/tv/util/TvInputManagerHelper.java @@ -19,6 +19,7 @@ package com.android.tv.util; import android.media.tv.TvInputInfo; import android.media.tv.TvInputManager; import android.media.tv.TvInputManager.TvInputListener; +import android.net.Uri; import android.os.Handler; import android.util.Log; @@ -54,6 +55,7 @@ public class TvInputManagerHelper { private final Handler mHandler = new Handler(); private boolean mStarted; private final HashSet<TvInputListener> mListeners = new HashSet<TvInputListener>(); + private List<Uri> mTvContentRatingSystemXmls; public TvInputManagerHelper(TvInputManager tvInputManager) { mTvInputManager = tvInputManager; @@ -87,6 +89,7 @@ public class TvInputManagerHelper { mInputStateMap.put(inputId, state); } Assert.assertEquals(mInputStateMap.size(), mInputMap.size()); + mTvContentRatingSystemXmls = mTvInputManager.getTvContentRatingSystemXmls(); } public void stop() { @@ -155,6 +158,10 @@ public class TvInputManagerHelper { return state; } + public List<Uri> getTvContentRatingSystemXmls() { + return mTvContentRatingSystemXmls; + } + public void addListener(TvInputListener listener) { mListeners.add(listener); } |