1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.tv.data; 18 19 import android.content.Context; 20 import android.media.tv.TvContentRating; 21 import android.support.annotation.Nullable; 22 import android.text.TextUtils; 23 import com.android.tv.R; 24 import com.google.common.collect.ImmutableList; 25 import java.util.Comparator; 26 import java.util.Objects; 27 28 /** 29 * Base class for {@link com.android.tv.data.Program} and {@link 30 * com.android.tv.dvr.data.RecordedProgram}. 31 */ 32 public abstract class BaseProgram { 33 /** 34 * Comparator used to compare {@link BaseProgram} according to its season and episodes number. 35 * If a program's season or episode number is null, it will be consider "smaller" than programs 36 * with season or episode numbers. 37 */ 38 public static final Comparator<BaseProgram> EPISODE_COMPARATOR = new EpisodeComparator(false); 39 40 /** 41 * Comparator used to compare {@link BaseProgram} according to its season and episodes number 42 * with season numbers in a reversed order. If a program's season or episode number is null, it 43 * will be consider "smaller" than programs with season or episode numbers. 44 */ 45 public static final Comparator<BaseProgram> SEASON_REVERSED_EPISODE_COMPARATOR = 46 new EpisodeComparator(true); 47 48 public static final String COLUMN_SERIES_ID = "series_id"; 49 50 public static final String COLUMN_STATE = "state"; 51 52 private static class EpisodeComparator implements Comparator<BaseProgram> { 53 private final boolean mReversedSeason; 54 EpisodeComparator(boolean reversedSeason)55 EpisodeComparator(boolean reversedSeason) { 56 mReversedSeason = reversedSeason; 57 } 58 59 @Override compare(BaseProgram lhs, BaseProgram rhs)60 public int compare(BaseProgram lhs, BaseProgram rhs) { 61 if (lhs == rhs) { 62 return 0; 63 } 64 int seasonNumberCompare = numberCompare(lhs.getSeasonNumber(), rhs.getSeasonNumber()); 65 if (seasonNumberCompare != 0) { 66 return mReversedSeason ? -seasonNumberCompare : seasonNumberCompare; 67 } else { 68 return numberCompare(lhs.getEpisodeNumber(), rhs.getEpisodeNumber()); 69 } 70 } 71 } 72 73 /** Compares two strings represent season numbers or episode numbers of programs. */ numberCompare(String s1, String s2)74 public static int numberCompare(String s1, String s2) { 75 if (Objects.equals(s1, s2)) { 76 return 0; 77 } else if (s1 == null) { 78 return -1; 79 } else if (s2 == null) { 80 return 1; 81 } else if (s1.equals(s2)) { 82 return 0; 83 } 84 try { 85 return Integer.compare(Integer.parseInt(s1), Integer.parseInt(s2)); 86 } catch (NumberFormatException e) { 87 return s1.compareTo(s2); 88 } 89 } 90 91 /** Returns ID of the program. */ getId()92 public abstract long getId(); 93 94 /** Returns the title of the program. */ getTitle()95 public abstract String getTitle(); 96 97 /** Returns the episode title. */ getEpisodeTitle()98 public abstract String getEpisodeTitle(); 99 100 /** Returns the displayed title of the program episode. */ 101 @Nullable getEpisodeDisplayTitle(Context context)102 public String getEpisodeDisplayTitle(Context context) { 103 String episodeNumber = getEpisodeNumber(); 104 String episodeTitle = getEpisodeTitle(); 105 if (!TextUtils.isEmpty(episodeNumber)) { 106 episodeTitle = episodeTitle == null ? "" : episodeTitle; 107 String seasonNumber = getSeasonNumber(); 108 if (TextUtils.isEmpty(seasonNumber) || TextUtils.equals(seasonNumber, "0")) { 109 // Do not show "S0: ". 110 return context.getResources() 111 .getString( 112 R.string.display_episode_title_format_no_season_number, 113 episodeNumber, 114 episodeTitle); 115 } else { 116 return context.getResources() 117 .getString( 118 R.string.display_episode_title_format, 119 seasonNumber, 120 episodeNumber, 121 episodeTitle); 122 } 123 } 124 return episodeTitle; 125 } 126 127 /** 128 * Returns the content description of the program episode, suitable for being spoken by an 129 * accessibility service. 130 */ getEpisodeContentDescription(Context context)131 public String getEpisodeContentDescription(Context context) { 132 String episodeNumber = getEpisodeNumber(); 133 String episodeTitle = getEpisodeTitle(); 134 if (!TextUtils.isEmpty(episodeNumber)) { 135 episodeTitle = episodeTitle == null ? "" : episodeTitle; 136 String seasonNumber = getSeasonNumber(); 137 if (TextUtils.isEmpty(seasonNumber) || TextUtils.equals(seasonNumber, "0")) { 138 // Do not list season if it is empty or 0 139 return context.getResources() 140 .getString( 141 R.string.content_description_episode_format_no_season_number, 142 episodeNumber, 143 episodeTitle); 144 } else { 145 return context.getResources() 146 .getString( 147 R.string.content_description_episode_format, 148 seasonNumber, 149 episodeNumber, 150 episodeTitle); 151 } 152 } 153 return episodeTitle; 154 } 155 156 /** Returns the description of the program. */ getDescription()157 public abstract String getDescription(); 158 159 /** Returns the long description of the program. */ getLongDescription()160 public abstract String getLongDescription(); 161 162 /** Returns the start time of the program in Milliseconds. */ getStartTimeUtcMillis()163 public abstract long getStartTimeUtcMillis(); 164 165 /** Returns the end time of the program in Milliseconds. */ getEndTimeUtcMillis()166 public abstract long getEndTimeUtcMillis(); 167 168 /** Returns the duration of the program in Milliseconds. */ getDurationMillis()169 public abstract long getDurationMillis(); 170 171 /** Returns the series ID. */ 172 @Nullable getSeriesId()173 public abstract String getSeriesId(); 174 175 /** Returns the season number. */ getSeasonNumber()176 public abstract String getSeasonNumber(); 177 178 /** Returns the episode number. */ getEpisodeNumber()179 public abstract String getEpisodeNumber(); 180 181 /** Returns URI of the program's poster. */ getPosterArtUri()182 public abstract String getPosterArtUri(); 183 184 /** Returns URI of the program's thumbnail. */ getThumbnailUri()185 public abstract String getThumbnailUri(); 186 187 /** Returns the array of the ID's of the canonical genres. */ getCanonicalGenreIds()188 public abstract int[] getCanonicalGenreIds(); 189 190 /** Returns the array of content ratings. */ getContentRatings()191 public abstract ImmutableList<TvContentRating> getContentRatings(); 192 193 /** Returns channel's ID of the program. */ getChannelId()194 public abstract long getChannelId(); 195 196 /** Returns if the program is valid. */ isValid()197 public abstract boolean isValid(); 198 199 /** Checks whether the program is episodic or not. */ isEpisodic()200 public boolean isEpisodic() { 201 return getSeriesId() != null; 202 } 203 204 /** Generates the series ID for the other inputs than the tuner TV input. */ generateSeriesId(String packageName, String title)205 public static String generateSeriesId(String packageName, String title) { 206 return packageName + "/" + title; 207 } 208 } 209