Skip to content

Commit

Permalink
[iOS] Adopt AVAudioSession to check if CarPlay is connected
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=260321
rdar://112481563

Reviewed by Eric Carlson.

Migrated MediaSessionHelperIOS from AVSystemController SPI to AVAudioSession API to check if CarPlay
is connected.

* Source/WebCore/PAL/pal/cocoa/AVFoundationSoftLink.h:
* Source/WebCore/PAL/pal/cocoa/AVFoundationSoftLink.mm:
* Source/WebCore/platform/audio/ios/MediaSessionHelperIOS.mm:
(MediaSessionHelperiOS::MediaSessionHelperiOS):
(MediaSessionHelperiOS::mediaServerConnectionDied):
(MediaSessionHelperiOS::updateCarPlayIsConnected):
(MediaSessionHelperiOS::setIsPlayingToAutomotiveHeadUnit):
(-[WebMediaSessionHelper initWithCallback:]):
(-[WebMediaSessionHelper mediaServerConnectionDied:]):
(-[WebMediaSessionHelper activeOutputDeviceDidChange:]):
(-[WebMediaSessionHelper carPlayIsConnectedDidChange:]): Deleted.

Canonical link: https://commits.webkit.org/267050@main
  • Loading branch information
aestes committed Aug 18, 2023
1 parent cf812ea commit d0daa33
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 49 deletions.
5 changes: 5 additions & 0 deletions Source/WebCore/PAL/pal/cocoa/AVFoundationSoftLink.h
Original file line number Diff line number Diff line change
Expand Up @@ -372,4 +372,9 @@ SOFT_LINK_CONSTANT_FOR_HEADER(PAL, AVFoundation, AVAssetExportPresetHighestQuali
SOFT_LINK_CONSTANT_MAY_FAIL_FOR_HEADER(PAL, AVFoundation, AVURLAssetExtendedMIMETypePlayabilityTreatPlaylistMIMETypesAsISOBMFFMediaDataContainersKey, NSString *)
#define AVURLAssetExtendedMIMETypePlayabilityTreatPlaylistMIMETypesAsISOBMFFMediaDataContainersKey PAL::get_AVFoundation_AVURLAssetExtendedMIMETypePlayabilityTreatPlaylistMIMETypesAsISOBMFFMediaDataContainersKey()

#if HAVE(AVAUDIOSESSION)
SOFT_LINK_CONSTANT_FOR_HEADER(PAL, AVFoundation, AVAudioSessionPortCarAudio, NSString *)
#define AVAudioSessionPortCarAudio PAL::get_AVFoundation_AVAudioSessionPortCarAudio()
#endif // HAVE(AVAUDIOSESSION)

#endif // USE(AVFOUNDATION)
4 changes: 4 additions & 0 deletions Source/WebCore/PAL/pal/cocoa/AVFoundationSoftLink.mm
Original file line number Diff line number Diff line change
Expand Up @@ -271,4 +271,8 @@ static BOOL justReturnsNO()

SOFT_LINK_CONSTANT_MAY_FAIL_FOR_SOURCE_WITH_EXPORT(PAL, AVFoundation, AVURLAssetExtendedMIMETypePlayabilityTreatPlaylistMIMETypesAsISOBMFFMediaDataContainersKey, NSString *, PAL_EXPORT)

#if HAVE(AVAUDIOSESSION)
SOFT_LINK_CONSTANT_FOR_SOURCE_WITH_EXPORT(PAL, AVFoundation, AVAudioSessionPortCarAudio, NSString *, PAL_EXPORT)
#endif // HAVE(AVAUDIOSESSION)

#endif // USE(AVFOUNDATION)
70 changes: 21 additions & 49 deletions Source/WebCore/platform/audio/ios/MediaSessionHelperIOS.mm
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,7 @@
SOFT_LINK_PRIVATE_FRAMEWORK_OPTIONAL(Celestial)
SOFT_LINK_CLASS_OPTIONAL(Celestial, AVSystemController)
SOFT_LINK_CONSTANT_MAY_FAIL(Celestial, AVSystemController_PIDToInheritApplicationStateFrom, NSString *)
SOFT_LINK_CONSTANT_MAY_FAIL(Celestial, AVSystemController_CarPlayIsConnectedAttribute, NSString *)
SOFT_LINK_CONSTANT_MAY_FAIL(Celestial, AVSystemController_CarPlayIsConnectedDidChangeNotification, NSString *)
SOFT_LINK_CONSTANT_MAY_FAIL(Celestial, AVSystemController_CarPlayIsConnectedNotificationParameter, NSString *)
SOFT_LINK_CONSTANT_MAY_FAIL(Celestial, AVSystemController_ServerConnectionDiedNotification, NSString *)
SOFT_LINK_CONSTANT_MAY_FAIL(Celestial, AVSystemController_SubscribeToNotificationsAttribute, NSString *)
#endif

using namespace WebCore;
Expand Down Expand Up @@ -93,9 +89,9 @@ - (void)stopMonitoringAirPlayRoutes;
MediaSessionHelperIOS();

void externalOutputDeviceAvailableDidChange();
void updateCarPlayIsConnected();
#if HAVE(CELESTIAL)
void mediaServerConnectionDied();
void updateCarPlayIsConnected(std::optional<bool>&&);
#endif
#if PLATFORM(IOS_FAMILY) && !PLATFORM(IOS_FAMILY_SIMULATOR) && !PLATFORM(MACCATALYST) && !PLATFORM(WATCHOS)
void activeAudioRouteDidChange(bool);
Expand Down Expand Up @@ -235,9 +231,7 @@ - (void)stopMonitoringAirPlayRoutes;
setIsExternalOutputDeviceAvailable([m_objcObserver hasWirelessTargetsAvailable]);
END_BLOCK_OBJC_EXCEPTIONS

#if HAVE(CELESTIAL)
updateCarPlayIsConnected(std::nullopt);
#endif
updateCarPlayIsConnected();
}

void MediaSessionHelperIOS::providePresentingApplicationPID(int pid, ShouldOverride shouldOverride)
Expand Down Expand Up @@ -282,40 +276,34 @@ - (void)stopMonitoringAirPlayRoutes;
#if HAVE(CELESTIAL)
void MediaSessionHelperIOS::mediaServerConnectionDied()
{
updateCarPlayIsConnected(std::nullopt);

// FIXME: Remove these once rdar://27662716 lands
if (canLoadAVSystemController_CarPlayIsConnectedDidChangeNotification() && canLoadAVSystemController_SubscribeToNotificationsAttribute())
[[getAVSystemControllerClass() sharedAVSystemController] setAttribute:@[getAVSystemController_CarPlayIsConnectedDidChangeNotification()] forKey:getAVSystemController_SubscribeToNotificationsAttribute() error:nil];

if (m_presentedApplicationPID) {
auto presentedApplicationPID = std::exchange(m_presentedApplicationPID, { });
callOnMainRunLoop([presentedApplicationPID] {
sharedHelper().providePresentingApplicationPID(*presentedApplicationPID);
});
}
}
#endif // HAVE(CELESTIAL)

void MediaSessionHelperIOS::updateCarPlayIsConnected(std::optional<bool>&& carPlayIsConnected)
void MediaSessionHelperIOS::updateCarPlayIsConnected()
{
if (carPlayIsConnected) {
setIsPlayingToAutomotiveHeadUnit(carPlayIsConnected.value());
return;
}

if (!canLoadAVSystemController_CarPlayIsConnectedAttribute()) {
setIsPlayingToAutomotiveHeadUnit(false);
return;
#if HAVE(AVAUDIOSESSION)
AVAudioSession *audioSession = [PAL::getAVAudioSessionClass() sharedInstance];
for (AVAudioSessionPortDescription *output in audioSession.currentRoute.outputs) {
if ([output.portType isEqualToString:AVAudioSessionPortCarAudio]) {
setIsPlayingToAutomotiveHeadUnit(true);
return;
}
}
#endif // HAVE(AVAUDIOSESSION)

setIsPlayingToAutomotiveHeadUnit([[[getAVSystemControllerClass() sharedAVSystemController] attributeForKey:getAVSystemController_CarPlayIsConnectedAttribute()] boolValue]);
setIsPlayingToAutomotiveHeadUnit(false);
}

void MediaSessionHelperIOS::setIsPlayingToAutomotiveHeadUnit(bool isPlaying)
{
isPlayingToAutomotiveHeadUnitDidChange(isPlaying ? PlayingToAutomotiveHeadUnit::Yes : PlayingToAutomotiveHeadUnit::No);
}
#endif // HAVE(CELESTIAL)

#if PLATFORM(IOS_FAMILY) && !PLATFORM(IOS_FAMILY_SIMULATOR) && !PLATFORM(MACCATALYST) && !PLATFORM(WATCHOS)
void MediaSessionHelperIOS::activeAudioRouteDidChange(bool shouldPause)
Expand Down Expand Up @@ -361,17 +349,11 @@ - (id)initWithCallback:(MediaSessionHelperIOS&)callback
[center addObserver:self selector:@selector(applicationWillResignActive:) name:WebUIApplicationWillResignActiveNotification object:nil];
[center addObserver:self selector:@selector(applicationDidEnterBackground:) name:PAL::get_UIKit_UIApplicationDidEnterBackgroundNotification() object:nil];
[center addObserver:self selector:@selector(applicationDidEnterBackground:) name:WebUIApplicationDidEnterBackgroundNotification object:nil];
#if PLATFORM(IOS_FAMILY) && !PLATFORM(IOS_FAMILY_SIMULATOR) && !PLATFORM(MACCATALYST) && !PLATFORM(WATCHOS)
[center addObserver:self selector:@selector(activeOutputDeviceDidChange:) name:PAL::get_AVFoundation_AVAudioSessionRouteChangeNotification() object:nil];
#endif

#if HAVE(CELESTIAL)
if (canLoadAVSystemController_ServerConnectionDiedNotification())
[center addObserver:self selector:@selector(mediaServerConnectionDied:) name:getAVSystemController_ServerConnectionDiedNotification() object:nil];
if (canLoadAVSystemController_CarPlayIsConnectedDidChangeNotification())
[center addObserver:self selector:@selector(carPlayIsConnectedDidChange:) name:getAVSystemController_CarPlayIsConnectedDidChangeNotification() object:nil];
if (canLoadAVSystemController_CarPlayIsConnectedDidChangeNotification() && canLoadAVSystemController_SubscribeToNotificationsAttribute())
[[getAVSystemControllerClass() sharedAVSystemController] setAttribute:@[getAVSystemController_CarPlayIsConnectedDidChangeNotification()] forKey:getAVSystemController_SubscribeToNotificationsAttribute() error:nil];
#endif

// Now playing won't work unless we turn on the delivery of remote control events.
Expand Down Expand Up @@ -540,35 +522,25 @@ - (void)mediaServerConnectionDied:(NSNotification *)notification
callback->mediaServerConnectionDied();
});
}

- (void)carPlayIsConnectedDidChange:(NSNotification *)notification
{
std::optional<bool> carPlayIsConnected;
if (notification && canLoadAVSystemController_CarPlayIsConnectedNotificationParameter()) {
NSNumber *nsCarPlayIsConnected = [[notification userInfo] valueForKey:getAVSystemController_CarPlayIsConnectedNotificationParameter()];
if (nsCarPlayIsConnected)
carPlayIsConnected = [nsCarPlayIsConnected boolValue];
}

callOnWebThreadOrDispatchAsyncOnMainThread([self, protectedSelf = retainPtr(self), carPlayIsConnected = WTFMove(carPlayIsConnected)]() mutable {
if (auto callback = _callback.get())
callback->updateCarPlayIsConnected(WTFMove(carPlayIsConnected));
});
}
#endif // HAVE(CELESTIAL)

#if PLATFORM(IOS_FAMILY) && !PLATFORM(IOS_FAMILY_SIMULATOR) && !PLATFORM(MACCATALYST) && !PLATFORM(WATCHOS)
- (void)activeOutputDeviceDidChange:(NSNotification *)notification
{
bool shouldPause = [[notification.userInfo objectForKey:PAL::get_AVFoundation_AVAudioSessionRouteChangeReasonKey()] unsignedIntegerValue] == AVAudioSessionRouteChangeReasonOldDeviceUnavailable;
LOG(Media, "-[WebMediaSessionHelper activeOutputDeviceDidChange:]");

bool shouldPause = [[notification.userInfo objectForKey:AVAudioSessionRouteChangeReasonKey] unsignedIntegerValue] == AVAudioSessionRouteChangeReasonOldDeviceUnavailable;
callOnWebThreadOrDispatchAsyncOnMainThread([self, protectedSelf = retainPtr(self), shouldPause]() {
if (auto callback = _callback.get()) {
callback->updateCarPlayIsConnected();
#if PLATFORM(IOS_FAMILY) && !PLATFORM(IOS_FAMILY_SIMULATOR) && !PLATFORM(MACCATALYST) && !PLATFORM(WATCHOS)
callback->activeAudioRouteDidChange(shouldPause);
callback->activeVideoRouteDidChange();
#else
UNUSED_PARAM(shouldPause);
#endif
}
});
}
#endif

@end

Expand Down

0 comments on commit d0daa33

Please sign in to comment.