 
     func provider(_ provider: CXProvider, perform action: CXStartCallAction) {
         listeners.forEach {
-            $0.listener?.performStartCall?(UUID: action.callUUID,
-                                           isVideo: action.isVideo)
+            let listener = $0 as! JMCallKitListener
+            listener.performStartCall?(UUID: action.callUUID, isVideo: action.isVideo)
         }
 
         action.fulfill()


internal final class JMCallKitEmitter: NSObject, CXProviderDelegate {

    private var listeners = Set<JMCallKitEventListenerWrapper>()

    internal override init() {}

    // MARK: - Add/remove listeners

    func addListener(_ listener: JMCallKitListener) {
        let wrapper = JMCallKitEventListenerWrapper(listener: listener)
        listeners.insert(wrapper)
    }

    func removeListener(_ listener: JMCallKitListener) {
        // XXX Constructing a new JMCallKitEventListenerWrapper instance in
        // order to remove the specified listener from listeners is (1) a bit
        // funny (though may make a statement about performance) and (2) not
        // really an option because the specified listener may already be
        // executing its dealloc (like RNCallKit).
        listeners.forEach {
            // 1. JMCallKitEventListenerWrapper weakly references
            //    JMCallKitListener so it may be nice to clean
            //    JMCallKitEventListenerWrapperinstances up if they've lost
            //    their associated JMCallKitListener instances (e.g. for
            //    example, because whoever did addListener forgot to
            //    removeListener). Unfortunately, I don't know how to do it
            //    because JMCallKitEventListenerWrapper is a struct.
            //
            // 2. XXX JMCallKitEventListenerWrapper implements the weird
            //    equality by JMCallKitListener hash which (1) I don't
            //    understand and (2) I don't know how to invoke without
            //    duplicating.
            if ($0.hashValue == listener.hash) {
                listeners.remove($0)
            }
        }
    }

    // MARK: - CXProviderDelegate

    func providerDidReset(_ provider: CXProvider) {
        listeners.forEach { $0.listener?.providerDidReset?() }
    }

    func provider(_ provider: CXProvider, perform action: CXAnswerCallAction) {
        listeners.forEach {
            $0.listener?.performAnswerCall?(UUID: action.callUUID)
        }

        action.fulfill()

    func provider(_ provider: CXProvider,
                  didActivate audioSession: AVAudioSession) {
        listeners.forEach {
            let listener = $0 as! JMCallKitListener
            listener.providerDidActivateAudioSession?(session: audioSession)
        }
    }

    func provider(_ provider: CXProvider,
                  didDeactivate audioSession: AVAudioSession) {
        listeners.forEach {
            let listener = $0 as! JMCallKitListener
            listener.providerDidDeactivateAudioSession?(session: audioSession)
        }
    }
}
