1/* 2 * Copyright 2018 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 */ 16package androidx.tvprovider.media.tv; 17 18import static org.junit.Assert.assertEquals; 19import static org.junit.Assert.assertFalse; 20import static org.junit.Assert.assertNotNull; 21import static org.junit.Assert.assertNull; 22import static org.junit.Assert.assertTrue; 23 24import android.content.Context; 25import android.content.Intent; 26import android.graphics.Bitmap; 27import android.graphics.BitmapFactory; 28import android.media.tv.TvContentRating; 29import android.net.Uri; 30import android.os.Build; 31import android.support.test.InstrumentationRegistry; 32import android.support.test.filters.SdkSuppress; 33import android.support.test.filters.SmallTest; 34 35import org.junit.After; 36import org.junit.Before; 37import org.junit.Rule; 38import org.junit.Test; 39import org.junit.rules.ExpectedException; 40import org.junit.runner.RunWith; 41import org.junit.runners.JUnit4; 42 43import java.io.IOException; 44import java.util.Arrays; 45import java.util.List; 46import java.util.Objects; 47 48/** 49 * Test that {@link PreviewChannelHelper} can perform CRUD operations on 50 * {@link PreviewChannel PreviewChannels} and {@link PreviewProgram PreviewPrograms} correctly. 51 * All of the following tests involve the system content provider. 52 */ 53@SmallTest 54@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O) 55@RunWith(JUnit4.class) 56public class PreviewChannelHelperTest { 57 58 59 private Context mContext; 60 61 @Rule 62 public ExpectedException thrown = ExpectedException.none(); 63 64 /** 65 * taken from {@link PreviewProgram} 66 */ 67 private static PreviewProgram.Builder createFullyPopulatedPreviewProgram(long channelId) { 68 return new PreviewProgram.Builder() 69 .setTitle("Google") 70 .setInternalProviderId("ID-4321") 71 .setChannelId(channelId) 72 .setWeight(100) 73 .setPreviewVideoUri(Uri.parse("http://example.com/preview-video.mpg")) 74 .setLastPlaybackPositionMillis(0) 75 .setDurationMillis(60 * 1000) 76 .setIntentUri(Uri.parse(new Intent(Intent.ACTION_VIEW).toUri( 77 Intent.URI_INTENT_SCHEME))) 78 .setTransient(false) 79 .setType(TvContractCompat.PreviewPrograms.TYPE_MOVIE) 80 .setPosterArtAspectRatio(TvContractCompat.PreviewPrograms.ASPECT_RATIO_2_3) 81 .setThumbnailAspectRatio(TvContractCompat.PreviewPrograms.ASPECT_RATIO_16_9) 82 .setLogoUri(Uri.parse("http://example.com/program-logo.mpg")) 83 .setAvailability(TvContractCompat.PreviewPrograms.AVAILABILITY_AVAILABLE) 84 .setStartingPrice("12.99 USD") 85 .setOfferPrice("4.99 USD") 86 .setReleaseDate("1997") 87 .setItemCount(3) 88 .setLive(false) 89 .setInteractionType(TvContractCompat.PreviewPrograms.INTERACTION_TYPE_LIKES) 90 .setInteractionCount(10200) 91 .setAuthor("author_name") 92 .setReviewRatingStyle(TvContractCompat.PreviewPrograms.REVIEW_RATING_STYLE_STARS) 93 .setReviewRating("4.5") 94 .setSearchable(false) 95 .setThumbnailUri(Uri.parse("http://example.com/thumbnail.png")) 96 .setAudioLanguages(new String[]{"eng", "kor"}) 97 .setCanonicalGenres(new String[]{TvContractCompat.Programs.Genres.MOVIES}) 98 .setContentRatings(new TvContentRating[]{ 99 TvContentRating.createRating("com.android.tv", "US_TV", "US_TV_Y7")}) 100 .setDescription("This is a sample program") 101 .setEpisodeNumber("Pilot", 0) 102 .setEpisodeTitle("Hello World") 103 .setLongDescription("This is a longer description than the previous description") 104 .setPosterArtUri(Uri.parse("http://example.com/poster.png")) 105 .setSeasonNumber("The Final Season", 7) 106 .setSeasonTitle("The Final Season") 107 .setVideoHeight(1080) 108 .setVideoWidth(1920) 109 .setInternalProviderFlag1(0x4) 110 .setInternalProviderFlag2(0x3) 111 .setInternalProviderFlag3(0x2) 112 .setInternalProviderFlag4(0x1) 113 .setBrowsable(true) 114 .setContentId("CID-8642"); 115 } 116 117 private static void compareProgram(PreviewProgram programA, PreviewProgram programB) { 118 assertTrue(Arrays.equals(programA.getAudioLanguages(), programB.getAudioLanguages())); 119 assertTrue(Arrays.deepEquals(programA.getCanonicalGenres(), programB.getCanonicalGenres())); 120 assertEquals(programA.getChannelId(), programB.getChannelId()); 121 assertTrue(Arrays.deepEquals(programA.getContentRatings(), programB.getContentRatings())); 122 assertEquals(programA.getDescription(), programB.getDescription()); 123 assertEquals(programA.getEpisodeNumber(), programB.getEpisodeNumber()); 124 assertEquals(programA.getEpisodeTitle(), programB.getEpisodeTitle()); 125 assertEquals(programA.getLongDescription(), programB.getLongDescription()); 126 assertEquals(programA.getPosterArtUri(), programB.getPosterArtUri()); 127 assertEquals(programA.getSeasonNumber(), programB.getSeasonNumber()); 128 assertEquals(programA.getThumbnailUri(), programB.getThumbnailUri()); 129 assertEquals(programA.getTitle(), programB.getTitle()); 130 assertEquals(programA.getVideoHeight(), programB.getVideoHeight()); 131 assertEquals(programA.getVideoWidth(), programB.getVideoWidth()); 132 assertEquals(programA.isSearchable(), programB.isSearchable()); 133 assertEquals(programA.getInternalProviderFlag1(), programB.getInternalProviderFlag1()); 134 assertEquals(programA.getInternalProviderFlag2(), programB.getInternalProviderFlag2()); 135 assertEquals(programA.getInternalProviderFlag3(), programB.getInternalProviderFlag3()); 136 assertEquals(programA.getInternalProviderFlag4(), programB.getInternalProviderFlag4()); 137 assertTrue(Objects.equals(programA.getSeasonTitle(), programB.getSeasonTitle())); 138 assertEquals(programA.getInternalProviderId(), programB.getInternalProviderId()); 139 assertEquals(programA.getPreviewVideoUri(), programB.getPreviewVideoUri()); 140 assertEquals(programA.getLastPlaybackPositionMillis(), 141 programB.getLastPlaybackPositionMillis()); 142 assertEquals(programA.getDurationMillis(), programB.getDurationMillis()); 143 assertEquals(programA.getIntentUri(), programB.getIntentUri()); 144 assertEquals(programA.getWeight(), programB.getWeight()); 145 assertEquals(programA.isTransient(), programB.isTransient()); 146 assertEquals(programA.getType(), programB.getType()); 147 assertEquals(programA.getPosterArtAspectRatio(), programB.getPosterArtAspectRatio()); 148 assertEquals(programA.getThumbnailAspectRatio(), programB.getThumbnailAspectRatio()); 149 assertEquals(programA.getLogoUri(), programB.getLogoUri()); 150 assertEquals(programA.getAvailability(), programB.getAvailability()); 151 assertEquals(programA.getStartingPrice(), programB.getStartingPrice()); 152 assertEquals(programA.getOfferPrice(), programB.getOfferPrice()); 153 assertEquals(programA.getReleaseDate(), programB.getReleaseDate()); 154 assertEquals(programA.getItemCount(), programB.getItemCount()); 155 assertEquals(programA.isLive(), programB.isLive()); 156 assertEquals(programA.getInteractionType(), programB.getInteractionType()); 157 assertEquals(programA.getInteractionCount(), programB.getInteractionCount()); 158 assertEquals(programA.getAuthor(), programB.getAuthor()); 159 assertEquals(programA.getReviewRatingStyle(), programB.getReviewRatingStyle()); 160 assertEquals(programA.getReviewRating(), programB.getReviewRating()); 161 assertEquals(programA.getContentId(), programB.getContentId()); 162 } 163 164 private static WatchNextProgram.Builder createFullyPopulatedWatchNextProgram() { 165 return new WatchNextProgram.Builder() 166 .setTitle("Google") 167 .setInternalProviderId("ID-4321") 168 .setPreviewVideoUri(Uri.parse("http://example.com/preview-video.mpg")) 169 .setLastPlaybackPositionMillis(0) 170 .setDurationMillis(60 * 1000) 171 .setIntentUri(Uri.parse(new Intent(Intent.ACTION_VIEW).toUri( 172 Intent.URI_INTENT_SCHEME))) 173 .setTransient(false) 174 .setType(TvContractCompat.WatchNextPrograms.TYPE_MOVIE) 175 .setWatchNextType(TvContractCompat.WatchNextPrograms.WATCH_NEXT_TYPE_CONTINUE) 176 .setPosterArtAspectRatio(TvContractCompat.WatchNextPrograms.ASPECT_RATIO_2_3) 177 .setThumbnailAspectRatio(TvContractCompat.WatchNextPrograms.ASPECT_RATIO_16_9) 178 .setLogoUri(Uri.parse("http://example.com/program-logo.mpg")) 179 .setAvailability(TvContractCompat.WatchNextPrograms.AVAILABILITY_AVAILABLE) 180 .setStartingPrice("12.99 USD") 181 .setOfferPrice("4.99 USD") 182 .setReleaseDate("1997") 183 .setItemCount(3) 184 .setLive(false) 185 .setInteractionType(TvContractCompat.WatchNextPrograms.INTERACTION_TYPE_LIKES) 186 .setInteractionCount(10200) 187 .setAuthor("author_name") 188 .setReviewRatingStyle(TvContractCompat.WatchNextPrograms.REVIEW_RATING_STYLE_STARS) 189 .setReviewRating("4.5") 190 .setSearchable(false) 191 .setThumbnailUri(Uri.parse("http://example.com/thumbnail.png")) 192 .setAudioLanguages(new String[]{"eng", "kor"}) 193 .setCanonicalGenres(new String[]{TvContractCompat.Programs.Genres.MOVIES}) 194 .setContentRatings(new TvContentRating[]{ 195 TvContentRating.createRating("com.android.tv", "US_TV", "US_TV_Y7")}) 196 .setDescription("This is a sample program") 197 .setEpisodeNumber("Pilot", 0) 198 .setEpisodeTitle("Hello World") 199 .setLongDescription("This is a longer description than the previous description") 200 .setPosterArtUri(Uri.parse("http://example.com/poster.png")) 201 .setSeasonNumber("The Final Season", 7) 202 .setSeasonTitle("The Final Season") 203 .setVideoHeight(1080) 204 .setVideoWidth(1920) 205 .setInternalProviderFlag1(0x4) 206 .setInternalProviderFlag2(0x3) 207 .setInternalProviderFlag3(0x2) 208 .setInternalProviderFlag4(0x1) 209 .setBrowsable(true) 210 .setContentId("CID-8442"); 211 } 212 213 private static void compareProgram(WatchNextProgram programA, WatchNextProgram programB) { 214 assertTrue(Arrays.equals(programA.getAudioLanguages(), programB.getAudioLanguages())); 215 assertTrue(Arrays.deepEquals(programA.getCanonicalGenres(), programB.getCanonicalGenres())); 216 assertTrue(Arrays.deepEquals(programA.getContentRatings(), programB.getContentRatings())); 217 assertEquals(programA.getDescription(), programB.getDescription()); 218 assertEquals(programA.getEpisodeNumber(), programB.getEpisodeNumber()); 219 assertEquals(programA.getEpisodeTitle(), programB.getEpisodeTitle()); 220 assertEquals(programA.getLongDescription(), programB.getLongDescription()); 221 assertEquals(programA.getPosterArtUri(), programB.getPosterArtUri()); 222 assertEquals(programA.getSeasonNumber(), programB.getSeasonNumber()); 223 assertEquals(programA.getThumbnailUri(), programB.getThumbnailUri()); 224 assertEquals(programA.getTitle(), programB.getTitle()); 225 assertEquals(programA.getVideoHeight(), programB.getVideoHeight()); 226 assertEquals(programA.getVideoWidth(), programB.getVideoWidth()); 227 assertEquals(programA.isSearchable(), programB.isSearchable()); 228 assertEquals(programA.getInternalProviderFlag1(), programB.getInternalProviderFlag1()); 229 assertEquals(programA.getInternalProviderFlag2(), programB.getInternalProviderFlag2()); 230 assertEquals(programA.getInternalProviderFlag3(), programB.getInternalProviderFlag3()); 231 assertEquals(programA.getInternalProviderFlag4(), programB.getInternalProviderFlag4()); 232 assertTrue(Objects.equals(programA.getSeasonTitle(), programB.getSeasonTitle())); 233 assertEquals(programA.getInternalProviderId(), programB.getInternalProviderId()); 234 assertEquals(programA.getPreviewVideoUri(), programB.getPreviewVideoUri()); 235 assertEquals(programA.getLastPlaybackPositionMillis(), 236 programB.getLastPlaybackPositionMillis()); 237 assertEquals(programA.getDurationMillis(), programB.getDurationMillis()); 238 assertEquals(programA.getIntentUri(), programB.getIntentUri()); 239 assertEquals(programA.isTransient(), programB.isTransient()); 240 assertEquals(programA.getType(), programB.getType()); 241 assertEquals(programA.getWatchNextType(), programB.getWatchNextType()); 242 assertEquals(programA.getPosterArtAspectRatio(), programB.getPosterArtAspectRatio()); 243 assertEquals(programA.getThumbnailAspectRatio(), programB.getThumbnailAspectRatio()); 244 assertEquals(programA.getLogoUri(), programB.getLogoUri()); 245 assertEquals(programA.getAvailability(), programB.getAvailability()); 246 assertEquals(programA.getStartingPrice(), programB.getStartingPrice()); 247 assertEquals(programA.getOfferPrice(), programB.getOfferPrice()); 248 assertEquals(programA.getReleaseDate(), programB.getReleaseDate()); 249 assertEquals(programA.getItemCount(), programB.getItemCount()); 250 assertEquals(programA.isLive(), programB.isLive()); 251 assertEquals(programA.getInteractionType(), programB.getInteractionType()); 252 assertEquals(programA.getInteractionCount(), programB.getInteractionCount()); 253 assertEquals(programA.getAuthor(), programB.getAuthor()); 254 assertEquals(programA.getReviewRatingStyle(), programB.getReviewRatingStyle()); 255 assertEquals(programA.getReviewRating(), programB.getReviewRating()); 256 assertEquals(programA.getContentId(), programB.getContentId()); 257 } 258 259 @Before 260 public void setUp() throws Exception { 261 mContext = InstrumentationRegistry.getContext(); 262 263 } 264 265 @After 266 public void tearDown() { 267 if (!Utils.hasTvInputFramework(InstrumentationRegistry.getContext())) { 268 return; 269 } 270 mContext.getContentResolver().delete( 271 TvContractCompat.Channels.CONTENT_URI, null, null); 272 mContext = null; 273 } 274 275 /** 276 * Test CR of CRUD 277 * Test that the PreviewChannelHelper can correctly create and read preview channels. 278 */ 279 @Test 280 public void testPreviewChannelCreation() throws IOException { 281 if (!Utils.hasTvInputFramework(InstrumentationRegistry.getContext())) { 282 return; 283 } 284 PreviewChannelHelper helper = new PreviewChannelHelper(mContext); 285 PreviewChannel.Builder builder = createFullyPopulatedPreviewChannel(); 286 long channelId = helper.publishDefaultChannel(builder.build()); 287 PreviewChannel channelFromTvProvider = getPreviewChannel(helper, channelId); 288 assertTrue(channelsEqual(builder.build(), channelFromTvProvider)); 289 } 290 291 @Test 292 public void testLogoRequiredForChannelCreation() throws IOException { 293 if (!Utils.hasTvInputFramework(InstrumentationRegistry.getContext())) { 294 return; 295 } 296 PreviewChannelHelper helper = new PreviewChannelHelper(mContext); 297 PreviewChannel.Builder builder = createFullyPopulatedPreviewChannel(); 298 builder.setLogo(Uri.parse("bogus")); 299 thrown.expect(IOException.class); 300 helper.publishDefaultChannel(builder.build()); 301 List<PreviewChannel> channels = helper.getAllChannels(); 302 assertEquals(0, channels.size()); 303 } 304 305 /** 306 * Test CR of CRUD 307 * Test that the PreviewChannelHelper can correctly create and read preview channels, when 308 * internalProviderId is null. 309 */ 310 @Test 311 public void testPreviewChannelCreationWithNullProviderId() throws IOException { 312 if (!Utils.hasTvInputFramework(InstrumentationRegistry.getContext())) { 313 return; 314 } 315 PreviewChannel.Builder builder = createFullyPopulatedPreviewChannel(); 316 builder.setInternalProviderId(null); 317 PreviewChannelHelper helper = new PreviewChannelHelper(mContext); 318 long channelId = helper.publishChannel(builder.build()); 319 PreviewChannel channelFromTvProvider = getPreviewChannel(helper, channelId); 320 assertTrue(channelsEqual(builder.build(), channelFromTvProvider)); 321 } 322 323 /** 324 * All this method is actually doing is 325 * <pre> 326 * 327 * PreviewChannel channelFromTvProvider = helper.getPreviewChannel(channelId); 328 * </pre> 329 * However, due to a known issue, when logo is persisted, the file status is not consistent 330 * between openInputStream and openOutputStream. So as a workaround, a wait period is applied 331 * to make sure that the logo file is written into the disk. 332 */ 333 private PreviewChannel getPreviewChannel(PreviewChannelHelper helper, 334 long channelId) { 335 boolean logoReady = false; 336 PreviewChannel channel = null; 337 while (!logoReady) { 338 try { 339 Thread.sleep(50); 340 } catch (InterruptedException e) { 341 } 342 channel = helper.getPreviewChannel(channelId); 343 logoReady = null != channel.getLogo(mContext); 344 } 345 return channel; 346 } 347 348 /** 349 * Test CR of CRUD 350 * Test that all published preview channels can be read at once. 351 */ 352 @Test 353 public void testAllPublishedChannelsRead() throws IOException { 354 if (!Utils.hasTvInputFramework(InstrumentationRegistry.getContext())) { 355 return; 356 } 357 PreviewChannelHelper helper = new PreviewChannelHelper(mContext); 358 PreviewChannel.Builder builder = createFullyPopulatedPreviewChannel(); 359 builder.setInternalProviderId("1"); 360 helper.publishChannel(builder.build()); 361 builder.setInternalProviderId("11"); 362 helper.publishChannel(builder.build()); 363 builder.setInternalProviderId("111"); 364 helper.publishChannel(builder.build()); 365 builder.setInternalProviderId("1111"); 366 helper.publishChannel(builder.build()); 367 List<PreviewChannel> allChannels = helper.getAllChannels(); 368 assertEquals(4, allChannels.size()); 369 } 370 371 /** 372 * Test UR of CRUD 373 * Test that the PreviewChannelHelper can correctly update and read preview channels. 374 */ 375 @Test 376 public void testPreviewChannelUpdate() throws IOException { 377 if (!Utils.hasTvInputFramework(InstrumentationRegistry.getContext())) { 378 return; 379 } 380 PreviewChannelHelper helper = new PreviewChannelHelper(mContext); 381 PreviewChannel.Builder builder = createFullyPopulatedPreviewChannel(); 382 long channelId = helper.publishChannel(builder.build()); 383 PreviewChannel channelFromTvProvider = getPreviewChannel(helper, channelId); 384 PreviewChannel channel = builder.build(); 385 assertTrue(channelsEqual(channel, channelFromTvProvider)); 386 387 PreviewChannel patch = new PreviewChannel.Builder() 388 .setDisplayName(channel.getDisplayName()) 389 .setAppLinkIntentUri(channel.getAppLinkIntentUri()) 390 .setDescription("Patch description").build(); 391 helper.updatePreviewChannel(channelId, patch); 392 channelFromTvProvider = helper.getPreviewChannel(channelId); 393 assertFalse(channelsEqual(channel, channelFromTvProvider)); 394 assertEquals(channelFromTvProvider.getDescription(), "Patch description"); 395 } 396 397 /** 398 * Tests that data is not being updated unnecessarily 399 */ 400 @Test 401 public void testDefensiveUpdatePreviewChannel() throws IOException { 402 if (!Utils.hasTvInputFramework(InstrumentationRegistry.getContext())) { 403 return; 404 } 405 final int[] channelUpdateCount = {0}; 406 PreviewChannelHelper helper = new PreviewChannelHelper(mContext) { 407 @Override 408 protected void updatePreviewChannelInternal(long channelId, PreviewChannel channel) { 409 channelUpdateCount[0]++; 410 } 411 }; 412 PreviewChannel.Builder builder = createFullyPopulatedPreviewChannel(); 413 long channelId = helper.publishChannel(builder.build()); 414 PreviewChannel fromProvider = helper.getPreviewChannel(channelId); 415 channelsEqual(builder.build(), fromProvider); 416 helper.updatePreviewChannel(channelId, builder.build()); 417 assertEquals(0, channelUpdateCount[0]); 418 419 final Uri uri = Uri.parse(new Intent(Intent.ACTION_VIEW).toUri(Intent.URI_INTENT_SCHEME)); 420 PreviewChannel channel = new PreviewChannel.Builder() 421 .setDisplayName("Test Display Name Udpate") 422 .setDescription("Test Preview Channel Description") 423 .setAppLinkIntentUri(uri).build(); 424 425 helper.updatePreviewChannel(channelId, channel); 426 assertEquals(1, channelUpdateCount[0]); 427 } 428 429 @Test 430 public void testPreviewResolverChannelDeletion() throws IOException { 431 if (!Utils.hasTvInputFramework(InstrumentationRegistry.getContext())) { 432 return; 433 } 434 PreviewChannelHelper helper = new PreviewChannelHelper(mContext); 435 PreviewChannel.Builder builder = createFullyPopulatedPreviewChannel(); 436 long channelId = helper.publishChannel(builder.build()); 437 PreviewChannel channelFromTvProvider = getPreviewChannel(helper, channelId); 438 assertTrue(channelsEqual(builder.build(), channelFromTvProvider)); 439 440 helper.deletePreviewChannel(channelId); 441 channelFromTvProvider = helper.getPreviewChannel(channelId); 442 assertNull(channelFromTvProvider); 443 } 444 445 @Test 446 public void testPreviewProgramCreation() throws IOException { 447 if (!Utils.hasTvInputFramework(InstrumentationRegistry.getContext())) { 448 return; 449 } 450 PreviewChannelHelper helper = new PreviewChannelHelper(mContext); 451 PreviewChannel.Builder channelBuilder = createFullyPopulatedPreviewChannel(); 452 long channelId = helper.publishChannel(channelBuilder.build()); 453 PreviewProgram program = createFullyPopulatedPreviewProgram(channelId).build(); 454 long programId = helper.publishPreviewProgram(program); 455 PreviewProgram programFromProvider = helper.getPreviewProgram(programId); 456 compareProgram(program, programFromProvider); 457 } 458 459 @Test 460 public void testPreviewProgramUpdate() throws IOException { 461 if (!Utils.hasTvInputFramework(InstrumentationRegistry.getContext())) { 462 return; 463 } 464 PreviewChannelHelper helper = new PreviewChannelHelper(mContext); 465 PreviewChannel.Builder channelBuilder = createFullyPopulatedPreviewChannel(); 466 long channelId = helper.publishChannel(channelBuilder.build()); 467 PreviewProgram.Builder programBuilder = createFullyPopulatedPreviewProgram(channelId); 468 long programId = helper.publishPreviewProgram(programBuilder.build()); 469 470 programBuilder.setReleaseDate("2000"); 471 472 helper.updatePreviewProgram(programId, programBuilder.build()); 473 PreviewProgram programFromProvider = helper.getPreviewProgram(programId); 474 compareProgram(programBuilder.build(), programFromProvider); 475 } 476 477 /** 478 * Tests that data is not being updated unnecessarily 479 */ 480 @Test 481 public void testDefensivePreviewProgramUpdateRequests() throws IOException { 482 if (!Utils.hasTvInputFramework(InstrumentationRegistry.getContext())) { 483 return; 484 } 485 final int[] programUpdateCount = {0}; 486 PreviewChannelHelper helper = new PreviewChannelHelper(mContext) { 487 488 @Override 489 public void updatePreviewProgramInternal(long programId, PreviewProgram upgrade) { 490 programUpdateCount[0]++; 491 } 492 }; 493 PreviewChannel.Builder channelBuilder = createFullyPopulatedPreviewChannel(); 494 long channelId = helper.publishChannel(channelBuilder.build()); 495 PreviewProgram.Builder programBuilder = createFullyPopulatedPreviewProgram(channelId); 496 long programId = helper.publishPreviewProgram(programBuilder.build()); 497 PreviewProgram programFromProvider = helper.getPreviewProgram(programId); 498 compareProgram(programBuilder.build(), programFromProvider); 499 helper.updatePreviewProgram(programId, programBuilder.build()); 500 assertEquals(0, programUpdateCount[0]); 501 programBuilder.setDurationMillis(61 * 1000); 502 helper.updatePreviewProgram(programId, programBuilder.build()); 503 assertEquals(1, programUpdateCount[0]); 504 } 505 506 @Test 507 public void testDeletePreviewProgram() throws IOException { 508 if (!Utils.hasTvInputFramework(InstrumentationRegistry.getContext())) { 509 return; 510 } 511 PreviewChannelHelper helper = new PreviewChannelHelper(mContext); 512 PreviewChannel.Builder channelBuilder = createFullyPopulatedPreviewChannel(); 513 long channelId = helper.publishChannel(channelBuilder.build()); 514 PreviewProgram.Builder programBuilder = createFullyPopulatedPreviewProgram(channelId); 515 long programId = helper.publishPreviewProgram(programBuilder.build()); 516 517 helper.deletePreviewProgram(programId); 518 PreviewProgram programFromProvider = helper.getPreviewProgram(programId); 519 assertNull(programFromProvider); 520 } 521 522 @Test 523 public void testWatchNextProgramCreation() { 524 if (!Utils.hasTvInputFramework(InstrumentationRegistry.getContext())) { 525 return; 526 } 527 PreviewChannelHelper helper = new PreviewChannelHelper(mContext); 528 WatchNextProgram program = createFullyPopulatedWatchNextProgram().build(); 529 long programId = helper.publishWatchNextProgram(program); 530 WatchNextProgram programFromProvider = helper.getWatchNextProgram(programId); 531 compareProgram(program, programFromProvider); 532 } 533 534 @Test 535 public void testUpdateWatchNextProgram() { 536 if (!Utils.hasTvInputFramework(InstrumentationRegistry.getContext())) { 537 return; 538 } 539 PreviewChannelHelper helper = new PreviewChannelHelper(mContext); 540 WatchNextProgram.Builder builder = createFullyPopulatedWatchNextProgram(); 541 long programId = helper.publishWatchNextProgram(builder.build()); 542 builder.setOfferPrice("10.99 USD"); 543 helper.updateWatchNextProgram(builder.build(), programId); 544 545 WatchNextProgram fromProvider = helper.getWatchNextProgram(programId); 546 compareProgram(builder.build(), fromProvider); 547 } 548 549 /** 550 * Tests that data is not being updated unnecessarily 551 */ 552 @Test 553 public void testDefensiveUpdateWatchNextProgram() { 554 if (!Utils.hasTvInputFramework(InstrumentationRegistry.getContext())) { 555 return; 556 } 557 final int[] programUpdateCount = {0}; 558 PreviewChannelHelper helper = new PreviewChannelHelper(mContext) { 559 @Override 560 protected void updateWatchNextProgram(long programId, WatchNextProgram upgrade) { 561 programUpdateCount[0]++; 562 } 563 }; 564 WatchNextProgram.Builder builder = createFullyPopulatedWatchNextProgram(); 565 long programId = helper.publishWatchNextProgram(builder.build()); 566 WatchNextProgram fromProvider = helper.getWatchNextProgram(programId); 567 compareProgram(builder.build(), fromProvider); 568 helper.updateWatchNextProgram(builder.build(), programId); 569 assertEquals(0, programUpdateCount[0]); 570 builder.setReleaseDate("2000"); 571 helper.updateWatchNextProgram(builder.build(), programId); 572 assertEquals(1, programUpdateCount[0]); 573 } 574 575 private boolean channelsEqual(PreviewChannel channelA, PreviewChannel channelB) { 576 boolean result = channelA.getDisplayName().equals(channelB.getDisplayName()) 577 && channelA.getType().equals(channelB.getType()) 578 && channelA.getAppLinkIntentUri().equals(channelB.getAppLinkIntentUri()) 579 && channelA.getDescription().equals(channelB.getDescription()) 580 && channelA.getPackageName().equals(channelB.getPackageName()) 581 && channelA.getInternalProviderFlag1() == channelB.getInternalProviderFlag1() 582 && channelA.getInternalProviderFlag2() == channelB.getInternalProviderFlag2() 583 && channelA.getInternalProviderFlag3() == channelB.getInternalProviderFlag3() 584 && channelA.getInternalProviderFlag4() == channelB.getInternalProviderFlag4() 585 && (channelA.getInternalProviderId() == null 586 && channelB.getInternalProviderId() == null 587 || channelA.getInternalProviderId().equals(channelB.getInternalProviderId())) 588 && (null != channelA.getLogo(mContext) && null != channelB.getLogo( 589 mContext)) 590 && Arrays.equals(channelA.getInternalProviderDataByteArray(), 591 channelB.getInternalProviderDataByteArray()); 592 return result; 593 } 594 595 public PreviewChannel.Builder createFullyPopulatedPreviewChannel() { 596 Bitmap logo = BitmapFactory.decodeResource(mContext.getResources(), 597 androidx.tvprovider.test.R.drawable.test_icon); 598 assertNotNull(logo); 599 return new PreviewChannel.Builder() 600 .setAppLinkIntent(new Intent()) 601 .setDescription("Test Preview Channel Description") 602 .setDisplayName("Test Display Name") 603 .setPackageName("androidx.tvprovider.media.tv.test") 604 .setInternalProviderFlag1(0x1) 605 .setInternalProviderFlag2(0x2) 606 .setInternalProviderFlag3(0x3) 607 .setInternalProviderFlag4(0x4) 608 .setInternalProviderId("Test Internal provider id") 609 .setInternalProviderData("Test byte array".getBytes()) 610 .setLogo(logo); 611 } 612} 613