Changeset 231913 in webkit


Ignore:
Timestamp:
May 17, 2018 11:44:33 AM (6 years ago)
Author:
eric.carlson@apple.com
Message:

[iOS] Update AirPlay route monitoring
https://bugs.webkit.org/show_bug.cgi?id=185706
<rdar://problem/40230677>

Reviewed by Jer Noble.

Use an AVRouteDetector instead of an MPVolumeView and an MPAVRoutingController for AirPlay
route detection and availability monitoring.

No new tests, tested manually.

  • html/MediaElementSession.cpp:

(WebCore::MediaElementSession::hasWirelessPlaybackTargets): No need to update m_hasPlaybackTargets
manually, it is always updated by the session manager when route availability changes.

  • platform/audio/ios/MediaSessionManagerIOS.mm:

(-[WebMediaSessionHelper dealloc]): Pull the logic from safelyTearDown inline.
(-[WebMediaSessionHelper hasWirelessTargetsAvailable]): Use the AVRouteDetector.
(-[WebMediaSessionHelper startMonitoringAirPlayRoutes]): Ditto. Simplify logic, there is no
need to dispatch twice.
(-[WebMediaSessionHelper stopMonitoringAirPlayRoutes]): Don't release the route detector
completely, just disable route detection, because AVRouteDetector is a lightweight object so
it is not worth the overhead of dealloc/realloc to disable/enable route detection.
(-[WebMediaSessionHelper interruption:]): Use callOnWebThreadOrDispatchAsyncOnMainThread
instead of WebThreadRun so it works correctly in WK2 as well as in WK1.
(-[WebMediaSessionHelper applicationWillEnterForeground:]): Ditto.
(-[WebMediaSessionHelper applicationDidBecomeActive:]): Ditto.
(-[WebMediaSessionHelper applicationWillResignActive:]): Ditto.
(-[WebMediaSessionHelper wirelessRoutesAvailableDidChange:]): Ditto.
(-[WebMediaSessionHelper applicationDidEnterBackground:]): Ditto.
(safelyTearDown): Deleted.

Location:
trunk/Source/WebCore
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r231911 r231913  
     12018-05-17  Eric Carlson  <eric.carlson@apple.com>
     2
     3        [iOS] Update AirPlay route monitoring
     4        https://bugs.webkit.org/show_bug.cgi?id=185706
     5        <rdar://problem/40230677>
     6
     7        Reviewed by Jer Noble.
     8
     9        Use an AVRouteDetector instead of an MPVolumeView and an MPAVRoutingController for AirPlay
     10        route detection and availability monitoring.
     11
     12        No new tests, tested manually.
     13
     14        * html/MediaElementSession.cpp:
     15        (WebCore::MediaElementSession::hasWirelessPlaybackTargets): No need to update m_hasPlaybackTargets
     16        manually, it is always updated by the session manager when route availability changes.
     17
     18        * platform/audio/ios/MediaSessionManagerIOS.mm:
     19        (-[WebMediaSessionHelper dealloc]): Pull the logic from safelyTearDown inline.
     20        (-[WebMediaSessionHelper hasWirelessTargetsAvailable]): Use the AVRouteDetector.
     21        (-[WebMediaSessionHelper startMonitoringAirPlayRoutes]): Ditto.  Simplify logic, there is no
     22        need to dispatch twice.
     23        (-[WebMediaSessionHelper stopMonitoringAirPlayRoutes]): Don't release the route detector
     24        completely, just disable route detection, because AVRouteDetector is a lightweight object so
     25        it is not worth the overhead of dealloc/realloc to disable/enable route detection.
     26        (-[WebMediaSessionHelper interruption:]): Use callOnWebThreadOrDispatchAsyncOnMainThread
     27        instead of WebThreadRun so it works correctly in WK2 as well as in WK1.
     28        (-[WebMediaSessionHelper applicationWillEnterForeground:]): Ditto.
     29        (-[WebMediaSessionHelper applicationDidBecomeActive:]): Ditto.
     30        (-[WebMediaSessionHelper applicationWillResignActive:]): Ditto.
     31        (-[WebMediaSessionHelper wirelessRoutesAvailableDidChange:]): Ditto.
     32        (-[WebMediaSessionHelper applicationDidEnterBackground:]): Ditto.
     33        (safelyTearDown): Deleted.
     34
    1352018-05-17  Chris Dumez  <cdumez@apple.com>
    236
  • trunk/Source/WebCore/html/MediaElementSession.cpp

    r231817 r231913  
    550550bool MediaElementSession::hasWirelessPlaybackTargets() const
    551551{
    552 #if PLATFORM(IOS)
    553     // FIXME: consolidate Mac and iOS implementations
    554     m_hasPlaybackTargets = PlatformMediaSessionManager::sharedManager().hasWirelessTargetsAvailable();
    555 #endif
    556 
    557552    INFO_LOG(LOGIDENTIFIER, "returning ", m_hasPlaybackTargets);
    558553
  • trunk/Source/WebCore/platform/audio/ios/MediaSessionManagerIOS.mm

    r231866 r231913  
    3535#import "WebCoreThreadRun.h"
    3636#import <AVFoundation/AVAudioSession.h>
     37#import <AVFoundation/AVRouteDetector.h>
    3738#import <UIKit/UIApplication.h>
    3839#import <objc/runtime.h>
     
    4647#import <MediaPlayer/MPMediaItem.h>
    4748#import <MediaPlayer/MPNowPlayingInfoCenter.h>
    48 #import <MediaPlayer/MPVolumeView.h>
    4949#import <pal/spi/ios/MediaPlayerSPI.h>
    5050#endif
     
    5252SOFT_LINK_FRAMEWORK(AVFoundation)
    5353SOFT_LINK_CLASS(AVFoundation, AVAudioSession)
     54SOFT_LINK_CLASS(AVFoundation, AVRouteDetector)
    5455SOFT_LINK_POINTER(AVFoundation, AVAudioSessionInterruptionNotification, NSString *)
    5556SOFT_LINK_POINTER(AVFoundation, AVAudioSessionInterruptionTypeKey, NSString *)
    5657SOFT_LINK_POINTER(AVFoundation, AVAudioSessionInterruptionOptionKey, NSString *)
     58SOFT_LINK_POINTER(AVFoundation, AVRouteDetectorMultipleRoutesDetectedDidChangeNotification, NSString *)
    5759
    5860#define AVAudioSession getAVAudioSessionClass()
     
    7678#if HAVE(MEDIA_PLAYER)
    7779SOFT_LINK_FRAMEWORK(MediaPlayer)
    78 SOFT_LINK_CLASS(MediaPlayer, MPAVRoutingController)
    7980SOFT_LINK_CLASS(MediaPlayer, MPNowPlayingInfoCenter)
    80 SOFT_LINK_CLASS(MediaPlayer, MPVolumeView)
    8181SOFT_LINK_POINTER(MediaPlayer, MPMediaItemPropertyTitle, NSString *)
    8282SOFT_LINK_POINTER(MediaPlayer, MPMediaItemPropertyPlaybackDuration, NSString *)
    8383SOFT_LINK_POINTER(MediaPlayer, MPNowPlayingInfoPropertyElapsedPlaybackTime, NSString *)
    8484SOFT_LINK_POINTER(MediaPlayer, MPNowPlayingInfoPropertyPlaybackRate, NSString *)
    85 SOFT_LINK_POINTER(MediaPlayer, MPVolumeViewWirelessRoutesAvailableDidChangeNotification, NSString *)
    8685SOFT_LINK_POINTER(MediaPlayer, kMRMediaRemoteNowPlayingInfoUniqueIdentifier, NSString *)
    8786
     
    9089#define MPNowPlayingInfoPropertyElapsedPlaybackTime getMPNowPlayingInfoPropertyElapsedPlaybackTime()
    9190#define MPNowPlayingInfoPropertyPlaybackRate getMPNowPlayingInfoPropertyPlaybackRate()
    92 #define MPVolumeViewWirelessRoutesAvailableDidChangeNotification getMPVolumeViewWirelessRoutesAvailableDidChangeNotification()
    9391#define kMRMediaRemoteNowPlayingInfoUniqueIdentifier getkMRMediaRemoteNowPlayingInfoUniqueIdentifier()
    9492#endif // HAVE(MEDIA_PLAYER)
     
    104102    MediaSessionManageriOS* _callback;
    105103
    106 #if HAVE(MEDIA_PLAYER)
    107     RetainPtr<MPVolumeView> _volumeView;
    108     RetainPtr<MPAVRoutingController> _airPlayPresenceRoutingController;
     104    RetainPtr<AVRouteDetector> _routeDetector;
    109105    bool _monitoringAirPlayRoutes;
    110106    bool _startMonitoringAirPlayRoutesPending;
    111 #endif
    112107}
    113108
     
    347342}
    348343
    349 #if HAVE(MEDIA_PLAYER)
    350 static void safelyTearDown(RetainPtr<MPVolumeView> volumeView, RetainPtr<MPAVRoutingController> routingController)
    351 {
    352     dispatch_async(dispatch_get_main_queue(), [volumeView = WTFMove(volumeView), routingController = WTFMove(routingController)] () mutable {
    353         LOG(Media, "safelyTearDown - dipatched to UI thread.");
    354         BEGIN_BLOCK_OBJC_EXCEPTIONS
    355         [routingController setDiscoveryMode:MPRouteDiscoveryModeDisabled];
    356         volumeView.clear();
    357         routingController.clear();
    358         END_BLOCK_OBJC_EXCEPTIONS
    359     });
    360 }
    361 #endif
    362 
    363344- (void)dealloc
    364345{
     
    366347
    367348#if HAVE(MEDIA_PLAYER)
    368     if (!pthread_main_np())
    369         safelyTearDown(WTFMove(_volumeView), WTFMove(_airPlayPresenceRoutingController));
    370     else
    371         [_airPlayPresenceRoutingController setDiscoveryMode:MPRouteDiscoveryModeDisabled];
     349    if (!pthread_main_np()) {
     350        dispatch_async(dispatch_get_main_queue(), [routeDetector = WTFMove(_routeDetector)] () mutable {
     351            LOG(Media, "safelyTearDown - dipatched to UI thread.");
     352            BEGIN_BLOCK_OBJC_EXCEPTIONS
     353            routeDetector.get().routeDetectionEnabled = NO;
     354            routeDetector.clear();
     355            END_BLOCK_OBJC_EXCEPTIONS
     356        });
     357    } else
     358        _routeDetector.get().routeDetectionEnabled = NO;
    372359#endif
    373360
     
    385372{
    386373    LOG(Media, "-[WebMediaSessionHelper hasWirelessTargetsAvailable]");
    387 #if HAVE(MEDIA_PLAYER)
    388     return _volumeView ? [_volumeView areWirelessRoutesAvailable] : NO;
    389 #else
    390     return NO;
    391 #endif
     374    return _routeDetector.get().multipleRoutesDetected;
    392375}
    393376
     
    403386        return;
    404387
     388    if (_routeDetector) {
     389        _routeDetector.get().routeDetectionEnabled = YES;
     390        return;
     391    }
     392
    405393    _startMonitoringAirPlayRoutesPending = true;
    406394
    407395    LOG(Media, "-[WebMediaSessionHelper startMonitoringAirPlayRoutes]");
    408396
    409     dispatch_async(dispatch_get_main_queue(), [protectedSelf = RetainPtr<WebMediaSessionHelper>(self)] () mutable {
    410         LOG(Media, "-[WebMediaSessionHelper startMonitoringAirPlayRoutes] - dipatched to main queue");
    411 
    412         BEGIN_BLOCK_OBJC_EXCEPTIONS
    413         RetainPtr<MPVolumeView> volumeView = adoptNS([allocMPVolumeViewInstance() init]);
    414         RetainPtr<MPAVRoutingController> routingController = adoptNS([allocMPAVRoutingControllerInstance() initWithName:@"WebCore - HTML media element checking for AirPlay route presence"]);
    415 
    416         [routingController setDiscoveryMode:MPRouteDiscoveryModePresence];
    417 
    418         callOnWebThreadOrDispatchAsyncOnMainThread([protectedSelf = WTFMove(protectedSelf), volumeView = WTFMove(volumeView), routingController = WTFMove(routingController)]() mutable {
    419 
    420             protectedSelf->_startMonitoringAirPlayRoutesPending = false;
    421 
    422             if (!protectedSelf->_monitoringAirPlayRoutes) {
    423                 safelyTearDown(WTFMove(volumeView), WTFMove(routingController));
    424                 return;
    425             }
    426 
    427             ASSERT(!protectedSelf->_volumeView);
    428             protectedSelf->_volumeView = volumeView;
    429 
    430             [[NSNotificationCenter defaultCenter] addObserver:protectedSelf.get() selector:@selector(wirelessRoutesAvailableDidChange:) name:MPVolumeViewWirelessRoutesAvailableDidChangeNotification object:volumeView.get()];
    431 
    432             ASSERT(!protectedSelf->_airPlayPresenceRoutingController);
    433             protectedSelf->_airPlayPresenceRoutingController = routingController;
    434         });
    435         END_BLOCK_OBJC_EXCEPTIONS
    436 
     397    callOnWebThreadOrDispatchAsyncOnMainThread([protectedSelf = WTFMove(self)]() mutable {
     398        ASSERT(!protectedSelf->_routeDetector);
     399
     400        if (protectedSelf->_callback) {
     401            BEGIN_BLOCK_OBJC_EXCEPTIONS
     402            protectedSelf->_routeDetector = adoptNS([allocAVRouteDetectorInstance() init]);
     403            protectedSelf->_routeDetector.get().routeDetectionEnabled = protectedSelf->_monitoringAirPlayRoutes;
     404            [[NSNotificationCenter defaultCenter] addObserver:protectedSelf selector:@selector(wirelessRoutesAvailableDidChange:) name:getAVRouteDetectorMultipleRoutesDetectedDidChangeNotification() object:protectedSelf->_routeDetector.get()];
     405            END_BLOCK_OBJC_EXCEPTIONS
     406        }
     407
     408        protectedSelf->_startMonitoringAirPlayRoutesPending = false;
    437409    });
    438410}
     
    443415        return;
    444416
     417    LOG(Media, "-[WebMediaSessionHelper stopMonitoringAirPlayRoutes]");
     418
    445419    _monitoringAirPlayRoutes = false;
    446 
    447     LOG(Media, "-[WebMediaSessionHelper stopMonitoringAirPlayRoutes]");
    448 
    449     RetainPtr<MPVolumeView> volumeView = _volumeView;
    450     RetainPtr<MPAVRoutingController> airPlayPresenceRoutingController = _airPlayPresenceRoutingController;
    451 
    452     _volumeView.clear();
    453     _airPlayPresenceRoutingController.clear();
    454 
    455     if (volumeView)
    456         [[NSNotificationCenter defaultCenter] removeObserver:self name:MPVolumeViewWirelessRoutesAvailableDidChangeNotification object:volumeView.get()];
    457 
    458     safelyTearDown(WTFMove(volumeView), WTFMove(airPlayPresenceRoutingController));
     420    _routeDetector.get().routeDetectionEnabled = NO;
    459421}
    460422#endif // HAVE(MEDIA_PLAYER)
     
    473435        flags = PlatformMediaSession::MayResumePlaying;
    474436
    475     WebThreadRun(^{
    476         if (!_callback)
     437    callOnWebThreadOrDispatchAsyncOnMainThread([protectedSelf = WTFMove(self), type, flags]() mutable {
     438        auto* callback = protectedSelf->_callback;
     439        if (!callback)
    477440            return;
    478441
    479442        if (type == AVAudioSessionInterruptionTypeBegan)
    480             _callback->beginInterruption(PlatformMediaSession::SystemInterruption);
     443            callback->beginInterruption(PlatformMediaSession::SystemInterruption);
    481444        else
    482             _callback->endInterruption(flags);
     445            callback->endInterruption(flags);
    483446
    484447    });
     
    495458
    496459    BOOL isSuspendedUnderLock = [[[notification userInfo] objectForKey:@"isSuspendedUnderLock"] boolValue];
    497 
    498     WebThreadRun(^{
    499         if (!_callback)
    500             return;
    501 
    502         _callback->applicationWillEnterForeground(isSuspendedUnderLock);
     460    callOnWebThreadOrDispatchAsyncOnMainThread([protectedSelf = WTFMove(self), isSuspendedUnderLock]() mutable {
     461        if (auto* callback = protectedSelf->_callback)
     462            callback->applicationWillEnterForeground(isSuspendedUnderLock);
    503463    });
    504464}
     
    513473    LOG(Media, "-[WebMediaSessionHelper applicationDidBecomeActive]");
    514474
    515     WebThreadRun(^{
    516         if (!_callback)
    517             return;
    518 
    519         _callback->applicationDidBecomeActive();
     475    callOnWebThreadOrDispatchAsyncOnMainThread([protectedSelf = WTFMove(self)]() mutable {
     476        if (auto* callback = protectedSelf->_callback)
     477            callback->applicationDidBecomeActive();
    520478    });
    521479}
     
    530488    LOG(Media, "-[WebMediaSessionHelper applicationWillResignActive]");
    531489
    532     WebThreadRun(^{
    533         if (!_callback)
    534             return;
    535 
    536         _callback->applicationWillBecomeInactive();
     490    callOnWebThreadOrDispatchAsyncOnMainThread([protectedSelf = WTFMove(self)]() mutable {
     491        if (auto* callback = protectedSelf->_callback)
     492            callback->applicationWillBecomeInactive();
    537493    });
    538494}
     
    542498    UNUSED_PARAM(notification);
    543499
    544     if (!_callback)
     500    if (!_callback || !_monitoringAirPlayRoutes)
    545501        return;
    546502
    547503    LOG(Media, "-[WebMediaSessionHelper wirelessRoutesAvailableDidChange]");
    548504
    549     WebThreadRun(^{
    550         if (!_callback)
    551             return;
    552 
    553         _callback->externalOutputDeviceAvailableDidChange();
     505    callOnWebThreadOrDispatchAsyncOnMainThread([protectedSelf = WTFMove(self)]() mutable {
     506        if (auto* callback = protectedSelf->_callback)
     507            callback->externalOutputDeviceAvailableDidChange();
    554508    });
    555509}
     
    563517
    564518    BOOL isSuspendedUnderLock = [[[notification userInfo] objectForKey:@"isSuspendedUnderLock"] boolValue];
    565 
    566     WebThreadRun(^{
    567         if (!_callback)
    568             return;
    569 
    570         _callback->applicationDidEnterBackground(isSuspendedUnderLock);
     519    callOnWebThreadOrDispatchAsyncOnMainThread([protectedSelf = WTFMove(self), isSuspendedUnderLock]() mutable {
     520        if (auto* callback = protectedSelf->_callback)
     521            callback->applicationDidEnterBackground(isSuspendedUnderLock);
    571522    });
    572523}
Note: See TracChangeset for help on using the changeset viewer.