Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Audio pass-through failed due to a timing issue. #1559

Closed
zhouxin627 opened this issue Feb 19, 2020 · 5 comments
Closed

Audio pass-through failed due to a timing issue. #1559

zhouxin627 opened this issue Feb 19, 2020 · 5 comments
Assignees
Labels
bug A defect in the library manager-lifecycle Relating to the manager layer - lifecycle manager Waiting for Feedback Maintainers are waiting for feedback from an author or contributor
Projects

Comments

@zhouxin627
Copy link
Contributor

zhouxin627 commented Feb 19, 2020

Bug Report

Audio pass-through failed due to a timing issue.

Preconditions

  1. Connect the head unit to the phone via BT+USB
  2. The app is a VR app.
Reproduction Steps
  1. Activate App
  2. Click PTT to start APT
  3. Click PTT again immediately to stop the first APT and start the second APT
Expected Behavior

The second APT recording successful.

Observed Behavior

The second APT recording failed.

Proxy will clear audioPassThruHandler after sending handler(request, response, error) to App.
When the user clicks PTT again immediately to stop the first APT and start the second APT,
the audioPassThruHandler of the second APT will be cleared due to a timing issue.

Sequence:

  1. Proxy sends handler(request, response, error) of the first APT to App.
  2. App starts the second APT and creates the APTHandler of the second APT.
  3. Proxy clears the APTHandler.
    (Proxy should clear the APTHandler of the first APT, but it clears the APTHandler of the second APT just updated)
  4. App can't use the APTHandler of the second APT, so the issue occurs.

I think the right sequence should be as follows:
3→1→2

SDLResponseDispatcher.m

// Called by notifications
- (void)sdl_runHandlersForResponse:(SDLRPCResponseNotification *)notification {
    if (![notification isResponseKindOfClass:[SDLRPCResponse class]]) {
        return;
    }

    __kindof SDLRPCResponse *response = notification.response;

    NSError *error = nil;
    if (![response.success boolValue]) {
        error = [NSError sdl_lifecycle_rpcErrorWithDescription:response.resultCode andReason:response.info];
    }

    // Find the appropriate request completion handler, remove the request and response handler
    SDLResponseHandler handler = self.rpcResponseHandlerMap[response.correlationID];
    SDLRPCRequest *request = self.rpcRequestDictionary[response.correlationID];
    [self.rpcRequestDictionary safeRemoveObjectForKey:response.correlationID];
    [self.rpcResponseHandlerMap safeRemoveObjectForKey:response.correlationID];

    // Run the response handler
    if (handler) {
        if (!response.success.boolValue) {
            SDLLogW(@"Request failed: %@, response: %@, error: %@", request, response, error);
        }
	handler(request, response, error); // step 1
    }

    // If we errored on the response, the delete / unsubscribe was unsuccessful
    if (error) {
        return;
    }

    // If it's a DeleteCommand, UnsubscribeButton, or PerformAudioPassThru we need to remove handlers for the corresponding RPCs
    if ([response isKindOfClass:[SDLDeleteCommandResponse class]]) {
        SDLDeleteCommand *deleteCommandRequest = (SDLDeleteCommand *)request;
        NSNumber *deleteCommandId = deleteCommandRequest.cmdID;
        [self.commandHandlerMap safeRemoveObjectForKey:deleteCommandId];
    } else if ([response isKindOfClass:[SDLUnsubscribeButtonResponse class]]) {
        SDLUnsubscribeButton *unsubscribeButtonRequest = (SDLUnsubscribeButton *)request;
        SDLButtonName unsubscribeButtonName = unsubscribeButtonRequest.buttonName;
        [self.buttonHandlerMap safeRemoveObjectForKey:unsubscribeButtonName];
    } else if ([response isKindOfClass:[SDLPerformAudioPassThruResponse class]]) {
        _audioPassThruHandler = nil; // step 2
    }
}

#pragma mark Audio Pass Thru
    
- (void)sdl_runHandlerForAudioPassThru:(SDLRPCNotificationNotification *)notification {
    SDLOnAudioPassThru *onAudioPassThruNotification = notification.notification;
    
	if (self.audioPassThruHandler) { // step 3
        self.audioPassThruHandler(onAudioPassThruNotification.bulkData);
    }
}
OS & Version Information
  • iOS Version: 10.2
  • SDL iOS Version: 6.4.1
  • Testing Against: SDL Core 6.0.1 + HMI running on our development environment.
Test Case, Sample Code, and / or Example App

logs:log_36.txt

Occurrence:

100%

Recovery Method:

None

@zhouxin627 zhouxin627 changed the title Audio pass through failed due to a timing issue. Audio pass-through failed due to a timing issue. Feb 19, 2020
@NicoleYarroch NicoleYarroch added the bug A defect in the library label Feb 19, 2020
@joeljfischer joeljfischer added the manager-lifecycle Relating to the manager layer - lifecycle manager label Feb 19, 2020
@joeljfischer
Copy link
Contributor

Click PTT to start APT

There is no ButtonName that's designed to start APT. Can you explain what you mean by this? Are you using the custom button name?

When the user clicks PTT again immediately to stop the first APT and start the second APT,
the audioPassThruHandler of the second APT will be cleared due to a timing issue.

Can you provide more details on the sequence here? Is the app receiving the custom(?) button press, then sending a PerformAudioPassThru, then receiving another, sending an EndAudioPassThru, waiting for the PerformAudioPassThru response and sending another PerformAudioPassThru in the response handler? If so, shouldn't the app simply wait for the EndAudioPassThru response and start the next one there?

@joeljfischer joeljfischer added the Waiting for Feedback Maintainers are waiting for feedback from an author or contributor label Feb 20, 2020
@zhouxin627
Copy link
Contributor Author

zhouxin627 commented Feb 25, 2020

Click PTT to start APT

There is no ButtonName that's designed to start APT. Can you explain what you mean by this? Are you using the custom button name?

Hi @joeljfischer
Yes, we are using a custom button to start APT.

When the user clicks PTT again immediately to stop the first APT and start the second APT,
the audioPassThruHandler of the second APT will be cleared due to a timing issue.

Can you provide more details on the sequence here? Is the app receiving the custom(?) button press, then sending a PerformAudioPassThru, then receiving another, sending an EndAudioPassThru, waiting for the PerformAudioPassThru response and sending another PerformAudioPassThru in the response handler? If so, shouldn't the app simply wait for the EndAudioPassThru response and start the next one there?

Yes, but I think wait for the EndAudioPassThru response and start the next one there also needs to modify the Proxy first and It is more like a workaround. So I think it's better to change the existing sequence to fix this issue.

@joeljfischer
Copy link
Contributor

Yes, we are using a custom button to start APT.

I just want to be clear; are you using ButtonName.CUSTOM_BUTTON specifically? If you are not, using a different button name will require a developer to customize the SDL library, which will get them rejected from the SDLC. I'd just like to ensure that you are doing this correctly.

Yes, but I think wait for the EndAudioPassThru response and start the next one there also needs to modify the Proxy first and It is more like a workaround. So I think it's better to change the existing sequence to fix this issue.

To be clear, I don't think that waiting for the EndAudioPassThru response is a "workaround." I believe that it's the correct way to do it. That doesn't necessarily mean that we can't fix the issue as written, but it does mean that fixing the issue may not mean that it works on all head units depending on the implementation.

@joeljfischer
Copy link
Contributor

@zhouxin627 Can you see if #1572 solves this problem for you?

@zhouxin627
Copy link
Contributor Author

Hi @joeljfischer, #1572 can solve this problem. Thank you very much.

@joeljfischer joeljfischer added this to Done in v6.6.0 via automation Feb 28, 2020
@joeljfischer joeljfischer mentioned this issue Apr 29, 2020
3 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug A defect in the library manager-lifecycle Relating to the manager layer - lifecycle manager Waiting for Feedback Maintainers are waiting for feedback from an author or contributor
Projects
No open projects
v6.6.0
  
Done
Development

No branches or pull requests

3 participants