1 /* 2 * Copyright 2024 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.photopicker.tests.core.events 18 19 import android.content.ContentResolver 20 import android.content.Context 21 import android.content.pm.PackageManager 22 import android.content.pm.UserProperties 23 import android.media.ApplicationMediaCapabilities 24 import android.media.MediaFeature.HdrType 25 import android.net.Uri 26 import android.os.Build 27 import android.os.Parcel 28 import android.os.UserHandle 29 import android.os.UserManager 30 import androidx.test.ext.junit.runners.AndroidJUnit4 31 import androidx.test.filters.SdkSuppress 32 import androidx.test.filters.SmallTest 33 import androidx.test.platform.app.InstrumentationRegistry 34 import com.android.modules.utils.build.SdkLevel 35 import com.android.photopicker.R 36 import com.android.photopicker.core.configuration.PhotopickerRuntimeEnv 37 import com.android.photopicker.core.configuration.TestPhotopickerConfiguration 38 import com.android.photopicker.core.configuration.provideTestConfigurationFlow 39 import com.android.photopicker.core.events.Event 40 import com.android.photopicker.core.events.Events 41 import com.android.photopicker.core.events.Telemetry 42 import com.android.photopicker.core.events.dispatchPhotopickerExpansionStateChangedEvent 43 import com.android.photopicker.core.events.dispatchReportPhotopickerApiInfoEvent 44 import com.android.photopicker.core.events.dispatchReportPhotopickerMediaItemStatusEvent 45 import com.android.photopicker.core.events.dispatchReportPhotopickerSessionInfoEvent 46 import com.android.photopicker.core.events.dispatchReportPickerAppMediaCapabilities 47 import com.android.photopicker.core.events.generatePickerSessionId 48 import com.android.photopicker.core.features.FeatureManager 49 import com.android.photopicker.core.features.FeatureToken 50 import com.android.photopicker.core.selection.Selection 51 import com.android.photopicker.core.selection.SelectionImpl 52 import com.android.photopicker.core.user.UserMonitor 53 import com.android.photopicker.data.DataService 54 import com.android.photopicker.data.TestDataServiceImpl 55 import com.android.photopicker.data.TestPrefetchDataService 56 import com.android.photopicker.data.model.Group 57 import com.android.photopicker.data.model.Media 58 import com.android.photopicker.data.model.MediaSource 59 import com.android.photopicker.features.search.SearchFeature 60 import com.android.photopicker.util.test.mockSystemService 61 import com.android.photopicker.util.test.whenever 62 import com.google.common.truth.Truth.assertThat 63 import dagger.Lazy 64 import kotlinx.coroutines.ExperimentalCoroutinesApi 65 import kotlinx.coroutines.flow.toList 66 import kotlinx.coroutines.launch 67 import kotlinx.coroutines.test.StandardTestDispatcher 68 import kotlinx.coroutines.test.TestScope 69 import kotlinx.coroutines.test.advanceTimeBy 70 import kotlinx.coroutines.test.runTest 71 import org.junit.Test 72 import org.junit.runner.RunWith 73 import org.mockito.ArgumentMatchers.any 74 import org.mockito.Mockito.anyInt 75 import org.mockito.Mockito.mock 76 77 /** Unit tests for the telemetry event dispatchers */ 78 @SmallTest 79 @RunWith(AndroidJUnit4::class) 80 @OptIn(ExperimentalCoroutinesApi::class) 81 class DispatchersTest { 82 private val sessionId = generatePickerSessionId() 83 private val packageUid = 12345 84 85 private val photopickerConfiguration = <lambda>null86 TestPhotopickerConfiguration.build { 87 action(value = "") 88 sessionId(value = sessionId) 89 callingPackageUid(value = packageUid) 90 runtimeEnv(value = PhotopickerRuntimeEnv.EMBEDDED) 91 mimeTypes(arrayListOf("image/jpeg")) 92 } 93 private val mediaItemAlbum = 94 Group.Album( 95 id = "", 96 pickerId = 0L, 97 authority = "", 98 dateTakenMillisLong = 0L, 99 displayName = "", 100 coverUri = Uri.EMPTY, 101 coverMediaSource = MediaSource.LOCAL, 102 ) 103 private val mediaItem = 104 Media.Image( 105 mediaId = "", 106 pickerId = 0L, 107 index = 9999, 108 authority = "", 109 mediaSource = MediaSource.LOCAL, 110 mediaUri = Uri.EMPTY, 111 glideLoadableUri = Uri.EMPTY, 112 dateTakenMillisLong = 0L, 113 sizeInBytes = 0, 114 mimeType = "image/jpeg", 115 standardMimeTypeExtension = 0, 116 selectionSource = Telemetry.MediaLocation.MAIN_GRID, 117 mediaItemAlbum = mediaItemAlbum, 118 ) 119 <lambda>null120 private val lazyDataService: Lazy<DataService> = Lazy { TestDataServiceImpl() } 121 122 private lateinit var lazyEvents: Lazy<Events> 123 private lateinit var eventsDispatched: MutableList<Event> 124 private lateinit var lazyUserMonitor: Lazy<UserMonitor> 125 private lateinit var lazyMediaSelection: Lazy<Selection<Media>> 126 private lateinit var lazyFeatureManager: Lazy<FeatureManager> 127 setupnull128 private fun setup(testScope: TestScope) { 129 val backgroundScope = testScope.backgroundScope 130 val testScheduler = testScope.testScheduler 131 132 val photopickerConfigurationStateFlow = 133 provideTestConfigurationFlow( 134 scope = backgroundScope, 135 defaultConfiguration = photopickerConfiguration, 136 ) 137 val featureManager = 138 FeatureManager( 139 configuration = photopickerConfigurationStateFlow, 140 scope = backgroundScope, 141 prefetchDataService = TestPrefetchDataService(), 142 ) 143 lazyFeatureManager = Lazy { featureManager } 144 145 val events = 146 Events( 147 scope = backgroundScope, 148 configuration = photopickerConfigurationStateFlow, 149 featureManager = featureManager, 150 ) 151 lazyEvents = Lazy { events } 152 153 eventsDispatched = mutableListOf() 154 backgroundScope.launch { events.flow.toList(eventsDispatched) } 155 156 val mockContext = mock(Context::class.java) 157 158 val mockUserManager = mock(UserManager::class.java) 159 mockSystemService(mockContext, UserManager::class.java) { mockUserManager } 160 161 if (SdkLevel.isAtLeastV()) { 162 whenever( 163 mockUserManager.getUserProperties(any(UserHandle::class.java)) 164 ) @JvmSerializableLambda { UserProperties.Builder().build() } 165 whenever(mockUserManager.getUserBadge()) { 166 InstrumentationRegistry.getInstrumentation() 167 .context 168 .resources 169 .getDrawable(R.drawable.android, /* theme= */ null) 170 } 171 whenever(mockUserManager.getProfileLabel()) { "label" } 172 } 173 174 whenever(mockContext.packageManager) { mock(PackageManager::class.java) } 175 whenever(mockContext.contentResolver) { mock(ContentResolver::class.java) } 176 whenever(mockContext.createPackageContextAsUser(any(), anyInt(), any())) { mockContext } 177 whenever(mockContext.createContextAsUser(any(UserHandle::class.java), anyInt())) { 178 mockContext 179 } 180 181 // Get primaryUserHandle: UserHandle 182 val parcel1 = Parcel.obtain() 183 parcel1.writeInt(/* primary user id */ 0) 184 parcel1.setDataPosition(0) 185 val primaryUserHandle = UserHandle(parcel1) 186 parcel1.recycle() 187 188 val userMonitor = 189 UserMonitor( 190 context = mockContext, 191 configuration = photopickerConfigurationStateFlow, 192 scope = backgroundScope, 193 dispatcher = StandardTestDispatcher(testScheduler), 194 processOwnerUserHandle = primaryUserHandle, 195 ) 196 lazyUserMonitor = Lazy { userMonitor } 197 198 val selection = 199 SelectionImpl( 200 scope = backgroundScope, 201 configuration = photopickerConfigurationStateFlow, 202 preSelectedMedia = lazyDataService.get().preSelectionMediaData, 203 ) 204 lazyMediaSelection = Lazy { selection } 205 } 206 207 @Test <lambda>null208 fun testDispatchPhotopickerExpansionStateChangedEvent_isExpanded() = runTest { 209 // Setup 210 setup(testScope = this) 211 212 val expectedEvent = 213 Event.LogPhotopickerUIEvent( 214 dispatcherToken = FeatureToken.CORE.token, 215 sessionId = sessionId, 216 packageUid = packageUid, 217 uiEvent = Telemetry.UiEvent.EXPAND_PICKER, 218 ) 219 220 // Action 221 dispatchPhotopickerExpansionStateChangedEvent( 222 coroutineScope = backgroundScope, 223 lazyEvents = lazyEvents, 224 photopickerConfiguration = photopickerConfiguration, 225 isExpanded = true, 226 ) 227 advanceTimeBy(delayTimeMillis = 50) 228 229 // Assert 230 assertThat(eventsDispatched).contains(expectedEvent) 231 } 232 233 @Test <lambda>null234 fun testDispatchPhotopickerExpansionStateChangedEvent_isCollapsed() = runTest { 235 // Setup 236 setup(testScope = this) 237 238 val expectedEvent = 239 Event.LogPhotopickerUIEvent( 240 dispatcherToken = FeatureToken.CORE.token, 241 sessionId = sessionId, 242 packageUid = packageUid, 243 uiEvent = Telemetry.UiEvent.COLLAPSE_PICKER, 244 ) 245 246 // Action 247 dispatchPhotopickerExpansionStateChangedEvent( 248 coroutineScope = backgroundScope, 249 lazyEvents = lazyEvents, 250 photopickerConfiguration = photopickerConfiguration, 251 isExpanded = false, 252 ) 253 advanceTimeBy(delayTimeMillis = 50) 254 255 // Assert 256 assertThat(eventsDispatched).contains(expectedEvent) 257 } 258 259 @Test <lambda>null260 fun testDispatchReportPhotopickerMediaItemStatusEvent_selected() = runTest { 261 // Setup 262 setup(testScope = this) 263 264 val expectedEvent = 265 Event.ReportPhotopickerMediaItemStatus( 266 dispatcherToken = FeatureToken.CORE.token, 267 sessionId = sessionId, 268 mediaStatus = Telemetry.MediaStatus.SELECTED, 269 selectionSource = Telemetry.MediaLocation.MAIN_GRID, 270 itemPosition = 9999, 271 selectedAlbum = mediaItemAlbum, 272 mediaType = Telemetry.MediaType.PHOTO, 273 cloudOnly = false, 274 pickerSize = Telemetry.PickerSize.UNSET_PICKER_SIZE, 275 ) 276 277 // Action 278 dispatchReportPhotopickerMediaItemStatusEvent( 279 coroutineScope = backgroundScope, 280 lazyEvents = lazyEvents, 281 photopickerConfiguration = photopickerConfiguration, 282 mediaItem = mediaItem, 283 mediaStatus = Telemetry.MediaStatus.SELECTED, 284 ) 285 advanceTimeBy(delayTimeMillis = 50) 286 287 // Assert 288 assertThat(eventsDispatched).contains(expectedEvent) 289 } 290 291 @Test <lambda>null292 fun testDispatchReportPhotopickerMediaItemStatusEvent_unselected() = runTest { 293 // Setup 294 setup(testScope = this) 295 296 val expectedEvent = 297 Event.ReportPhotopickerMediaItemStatus( 298 dispatcherToken = FeatureToken.CORE.token, 299 sessionId = sessionId, 300 mediaStatus = Telemetry.MediaStatus.UNSELECTED, 301 selectionSource = Telemetry.MediaLocation.MAIN_GRID, 302 itemPosition = 9999, 303 selectedAlbum = mediaItemAlbum, 304 mediaType = Telemetry.MediaType.PHOTO, 305 cloudOnly = false, 306 pickerSize = Telemetry.PickerSize.UNSET_PICKER_SIZE, 307 ) 308 309 // Action 310 dispatchReportPhotopickerMediaItemStatusEvent( 311 coroutineScope = backgroundScope, 312 lazyEvents = lazyEvents, 313 photopickerConfiguration = photopickerConfiguration, 314 mediaItem = mediaItem, 315 mediaStatus = Telemetry.MediaStatus.UNSELECTED, 316 ) 317 advanceTimeBy(delayTimeMillis = 50) 318 319 // Assert 320 assertThat(eventsDispatched).contains(expectedEvent) 321 } 322 323 @Test <lambda>null324 fun testDispatchReportPhotopickerSessionInfoEvent() = runTest { 325 // Setup 326 setup(testScope = this) 327 328 val pickerStatus = Telemetry.PickerStatus.OPENED 329 val pickerCloseMethod = Telemetry.PickerCloseMethod.SWIPE_DOWN 330 331 val expectedEvent = 332 Event.ReportPhotopickerSessionInfo( 333 dispatcherToken = FeatureToken.CORE.token, 334 sessionId = sessionId, 335 packageUid = packageUid, 336 pickerSelection = Telemetry.PickerSelection.SINGLE, 337 cloudProviderUid = -1, 338 userProfile = Telemetry.UserProfile.PERSONAL, 339 pickerStatus = pickerStatus, 340 pickedItemsCount = 0, 341 pickedItemsSize = 0, 342 profileSwitchButtonVisible = false, 343 pickerMode = Telemetry.PickerMode.EMBEDDED_PICKER, 344 pickerCloseMethod = pickerCloseMethod, 345 ) 346 347 // Action 348 dispatchReportPhotopickerSessionInfoEvent( 349 coroutineScope = backgroundScope, 350 lazyEvents = lazyEvents, 351 photopickerConfiguration = photopickerConfiguration, 352 lazyDataService = lazyDataService, 353 lazyUserMonitor = lazyUserMonitor, 354 lazyMediaSelection = lazyMediaSelection, 355 pickerStatus = pickerStatus, 356 pickerCloseMethod = pickerCloseMethod, 357 ) 358 advanceTimeBy(delayTimeMillis = 50) 359 360 // Assert 361 assertThat(eventsDispatched).contains(expectedEvent) 362 } 363 364 @Test testDispatchReportPhotopickerApiInfoEventWithPhotoMimeTypenull365 fun testDispatchReportPhotopickerApiInfoEventWithPhotoMimeType() = runTest { 366 // Setup 367 setup(testScope = this) 368 369 val mimeTypeList = arrayListOf("image/jpg") 370 val telemetryMimeTypeMapping = Telemetry.MediaType.PHOTO 371 372 val pickerIntentAction = Telemetry.PickerIntentAction.ACTION_PICK_IMAGES 373 val cloudSearch = lazyFeatureManager.get().isFeatureEnabled(SearchFeature::class.java) 374 val photopickerConfiguration = 375 TestPhotopickerConfiguration.build { 376 action(value = "") 377 sessionId(value = sessionId) 378 callingPackageUid(value = packageUid) 379 runtimeEnv(value = PhotopickerRuntimeEnv.EMBEDDED) 380 mimeTypes(mimeTypeList) 381 } 382 383 val expectedEvent = 384 Event.ReportPhotopickerApiInfo( 385 dispatcherToken = FeatureToken.CORE.token, 386 sessionId = sessionId, 387 pickerIntentAction = pickerIntentAction, 388 pickerSize = Telemetry.PickerSize.COLLAPSED, 389 mediaFilter = telemetryMimeTypeMapping, 390 maxPickedItemsCount = 1, 391 selectedTab = Telemetry.SelectedTab.UNSET_SELECTED_TAB, 392 selectedAlbum = Telemetry.SelectedAlbum.UNSET_SELECTED_ALBUM, 393 isOrderedSelectionSet = false, 394 isAccentColorSet = false, 395 isDefaultTabSet = false, 396 isCloudSearchEnabled = cloudSearch, 397 isLocalSearchEnabled = false, 398 isTranscodingRequested = false, 399 ) 400 401 // Action 402 dispatchReportPhotopickerApiInfoEvent( 403 coroutineScope = backgroundScope, 404 lazyEvents = lazyEvents, 405 photopickerConfiguration = photopickerConfiguration, 406 pickerIntentAction = pickerIntentAction, 407 lazyFeatureManager = lazyFeatureManager, 408 ) 409 advanceTimeBy(delayTimeMillis = 50) 410 411 // Assert 412 assertThat(eventsDispatched).contains(expectedEvent) 413 assertThat(expectedEvent.mediaFilter).isEqualTo(telemetryMimeTypeMapping) 414 } 415 416 @Test <lambda>null417 fun testDispatchReportPhotopickerApiInfoEventWithVideoMimeType() = runTest { 418 // Setup 419 setup(testScope = this) 420 421 val mimeTypeList = arrayListOf("video/jpg") 422 val telemetryMimeTypeMapping = Telemetry.MediaType.VIDEO 423 424 val pickerIntentAction = Telemetry.PickerIntentAction.ACTION_PICK_IMAGES 425 val cloudSearch = lazyFeatureManager.get().isFeatureEnabled(SearchFeature::class.java) 426 val photopickerConfiguration = 427 TestPhotopickerConfiguration.build { 428 action(value = "") 429 sessionId(value = sessionId) 430 callingPackageUid(value = packageUid) 431 runtimeEnv(value = PhotopickerRuntimeEnv.EMBEDDED) 432 mimeTypes(mimeTypeList) 433 } 434 435 val expectedEvent = 436 Event.ReportPhotopickerApiInfo( 437 dispatcherToken = FeatureToken.CORE.token, 438 sessionId = sessionId, 439 pickerIntentAction = pickerIntentAction, 440 pickerSize = Telemetry.PickerSize.COLLAPSED, 441 mediaFilter = telemetryMimeTypeMapping, 442 maxPickedItemsCount = 1, 443 selectedTab = Telemetry.SelectedTab.UNSET_SELECTED_TAB, 444 selectedAlbum = Telemetry.SelectedAlbum.UNSET_SELECTED_ALBUM, 445 isOrderedSelectionSet = false, 446 isAccentColorSet = false, 447 isDefaultTabSet = false, 448 isCloudSearchEnabled = cloudSearch, 449 isLocalSearchEnabled = false, 450 isTranscodingRequested = false, 451 ) 452 453 // Action 454 dispatchReportPhotopickerApiInfoEvent( 455 coroutineScope = backgroundScope, 456 lazyEvents = lazyEvents, 457 photopickerConfiguration = photopickerConfiguration, 458 pickerIntentAction = pickerIntentAction, 459 lazyFeatureManager = lazyFeatureManager, 460 ) 461 advanceTimeBy(delayTimeMillis = 50) 462 463 // Assert 464 assertThat(eventsDispatched).contains(expectedEvent) 465 assertThat(expectedEvent.mediaFilter).isEqualTo(telemetryMimeTypeMapping) 466 } 467 468 @Test <lambda>null469 fun testDispatchReportPhotopickerApiInfoEventWithBothPhotoAndVideoMimeType() = runTest { 470 // Setup 471 setup(testScope = this) 472 473 val mimeTypeList = arrayListOf("image/jpg", "video/mp4") 474 val telemetryMimeTypeMapping = Telemetry.MediaType.PHOTO_VIDEO 475 476 val pickerIntentAction = Telemetry.PickerIntentAction.ACTION_PICK_IMAGES 477 val cloudSearch = lazyFeatureManager.get().isFeatureEnabled(SearchFeature::class.java) 478 val photopickerConfiguration = 479 TestPhotopickerConfiguration.build { 480 action(value = "") 481 sessionId(value = sessionId) 482 callingPackageUid(value = packageUid) 483 runtimeEnv(value = PhotopickerRuntimeEnv.EMBEDDED) 484 mimeTypes(mimeTypeList) 485 } 486 487 val expectedEvent = 488 Event.ReportPhotopickerApiInfo( 489 dispatcherToken = FeatureToken.CORE.token, 490 sessionId = sessionId, 491 pickerIntentAction = pickerIntentAction, 492 pickerSize = Telemetry.PickerSize.COLLAPSED, 493 mediaFilter = telemetryMimeTypeMapping, 494 maxPickedItemsCount = 1, 495 selectedTab = Telemetry.SelectedTab.UNSET_SELECTED_TAB, 496 selectedAlbum = Telemetry.SelectedAlbum.UNSET_SELECTED_ALBUM, 497 isOrderedSelectionSet = false, 498 isAccentColorSet = false, 499 isDefaultTabSet = false, 500 isCloudSearchEnabled = cloudSearch, 501 isLocalSearchEnabled = false, 502 isTranscodingRequested = false, 503 ) 504 505 // Action 506 dispatchReportPhotopickerApiInfoEvent( 507 coroutineScope = backgroundScope, 508 lazyEvents = lazyEvents, 509 photopickerConfiguration = photopickerConfiguration, 510 pickerIntentAction = pickerIntentAction, 511 lazyFeatureManager = lazyFeatureManager, 512 ) 513 advanceTimeBy(delayTimeMillis = 50) 514 515 // Assert 516 assertThat(eventsDispatched).contains(expectedEvent) 517 assertThat(expectedEvent.mediaFilter).isEqualTo(telemetryMimeTypeMapping) 518 } 519 520 @Test <lambda>null521 fun testDispatchReportPhotopickerApiInfoEventWithDefaultPhotoAndVideoMimeType() = runTest { 522 // Setup 523 setup(testScope = this) 524 525 val mimeTypeList = arrayListOf("image/*", "video/*") 526 val telemetryMimeTypeMapping = Telemetry.MediaType.PHOTO_VIDEO 527 528 val pickerIntentAction = Telemetry.PickerIntentAction.ACTION_PICK_IMAGES 529 val cloudSearch = lazyFeatureManager.get().isFeatureEnabled(SearchFeature::class.java) 530 val photopickerConfiguration = 531 TestPhotopickerConfiguration.build { 532 action(value = "") 533 sessionId(value = sessionId) 534 callingPackageUid(value = packageUid) 535 runtimeEnv(value = PhotopickerRuntimeEnv.EMBEDDED) 536 mimeTypes(mimeTypeList) 537 } 538 539 val expectedEvent = 540 Event.ReportPhotopickerApiInfo( 541 dispatcherToken = FeatureToken.CORE.token, 542 sessionId = sessionId, 543 pickerIntentAction = pickerIntentAction, 544 pickerSize = Telemetry.PickerSize.COLLAPSED, 545 mediaFilter = telemetryMimeTypeMapping, 546 maxPickedItemsCount = 1, 547 selectedTab = Telemetry.SelectedTab.UNSET_SELECTED_TAB, 548 selectedAlbum = Telemetry.SelectedAlbum.UNSET_SELECTED_ALBUM, 549 isOrderedSelectionSet = false, 550 isAccentColorSet = false, 551 isDefaultTabSet = false, 552 isCloudSearchEnabled = cloudSearch, 553 isLocalSearchEnabled = false, 554 isTranscodingRequested = false, 555 ) 556 557 // Action 558 dispatchReportPhotopickerApiInfoEvent( 559 coroutineScope = backgroundScope, 560 lazyEvents = lazyEvents, 561 photopickerConfiguration = photopickerConfiguration, 562 pickerIntentAction = pickerIntentAction, 563 lazyFeatureManager = lazyFeatureManager, 564 ) 565 advanceTimeBy(delayTimeMillis = 50) 566 567 // Assert 568 assertThat(eventsDispatched).contains(expectedEvent) 569 assertThat(expectedEvent.mediaFilter).isEqualTo(telemetryMimeTypeMapping) 570 } 571 572 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S) 573 @Test <lambda>null574 fun testDispatchReportPickerAppMediaCapabilities() = runTest { 575 // Setup 576 setup(testScope = this) 577 578 val capabilities = 579 ApplicationMediaCapabilities.Builder().addUnsupportedHdrType(HdrType.HDR10).build() 580 581 val photopickerConfiguration = 582 TestPhotopickerConfiguration.build { 583 action(value = "") 584 sessionId(value = sessionId) 585 callingPackageUid(value = packageUid) 586 runtimeEnv(value = PhotopickerRuntimeEnv.EMBEDDED) 587 appMediaCapabilities(capabilities) 588 } 589 590 val expectedEvent = 591 Event.ReportPickerAppMediaCapabilities( 592 dispatcherToken = FeatureToken.CORE.token, 593 sessionId = sessionId, 594 supportedHdrTypes = intArrayOf(), 595 unsupportedHdrTypes = intArrayOf(Telemetry.HdrTypes.HDR10_UNSUPPORTED.type), 596 ) 597 598 // Action 599 dispatchReportPickerAppMediaCapabilities( 600 coroutineScope = backgroundScope, 601 lazyEvents = lazyEvents, 602 photopickerConfiguration = photopickerConfiguration, 603 ) 604 advanceTimeBy(delayTimeMillis = 50) 605 606 // Assert 607 assertThat(eventsDispatched.size).isEqualTo(1) 608 assertThat(eventsDispatched.get(0).toString()).isEqualTo(expectedEvent.toString()) 609 } 610 } 611