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 17package com.android.tv.common.recording; 18 19import static android.media.tv.TvContract.RecordedPrograms; 20 21import android.content.ContentUris; 22import android.content.ContentValues; 23import android.content.Context; 24import android.database.Cursor; 25import android.media.tv.TvContract; 26import android.net.Uri; 27import android.support.annotation.Nullable; 28import android.text.TextUtils; 29 30import com.android.tv.common.R; 31 32import java.util.Arrays; 33import java.util.Comparator; 34import java.util.Objects; 35 36/** 37 * Immutable instance of {@link android.media.tv.TvContract.RecordedPrograms}. 38 */ 39public class RecordedProgram { 40 public static final int ID_NOT_SET = -1; 41 42 public final static String[] PROJECTION = { 43 // These are in exactly the order listed in RecordedPrograms 44 RecordedPrograms._ID, 45 RecordedPrograms.COLUMN_INPUT_ID, 46 RecordedPrograms.COLUMN_CHANNEL_ID, 47 RecordedPrograms.COLUMN_TITLE, 48 RecordedPrograms.COLUMN_SEASON_DISPLAY_NUMBER, 49 RecordedPrograms.COLUMN_SEASON_TITLE, 50 RecordedPrograms.COLUMN_EPISODE_DISPLAY_NUMBER, 51 RecordedPrograms.COLUMN_EPISODE_TITLE, 52 RecordedPrograms.COLUMN_START_TIME_UTC_MILLIS, 53 RecordedPrograms.COLUMN_END_TIME_UTC_MILLIS, 54 RecordedPrograms.COLUMN_BROADCAST_GENRE, 55 RecordedPrograms.COLUMN_CANONICAL_GENRE, 56 RecordedPrograms.COLUMN_SHORT_DESCRIPTION, 57 RecordedPrograms.COLUMN_LONG_DESCRIPTION, 58 RecordedPrograms.COLUMN_VIDEO_WIDTH, 59 RecordedPrograms.COLUMN_VIDEO_HEIGHT, 60 RecordedPrograms.COLUMN_AUDIO_LANGUAGE, 61 RecordedPrograms.COLUMN_CONTENT_RATING, 62 RecordedPrograms.COLUMN_POSTER_ART_URI, 63 RecordedPrograms.COLUMN_THUMBNAIL_URI, 64 RecordedPrograms.COLUMN_SEARCHABLE, 65 RecordedPrograms.COLUMN_RECORDING_DATA_URI, 66 RecordedPrograms.COLUMN_RECORDING_DATA_BYTES, 67 RecordedPrograms.COLUMN_RECORDING_DURATION_MILLIS, 68 RecordedPrograms.COLUMN_RECORDING_EXPIRE_TIME_UTC_MILLIS, 69 RecordedPrograms.COLUMN_INTERNAL_PROVIDER_DATA, 70 RecordedPrograms.COLUMN_INTERNAL_PROVIDER_FLAG1, 71 RecordedPrograms.COLUMN_INTERNAL_PROVIDER_FLAG2, 72 RecordedPrograms.COLUMN_INTERNAL_PROVIDER_FLAG3, 73 RecordedPrograms.COLUMN_INTERNAL_PROVIDER_FLAG4, 74 RecordedPrograms.COLUMN_VERSION_NUMBER, 75 }; 76 77 public static final RecordedProgram fromCursor(Cursor cursor) { 78 int index = 0; 79 return builder() 80 .setId(cursor.getLong(index++)) 81 .setInputId(cursor.getString(index++)) 82 .setChannelId(cursor.getLong(index++)) 83 .setTitle(cursor.getString(index++)) 84 .setSeasonNumber(cursor.getString(index++)) 85 .setSeasonTitle(cursor.getString(index++)) 86 .setEpisodeNumber(cursor.getString(index++)) 87 .setEpisodeTitle(cursor.getString(index++)) 88 .setStartTimeUtcMillis(cursor.getLong(index++)) 89 .setEndTimeUtcMillis(cursor.getLong(index++)) 90 .setBroadcastGenres(cursor.getString(index++)) 91 .setCanonicalGenres(cursor.getString(index++)) 92 .setShortDescription(cursor.getString(index++)) 93 .setLongDescription(cursor.getString(index++)) 94 .setVideoWidth(cursor.getInt(index++)) 95 .setVideoHeight(cursor.getInt(index++)) 96 .setAudioLanguage(cursor.getString(index++)) 97 .setContentRating(cursor.getString(index++)) 98 .setPosterArt(cursor.getString(index++)) 99 .setThumbnail(cursor.getString(index++)) 100 .setSearchable(cursor.getInt(index++) == 1) 101 .setDataUri(cursor.getString(index++)) 102 .setDataBytes(cursor.getLong(index++)) 103 .setDurationMillis(cursor.getLong(index++)) 104 .setExpireTimeUtcMillis(cursor.getLong(index++)) 105 .setInternalProviderData(cursor.getBlob(index++)) 106 .setInternalProviderFlag1(cursor.getInt(index++)) 107 .setInternalProviderFlag2(cursor.getInt(index++)) 108 .setInternalProviderFlag3(cursor.getInt(index++)) 109 .setInternalProviderFlag4(cursor.getInt(index++)) 110 .setVersionNumber(cursor.getInt(index++)) 111 .build(); 112 } 113 114 public static ContentValues toValues(RecordedProgram recordedProgram) { 115 ContentValues values = new ContentValues(); 116 if (recordedProgram.mId != ID_NOT_SET) { 117 values.put(RecordedPrograms._ID, recordedProgram.mId); 118 } 119 values.put(RecordedPrograms.COLUMN_INPUT_ID, recordedProgram.mInputId); 120 values.put(RecordedPrograms.COLUMN_CHANNEL_ID, recordedProgram.mChannelId); 121 values.put(RecordedPrograms.COLUMN_TITLE, recordedProgram.mTitle); 122 values.put(RecordedPrograms.COLUMN_SEASON_DISPLAY_NUMBER, recordedProgram.mSeasonNumber); 123 values.put(RecordedPrograms.COLUMN_SEASON_TITLE, recordedProgram.mSeasonTitle); 124 values.put(RecordedPrograms.COLUMN_EPISODE_DISPLAY_NUMBER, recordedProgram.mEpisodeNumber); 125 values.put(RecordedPrograms.COLUMN_EPISODE_TITLE, recordedProgram.mTitle); 126 values.put(RecordedPrograms.COLUMN_START_TIME_UTC_MILLIS, 127 recordedProgram.mStartTimeUtcMillis); 128 values.put(RecordedPrograms.COLUMN_END_TIME_UTC_MILLIS, recordedProgram.mEndTimeUtcMillis); 129 values.put(RecordedPrograms.COLUMN_BROADCAST_GENRE, 130 safeEncode(recordedProgram.mBroadcastGenres)); 131 values.put(RecordedPrograms.COLUMN_CANONICAL_GENRE, 132 safeEncode(recordedProgram.mCanonicalGenres)); 133 values.put(RecordedPrograms.COLUMN_SHORT_DESCRIPTION, recordedProgram.mShortDescription); 134 values.put(RecordedPrograms.COLUMN_LONG_DESCRIPTION, recordedProgram.mLongDescription); 135 if (recordedProgram.mVideoWidth == 0) { 136 values.putNull(RecordedPrograms.COLUMN_VIDEO_WIDTH); 137 } else { 138 values.put(RecordedPrograms.COLUMN_VIDEO_WIDTH, recordedProgram.mVideoWidth); 139 } 140 if (recordedProgram.mVideoHeight == 0) { 141 values.putNull(RecordedPrograms.COLUMN_VIDEO_HEIGHT); 142 } else { 143 values.put(RecordedPrograms.COLUMN_VIDEO_HEIGHT, recordedProgram.mVideoHeight); 144 } 145 values.put(RecordedPrograms.COLUMN_AUDIO_LANGUAGE, recordedProgram.mAudioLanguage); 146 values.put(RecordedPrograms.COLUMN_CONTENT_RATING, recordedProgram.mContentRating); 147 values.put(RecordedPrograms.COLUMN_POSTER_ART_URI, 148 safeToString(recordedProgram.mPosterArt)); 149 values.put(RecordedPrograms.COLUMN_THUMBNAIL_URI, safeToString(recordedProgram.mThumbnail)); 150 values.put(RecordedPrograms.COLUMN_SEARCHABLE, recordedProgram.mSearchable ? 1 : 0); 151 values.put(RecordedPrograms.COLUMN_RECORDING_DATA_URI, 152 safeToString(recordedProgram.mDataUri)); 153 values.put(RecordedPrograms.COLUMN_RECORDING_DATA_BYTES, recordedProgram.mDataBytes); 154 values.put(RecordedPrograms.COLUMN_RECORDING_DURATION_MILLIS, 155 recordedProgram.mDurationMillis); 156 values.put(RecordedPrograms.COLUMN_RECORDING_EXPIRE_TIME_UTC_MILLIS, 157 recordedProgram.mExpireTimeUtcMillis); 158 values.put(RecordedPrograms.COLUMN_INTERNAL_PROVIDER_DATA, 159 recordedProgram.mInternalProviderData); 160 values.put(RecordedPrograms.COLUMN_INTERNAL_PROVIDER_FLAG1, 161 recordedProgram.mInternalProviderFlag1); 162 values.put(RecordedPrograms.COLUMN_INTERNAL_PROVIDER_FLAG2, 163 recordedProgram.mInternalProviderFlag2); 164 values.put(RecordedPrograms.COLUMN_INTERNAL_PROVIDER_FLAG3, 165 recordedProgram.mInternalProviderFlag3); 166 values.put(RecordedPrograms.COLUMN_INTERNAL_PROVIDER_FLAG4, 167 recordedProgram.mInternalProviderFlag4); 168 values.put(RecordedPrograms.COLUMN_VERSION_NUMBER, recordedProgram.mVersionNumber); 169 return values; 170 } 171 172 public static class Builder{ 173 private long mId = ID_NOT_SET; 174 private String mInputId; 175 private long mChannelId; 176 private String mTitle; 177 private String mSeasonNumber; 178 private String mSeasonTitle; 179 private String mEpisodeNumber; 180 private String mEpisodeTitle; 181 private long mStartTimeUtcMillis; 182 private long mEndTimeUtcMillis; 183 private String[] mBroadcastGenres; 184 private String[] mCanonicalGenres; 185 private String mShortDescription; 186 private String mLongDescription; 187 private int mVideoWidth; 188 private int mVideoHeight; 189 private String mAudioLanguage; 190 private String mContentRating; 191 private Uri mPosterArt; 192 private Uri mThumbnail; 193 private boolean mSearchable = true; 194 private Uri mDataUri; 195 private long mDataBytes; 196 private long mDurationMillis; 197 private long mExpireTimeUtcMillis; 198 private byte[] mInternalProviderData; 199 private int mInternalProviderFlag1; 200 private int mInternalProviderFlag2; 201 private int mInternalProviderFlag3; 202 private int mInternalProviderFlag4; 203 private int mVersionNumber; 204 205 public Builder setId(long id) { 206 mId = id; 207 return this; 208 } 209 210 public Builder setInputId(String inputId) { 211 mInputId = inputId; 212 return this; 213 } 214 215 public Builder setChannelId(long channelId) { 216 mChannelId = channelId; 217 return this; 218 } 219 220 public Builder setTitle(String title) { 221 mTitle = title; 222 return this; 223 } 224 225 public Builder setSeasonNumber(String seasonNumber) { 226 mSeasonNumber = seasonNumber; 227 return this; 228 } 229 230 public Builder setSeasonTitle(String seasonTitle) { 231 mSeasonTitle = seasonTitle; 232 return this; 233 } 234 235 public Builder setEpisodeNumber(String episodeNumber) { 236 mEpisodeNumber = episodeNumber; 237 return this; 238 } 239 240 public Builder setEpisodeTitle(String episodeTitle) { 241 mEpisodeTitle = episodeTitle; 242 return this; 243 } 244 245 public Builder setStartTimeUtcMillis(long startTimeUtcMillis) { 246 mStartTimeUtcMillis = startTimeUtcMillis; 247 return this; 248 } 249 250 public Builder setEndTimeUtcMillis(long endTimeUtcMillis) { 251 mEndTimeUtcMillis = endTimeUtcMillis; 252 return this; 253 } 254 255 public Builder setBroadcastGenres(String broadcastGenres) { 256 if (TextUtils.isEmpty(broadcastGenres)) { 257 mBroadcastGenres = null; 258 return this; 259 } 260 return setBroadcastGenres(TvContract.Programs.Genres.decode(broadcastGenres)); 261 } 262 263 private Builder setBroadcastGenres(String[] broadcastGenres) { 264 mBroadcastGenres = broadcastGenres; 265 return this; 266 } 267 268 public Builder setCanonicalGenres(String canonicalGenres) { 269 if (TextUtils.isEmpty(canonicalGenres)) { 270 mCanonicalGenres = null; 271 return this; 272 } 273 return setCanonicalGenres(TvContract.Programs.Genres.decode(canonicalGenres)); 274 } 275 276 private Builder setCanonicalGenres(String[] canonicalGenres) { 277 mCanonicalGenres = canonicalGenres; 278 return this; 279 } 280 281 public Builder setShortDescription(String shortDescription) { 282 mShortDescription = shortDescription; 283 return this; 284 } 285 286 public Builder setLongDescription(String longDescription) { 287 mLongDescription = longDescription; 288 return this; 289 } 290 291 public Builder setVideoWidth(int videoWidth) { 292 mVideoWidth = videoWidth; 293 return this; 294 } 295 296 public Builder setVideoHeight(int videoHeight) { 297 mVideoHeight = videoHeight; 298 return this; 299 } 300 301 public Builder setAudioLanguage(String audioLanguage) { 302 mAudioLanguage = audioLanguage; 303 return this; 304 } 305 306 public Builder setContentRating(String contentRating) { 307 mContentRating = contentRating; 308 return this; 309 } 310 311 private Uri toUri(String uriString) { 312 try { 313 return uriString == null ? null : Uri.parse(uriString); 314 } catch (Exception e) { 315 return null; 316 } 317 } 318 319 public Builder setPosterArt(String posterArtUri) { 320 return setPosterArt(toUri(posterArtUri)); 321 } 322 323 public Builder setPosterArt(Uri posterArt) { 324 mPosterArt = posterArt; 325 return this; 326 } 327 328 public Builder setThumbnail(String thumbnailUri) { 329 return setThumbnail(toUri(thumbnailUri)); 330 } 331 332 public Builder setThumbnail(Uri thumbnail) { 333 mThumbnail = thumbnail; 334 return this; 335 } 336 337 public Builder setSearchable(boolean searchable) { 338 mSearchable = searchable; 339 return this; 340 } 341 342 public Builder setDataUri(String dataUri) { 343 return setDataUri(toUri(dataUri)); 344 } 345 346 public Builder setDataUri(Uri dataUri) { 347 mDataUri = dataUri; 348 return this; 349 } 350 351 public Builder setDataBytes(long dataBytes) { 352 mDataBytes = dataBytes; 353 return this; 354 } 355 356 public Builder setDurationMillis(long durationMillis) { 357 mDurationMillis = durationMillis; 358 return this; 359 } 360 361 public Builder setExpireTimeUtcMillis(long expireTimeUtcMillis) { 362 mExpireTimeUtcMillis = expireTimeUtcMillis; 363 return this; 364 } 365 366 public Builder setInternalProviderData(byte[] internalProviderData) { 367 mInternalProviderData = internalProviderData; 368 return this; 369 } 370 371 public Builder setInternalProviderFlag1(int internalProviderFlag1) { 372 mInternalProviderFlag1 = internalProviderFlag1; 373 return this; 374 } 375 376 public Builder setInternalProviderFlag2(int internalProviderFlag2) { 377 mInternalProviderFlag2 = internalProviderFlag2; 378 return this; 379 } 380 381 public Builder setInternalProviderFlag3(int internalProviderFlag3) { 382 mInternalProviderFlag3 = internalProviderFlag3; 383 return this; 384 } 385 386 public Builder setInternalProviderFlag4(int internalProviderFlag4) { 387 mInternalProviderFlag4 = internalProviderFlag4; 388 return this; 389 } 390 391 public Builder setVersionNumber(int versionNumber) { 392 mVersionNumber = versionNumber; 393 return this; 394 } 395 396 public RecordedProgram build() { 397 return new RecordedProgram(mId, mInputId, mChannelId, mTitle, mSeasonNumber, 398 mSeasonTitle, mEpisodeNumber, mEpisodeTitle, mStartTimeUtcMillis, 399 mEndTimeUtcMillis, mBroadcastGenres, mCanonicalGenres, mShortDescription, 400 mLongDescription, mVideoWidth, mVideoHeight, mAudioLanguage, mContentRating, 401 mPosterArt, mThumbnail, mSearchable, mDataUri, mDataBytes, mDurationMillis, 402 mExpireTimeUtcMillis, mInternalProviderData, mInternalProviderFlag1, 403 mInternalProviderFlag2, mInternalProviderFlag3, mInternalProviderFlag4, 404 mVersionNumber); 405 } 406 } 407 408 public static Builder builder() { return new Builder(); } 409 410 public static Builder buildFrom(RecordedProgram orig) { 411 return builder() 412 .setId(orig.getId()) 413 .setInputId(orig.getInputId()) 414 .setChannelId(orig.getChannelId()) 415 .setTitle(orig.getTitle()) 416 .setSeasonNumber(orig.getSeasonNumber()) 417 .setSeasonTitle(orig.getSeasonTitle()) 418 .setEpisodeNumber(orig.getEpisodeNumber()) 419 .setEpisodeTitle(orig.getEpisodeTitle()) 420 .setStartTimeUtcMillis(orig.getStartTimeUtcMillis()) 421 .setEndTimeUtcMillis(orig.getEndTimeUtcMillis()) 422 .setBroadcastGenres(orig.getBroadcastGenres()) 423 .setCanonicalGenres(orig.getCanonicalGenres()) 424 .setShortDescription(orig.getShortDescription()) 425 .setLongDescription(orig.getLongDescription()) 426 .setVideoWidth(orig.getVideoWidth()) 427 .setVideoHeight(orig.getVideoHeight()) 428 .setAudioLanguage(orig.getAudioLanguage()) 429 .setContentRating(orig.getContentRating()) 430 .setPosterArt(orig.getPosterArt()) 431 .setThumbnail(orig.getThumbnail()) 432 .setSearchable(orig.isSearchable()) 433 .setInternalProviderData(orig.getInternalProviderData()) 434 .setInternalProviderFlag1(orig.getInternalProviderFlag1()) 435 .setInternalProviderFlag2(orig.getInternalProviderFlag2()) 436 .setInternalProviderFlag3(orig.getInternalProviderFlag3()) 437 .setInternalProviderFlag4(orig.getInternalProviderFlag4()) 438 .setVersionNumber(orig.getVersionNumber()); 439 } 440 441 public static final Comparator<RecordedProgram> START_TIME_THEN_ID_COMPARATOR 442 = new Comparator<RecordedProgram>() { 443 @Override 444 public int compare(RecordedProgram lhs, RecordedProgram rhs) { 445 int res = Long.compare(lhs.getStartTimeUtcMillis(), rhs.getStartTimeUtcMillis()); 446 if (res != 0) { 447 return res; 448 } 449 return Long.compare(lhs.mId, rhs.mId); 450 } 451 }; 452 453 private final long mId; 454 private final String mInputId; 455 private final long mChannelId; 456 private final String mTitle; 457 private final String mSeasonNumber; 458 private final String mSeasonTitle; 459 private final String mEpisodeNumber; 460 private final String mEpisodeTitle; 461 private final long mStartTimeUtcMillis; 462 private final long mEndTimeUtcMillis; 463 private final String[] mBroadcastGenres; 464 private final String[] mCanonicalGenres; 465 private final String mShortDescription; 466 private final String mLongDescription; 467 private final int mVideoWidth; 468 private final int mVideoHeight; 469 private final String mAudioLanguage; 470 private final String mContentRating; 471 private final Uri mPosterArt; 472 private final Uri mThumbnail; 473 private final boolean mSearchable; 474 private final Uri mDataUri; 475 private final long mDataBytes; 476 private final long mDurationMillis; 477 private final long mExpireTimeUtcMillis; 478 private final byte[] mInternalProviderData; 479 private final int mInternalProviderFlag1; 480 private final int mInternalProviderFlag2; 481 private final int mInternalProviderFlag3; 482 private final int mInternalProviderFlag4; 483 private final int mVersionNumber; 484 485 private RecordedProgram(long id, String inputId, long channelId, String title, 486 String seasonNumber, String seasonTitle, String episodeNumber, String episodeTitle, 487 long startTimeUtcMillis, long endTimeUtcMillis, String[] broadcastGenres, 488 String[] canonicalGenres, String shortDescription, String longDescription, 489 int videoWidth, int videoHeight, String audioLanguage, String contentRating, 490 Uri posterArt, Uri thumbnail, boolean searchable, Uri dataUri, long dataBytes, 491 long durationMillis, long expireTimeUtcMillis, byte[] internalProviderData, 492 int internalProviderFlag1, int internalProviderFlag2, int internalProviderFlag3, 493 int internalProviderFlag4, int versionNumber) { 494 mId = id; 495 mInputId = inputId; 496 mChannelId = channelId; 497 mTitle = title; 498 mSeasonNumber = seasonNumber; 499 mSeasonTitle = seasonTitle; 500 mEpisodeNumber = episodeNumber; 501 mEpisodeTitle = episodeTitle; 502 mStartTimeUtcMillis = startTimeUtcMillis; 503 mEndTimeUtcMillis = endTimeUtcMillis; 504 mBroadcastGenres = broadcastGenres; 505 mCanonicalGenres = canonicalGenres; 506 mShortDescription = shortDescription; 507 mLongDescription = longDescription; 508 mVideoWidth = videoWidth; 509 mVideoHeight = videoHeight; 510 511 mAudioLanguage = audioLanguage; 512 mContentRating = contentRating; 513 mPosterArt = posterArt; 514 mThumbnail = thumbnail; 515 mSearchable = searchable; 516 mDataUri = dataUri; 517 mDataBytes = dataBytes; 518 mDurationMillis = durationMillis; 519 mExpireTimeUtcMillis = expireTimeUtcMillis; 520 mInternalProviderData = internalProviderData; 521 mInternalProviderFlag1 = internalProviderFlag1; 522 mInternalProviderFlag2 = internalProviderFlag2; 523 mInternalProviderFlag3 = internalProviderFlag3; 524 mInternalProviderFlag4 = internalProviderFlag4; 525 mVersionNumber = versionNumber; 526 } 527 528 public String getAudioLanguage() { 529 return mAudioLanguage; 530 } 531 532 public String[] getBroadcastGenres() { 533 return mBroadcastGenres; 534 } 535 536 public String[] getCanonicalGenres() { 537 return mCanonicalGenres; 538 } 539 540 public long getChannelId() { 541 return mChannelId; 542 } 543 544 public String getContentRating() { 545 return mContentRating; 546 } 547 548 public Uri getDataUri() { 549 return mDataUri; 550 } 551 552 public long getDataBytes() { 553 return mDataBytes; 554 } 555 556 public long getDurationMillis() { 557 return mDurationMillis; 558 } 559 560 public long getEndTimeUtcMillis() { 561 return mEndTimeUtcMillis; 562 } 563 564 public String getEpisodeNumber() { 565 return mEpisodeNumber; 566 } 567 568 public String getEpisodeTitle() { 569 return mEpisodeTitle; 570 } 571 572 public String getEpisodeDisplayTitle(Context context) { 573 if (!TextUtils.isEmpty(mSeasonNumber) && !TextUtils.isEmpty(mEpisodeNumber) 574 && !TextUtils.isEmpty(mEpisodeTitle)) { 575 return String.format(context.getResources().getString(R.string.episode_format), 576 mSeasonNumber, mEpisodeNumber, mEpisodeTitle); 577 } 578 return mEpisodeTitle; 579 } 580 581 public long getExpireTimeUtcMillis() { 582 return mExpireTimeUtcMillis; 583 } 584 585 public long getId() { 586 return mId; 587 } 588 589 public String getInputId() { 590 return mInputId; 591 } 592 593 public byte[] getInternalProviderData() { 594 return mInternalProviderData; 595 } 596 597 public int getInternalProviderFlag1() { 598 return mInternalProviderFlag1; 599 } 600 601 public int getInternalProviderFlag2() { 602 return mInternalProviderFlag2; 603 } 604 605 public int getInternalProviderFlag3() { 606 return mInternalProviderFlag3; 607 } 608 609 public int getInternalProviderFlag4() { 610 return mInternalProviderFlag4; 611 } 612 613 public String getLongDescription() { 614 return mLongDescription; 615 } 616 617 public Uri getPosterArt() { 618 return mPosterArt; 619 } 620 621 public boolean isSearchable() { 622 return mSearchable; 623 } 624 625 public String getSeasonNumber() { 626 return mSeasonNumber; 627 } 628 629 public String getSeasonTitle() { 630 return mSeasonTitle; 631 } 632 633 public String getShortDescription() { 634 return mShortDescription; 635 } 636 637 public long getStartTimeUtcMillis() { 638 return mStartTimeUtcMillis; 639 } 640 641 public Uri getThumbnail() { 642 return mThumbnail; 643 } 644 645 public String getTitle() { 646 return mTitle; 647 } 648 649 public Uri getUri() { 650 return ContentUris.withAppendedId(RecordedPrograms.CONTENT_URI, mId); 651 } 652 653 public int getVersionNumber() { 654 return mVersionNumber; 655 } 656 657 public int getVideoHeight() { 658 return mVideoHeight; 659 } 660 661 public int getVideoWidth() { 662 return mVideoWidth; 663 } 664 665 /** 666 * Compares everything except {@link #getInternalProviderData()} 667 */ 668 @Override 669 public boolean equals(Object o) { 670 if (this == o) return true; 671 if (o == null || getClass() != o.getClass()) return false; 672 RecordedProgram that = (RecordedProgram) o; 673 return Objects.equals(mId, that.mId) && 674 Objects.equals(mChannelId, that.mChannelId) && 675 Objects.equals(mSeasonNumber, that.mSeasonNumber) && 676 Objects.equals(mSeasonTitle, that.mSeasonTitle) && 677 Objects.equals(mEpisodeNumber, that.mEpisodeNumber) && 678 Objects.equals(mStartTimeUtcMillis, that.mStartTimeUtcMillis) && 679 Objects.equals(mEndTimeUtcMillis, that.mEndTimeUtcMillis) && 680 Objects.equals(mVideoWidth, that.mVideoWidth) && 681 Objects.equals(mVideoHeight, that.mVideoHeight) && 682 Objects.equals(mSearchable, that.mSearchable) && 683 Objects.equals(mDataBytes, that.mDataBytes) && 684 Objects.equals(mDurationMillis, that.mDurationMillis) && 685 Objects.equals(mExpireTimeUtcMillis, that.mExpireTimeUtcMillis) && 686 Objects.equals(mInternalProviderFlag1, that.mInternalProviderFlag1) && 687 Objects.equals(mInternalProviderFlag2, that.mInternalProviderFlag2) && 688 Objects.equals(mInternalProviderFlag3, that.mInternalProviderFlag3) && 689 Objects.equals(mInternalProviderFlag4, that.mInternalProviderFlag4) && 690 Objects.equals(mVersionNumber, that.mVersionNumber) && 691 Objects.equals(mTitle, that.mTitle) && 692 Objects.equals(mEpisodeTitle, that.mEpisodeTitle) && 693 Arrays.equals(mBroadcastGenres, that.mBroadcastGenres) && 694 Arrays.equals(mCanonicalGenres, that.mCanonicalGenres) && 695 Objects.equals(mShortDescription, that.mShortDescription) && 696 Objects.equals(mLongDescription, that.mLongDescription) && 697 Objects.equals(mAudioLanguage, that.mAudioLanguage) && 698 Objects.equals(mContentRating, that.mContentRating) && 699 Objects.equals(mPosterArt, that.mPosterArt) && 700 Objects.equals(mThumbnail, that.mThumbnail); 701 } 702 703 /** 704 * Hashes based on the ID. 705 */ 706 @Override 707 public int hashCode() { 708 return Objects.hash(mId); 709 } 710 711 @Override 712 public String toString() { 713 return "RecordedProgram" 714 + "[" + mId + 715 "]{ mInputId=" + mInputId + 716 ", mChannelId='" + mChannelId + '\'' + 717 ", mTitle='" + mTitle + '\'' + 718 ", mEpisodeNumber=" + mEpisodeNumber + 719 ", mEpisodeTitle='" + mEpisodeTitle + '\'' + 720 ", mStartTimeUtcMillis=" + mStartTimeUtcMillis + 721 ", mEndTimeUtcMillis=" + mEndTimeUtcMillis + 722 ", mBroadcastGenres=" + 723 (mBroadcastGenres != null ? Arrays.toString(mBroadcastGenres) : "null") + 724 ", mCanonicalGenres=" + 725 (mCanonicalGenres != null ? Arrays.toString(mCanonicalGenres) : "null") + 726 ", mShortDescription='" + mShortDescription + '\'' + 727 ", mLongDescription='" + mLongDescription + '\'' + 728 ", mVideoHeight=" + mVideoHeight + 729 ", mVideoWidth=" + mVideoWidth + 730 ", mAudioLanguage='" + mAudioLanguage + '\'' + 731 ", mContentRating='" + mContentRating + '\'' + 732 ", mPosterArt=" + mPosterArt + 733 ", mThumbnail=" + mThumbnail + 734 ", mSearchable=" + mSearchable + 735 ", mDataUri=" + mDataUri + 736 ", mDataBytes=" + mDataBytes + 737 ", mDurationMillis=" + mDurationMillis + 738 ", mExpireTimeUtcMillis=" + mExpireTimeUtcMillis + 739 ", mInternalProviderData.length=" + 740 (mInternalProviderData == null ? "null" : mInternalProviderData.length) + 741 ", mInternalProviderFlag1=" + mInternalProviderFlag1 + 742 ", mInternalProviderFlag2=" + mInternalProviderFlag2 + 743 ", mInternalProviderFlag3=" + mInternalProviderFlag3 + 744 ", mInternalProviderFlag4=" + mInternalProviderFlag4 + 745 ", mSeasonNumber=" + mSeasonNumber + 746 ", mSeasonTitle=" + mSeasonTitle + 747 ", mVersionNumber=" + mVersionNumber + 748 '}'; 749 } 750 751 @Nullable 752 private static String safeToString(@Nullable Object o) { 753 return o == null ? null : o.toString(); 754 } 755 756 @Nullable 757 private static String safeEncode(@Nullable String[] genres) { 758 return genres == null ? null : TvContract.Programs.Genres.encode(genres); 759 } 760} 761