/* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License */ package com.android.tv.dvr.ui.browse; import android.content.Context; import android.media.tv.TvContract; import android.support.annotation.Nullable; import android.text.TextUtils; import com.android.tv.R; import com.android.tv.TvSingletons; import com.android.tv.data.api.Channel; import com.android.tv.data.api.Program; import com.android.tv.dvr.data.RecordedProgram; import com.android.tv.dvr.data.ScheduledRecording; import com.android.tv.dvr.data.SeriesRecording; import com.android.tv.dvr.ui.DvrUiHelper; /** A class for details content. */ public class DetailsContent { /** Constant for invalid time. */ public static final long INVALID_TIME = -1; private CharSequence mTitle; private long mStartTimeUtcMillis; private long mEndTimeUtcMillis; private String mDescription; private String mLogoImageUri; private String mBackgroundImageUri; private boolean mUsingChannelLogo; private boolean mShowErrorMessage; static DetailsContent createFromRecordedProgram( Context context, RecordedProgram recordedProgram) { return new DetailsContent.Builder() .setChannelId(recordedProgram.getChannelId()) .setProgramTitle(recordedProgram.getTitle()) .setSeasonNumber(recordedProgram.getSeasonNumber()) .setEpisodeNumber(recordedProgram.getEpisodeNumber()) .setStartTimeUtcMillis(recordedProgram.getStartTimeUtcMillis()) .setEndTimeUtcMillis(recordedProgram.getEndTimeUtcMillis()) .setDescription( TextUtils.isEmpty(recordedProgram.getLongDescription()) ? recordedProgram.getDescription() : recordedProgram.getLongDescription()) .setPosterArtUri(recordedProgram.getPosterArtUri()) .setThumbnailUri(recordedProgram.getThumbnailUri()) .build(context); } public static DetailsContent createFromProgram(Context context, Program program) { return new DetailsContent.Builder() .setChannelId(program.getChannelId()) .setProgramTitle(program.getTitle()) .setSeasonNumber(program.getSeasonNumber()) .setEpisodeNumber(program.getEpisodeNumber()) .setStartTimeUtcMillis(program.getStartTimeUtcMillis()) .setEndTimeUtcMillis(program.getEndTimeUtcMillis()) .setDescription( TextUtils.isEmpty(program.getLongDescription()) ? program.getDescription() : program.getLongDescription()) .setPosterArtUri(program.getPosterArtUri()) .setThumbnailUri(program.getThumbnailUri()) .build(context); } static DetailsContent createFromSeriesRecording( Context context, SeriesRecording seriesRecording) { return new DetailsContent.Builder() .setChannelId(seriesRecording.getChannelId()) .setTitle(seriesRecording.getTitle()) .setDescription( TextUtils.isEmpty(seriesRecording.getLongDescription()) ? seriesRecording.getDescription() : seriesRecording.getLongDescription()) .setPosterArtUri(seriesRecording.getPosterUri()) .setThumbnailUri(seriesRecording.getPhotoUri()) .build(context); } static DetailsContent createFromScheduledRecording( Context context, ScheduledRecording scheduledRecording) { Channel channel = TvSingletons.getSingletons(context) .getChannelDataManager() .getChannel(scheduledRecording.getChannelId()); String description; if (scheduledRecording.getState() == ScheduledRecording.STATE_RECORDING_FAILED) { description = getErrorMessage(context, scheduledRecording); } else { description = !TextUtils.isEmpty(scheduledRecording.getProgramDescription()) ? scheduledRecording.getProgramDescription() : scheduledRecording.getProgramLongDescription(); } if (TextUtils.isEmpty(description)) { description = channel != null ? channel.getDescription() : null; } return new DetailsContent.Builder() .setChannelId(scheduledRecording.getChannelId()) .setProgramTitle(scheduledRecording.getProgramTitle()) .setSeasonNumber(scheduledRecording.getSeasonNumber()) .setEpisodeNumber(scheduledRecording.getEpisodeNumber()) .setStartTimeUtcMillis(scheduledRecording.getStartTimeMs()) .setEndTimeUtcMillis(scheduledRecording.getEndTimeMs()) .setDescription(description) .setPosterArtUri(scheduledRecording.getProgramPosterArtUri()) .setThumbnailUri(scheduledRecording.getProgramThumbnailUri()) .setShowErrorMessage( scheduledRecording.getState() == ScheduledRecording.STATE_RECORDING_FAILED) .build(context); } private static String getErrorMessage(Context context, ScheduledRecording recording) { int reason = recording.getFailedReason() == null ? ScheduledRecording.FAILED_REASON_OTHER : recording.getFailedReason(); switch (reason) { case ScheduledRecording.FAILED_REASON_PROGRAM_ENDED_BEFORE_RECORDING_STARTED: return context.getString(R.string.dvr_recording_failed_not_started); case ScheduledRecording.FAILED_REASON_RESOURCE_BUSY: return context.getString(R.string.dvr_recording_failed_resource_busy); case ScheduledRecording.FAILED_REASON_INPUT_UNAVAILABLE: return context.getString( R.string.dvr_recording_failed_input_unavailable, recording.getInputId()); case ScheduledRecording.FAILED_REASON_INPUT_DVR_UNSUPPORTED: return context.getString(R.string.dvr_recording_failed_input_dvr_unsupported); case ScheduledRecording.FAILED_REASON_INSUFFICIENT_SPACE: return context.getString(R.string.dvr_recording_failed_insufficient_space); case ScheduledRecording.FAILED_REASON_OTHER: // fall through case ScheduledRecording.FAILED_REASON_NOT_FINISHED: // fall through case ScheduledRecording.FAILED_REASON_SCHEDULER_STOPPED: // fall through case ScheduledRecording.FAILED_REASON_INVALID_CHANNEL: // fall through case ScheduledRecording.FAILED_REASON_MESSAGE_NOT_SENT: // fall through case ScheduledRecording.FAILED_REASON_CONNECTION_FAILED: // fall through default: return context.getString(R.string.dvr_recording_failed_system_failure, reason); } } private DetailsContent() {} /** Returns title. */ public CharSequence getTitle() { return mTitle; } /** Returns start time. */ public long getStartTimeUtcMillis() { return mStartTimeUtcMillis; } /** Returns end time. */ public long getEndTimeUtcMillis() { return mEndTimeUtcMillis; } /** Returns description. */ public String getDescription() { return mDescription; } /** Returns Logo image URI as a String. */ public String getLogoImageUri() { return mLogoImageUri; } /** Returns background image URI as a String. */ public String getBackgroundImageUri() { return mBackgroundImageUri; } /** Returns if image URIs are from its channels' logo. */ public boolean isUsingChannelLogo() { return mUsingChannelLogo; } /** Returns if the error message should be shown. */ public boolean shouldShowErrorMessage() { return mShowErrorMessage; } /** Copies other details content. */ public void copyFrom(DetailsContent other) { if (this == other) { return; } mTitle = other.mTitle; mStartTimeUtcMillis = other.mStartTimeUtcMillis; mEndTimeUtcMillis = other.mEndTimeUtcMillis; mDescription = other.mDescription; mLogoImageUri = other.mLogoImageUri; mBackgroundImageUri = other.mBackgroundImageUri; mUsingChannelLogo = other.mUsingChannelLogo; mShowErrorMessage = other.mShowErrorMessage; } /** A class for building details content. */ public static final class Builder { private final DetailsContent mDetailsContent; private long mChannelId; private String mProgramTitle; private String mSeasonNumber; private String mEpisodeNumber; private String mPosterArtUri; private String mThumbnailUri; public Builder() { mDetailsContent = new DetailsContent(); mDetailsContent.mStartTimeUtcMillis = INVALID_TIME; mDetailsContent.mEndTimeUtcMillis = INVALID_TIME; } /** Sets title. */ public Builder setTitle(CharSequence title) { mDetailsContent.mTitle = title; return this; } /** Sets start time. */ public Builder setStartTimeUtcMillis(long startTimeUtcMillis) { mDetailsContent.mStartTimeUtcMillis = startTimeUtcMillis; return this; } /** Sets end time. */ public Builder setEndTimeUtcMillis(long endTimeUtcMillis) { mDetailsContent.mEndTimeUtcMillis = endTimeUtcMillis; return this; } /** Sets description. */ public Builder setDescription(String description) { mDetailsContent.mDescription = description; return this; } /** Sets logo image URI as a String. */ public Builder setLogoImageUri(String logoImageUri) { mDetailsContent.mLogoImageUri = logoImageUri; return this; } /** Sets background image URI as a String. */ public Builder setBackgroundImageUri(String backgroundImageUri) { mDetailsContent.mBackgroundImageUri = backgroundImageUri; return this; } private Builder setProgramTitle(String programTitle) { mProgramTitle = programTitle; return this; } private Builder setSeasonNumber(String seasonNumber) { mSeasonNumber = seasonNumber; return this; } private Builder setEpisodeNumber(String episodeNumber) { mEpisodeNumber = episodeNumber; return this; } private Builder setChannelId(long channelId) { mChannelId = channelId; return this; } private Builder setPosterArtUri(String posterArtUri) { mPosterArtUri = posterArtUri; return this; } private Builder setThumbnailUri(String thumbnailUri) { mThumbnailUri = thumbnailUri; return this; } private Builder setShowErrorMessage(boolean showErrorMessage) { mDetailsContent.mShowErrorMessage = showErrorMessage; return this; } private void createStyledTitle(Context context, Channel channel) { CharSequence title = DvrUiHelper.getStyledTitleWithEpisodeNumber( context, mProgramTitle, mSeasonNumber, mEpisodeNumber, R.style.text_appearance_card_view_episode_number); if (TextUtils.isEmpty(title)) { mDetailsContent.mTitle = channel != null ? channel.getDisplayName() : context.getResources().getString(R.string.no_program_information); } else { mDetailsContent.mTitle = title; } } private void createImageUris(@Nullable Channel channel) { mDetailsContent.mLogoImageUri = null; mDetailsContent.mBackgroundImageUri = null; mDetailsContent.mUsingChannelLogo = false; if (!TextUtils.isEmpty(mPosterArtUri) && !TextUtils.isEmpty(mThumbnailUri)) { mDetailsContent.mLogoImageUri = mPosterArtUri; mDetailsContent.mBackgroundImageUri = mThumbnailUri; } else if (!TextUtils.isEmpty(mPosterArtUri)) { // thumbnailUri is empty mDetailsContent.mLogoImageUri = mPosterArtUri; mDetailsContent.mBackgroundImageUri = mPosterArtUri; } else if (!TextUtils.isEmpty(mThumbnailUri)) { // posterArtUri is empty mDetailsContent.mLogoImageUri = mThumbnailUri; mDetailsContent.mBackgroundImageUri = mThumbnailUri; } if (TextUtils.isEmpty(mDetailsContent.mLogoImageUri) && channel != null) { String channelLogoUri = TvContract.buildChannelLogoUri(channel.getId()).toString(); mDetailsContent.mLogoImageUri = channelLogoUri; mDetailsContent.mBackgroundImageUri = channelLogoUri; mDetailsContent.mUsingChannelLogo = true; } } /** Builds details content. */ public DetailsContent build(Context context) { Channel channel = TvSingletons.getSingletons(context) .getChannelDataManager() .getChannel(mChannelId); if (mDetailsContent.mTitle == null) { createStyledTitle(context, channel); } if (mDetailsContent.mBackgroundImageUri == null && mDetailsContent.mLogoImageUri == null) { createImageUris(channel); } DetailsContent detailsContent = new DetailsContent(); detailsContent.copyFrom(mDetailsContent); return detailsContent; } } }