Skip to content

Commit

Permalink
tv-casting-app: Implementing PASE related callbacks (#28342)
Browse files Browse the repository at this point in the history
* Linux tv-casting-app: Implementing AppDelegate

* Android tv-casting-app: Implementing AppDelegate

* iOS tv-casting-app: Implementing AppDelegate
  • Loading branch information
sharadb-amazon authored and pull[bot] committed May 8, 2024
1 parent ebd580d commit 1069951
Show file tree
Hide file tree
Showing 18 changed files with 644 additions and 65 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import android.widget.TextView;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import com.chip.casting.CommissioningCallbacks;
import com.chip.casting.ContentApp;
import com.chip.casting.DiscoveredNodeData;
import com.chip.casting.FailureCallback;
Expand Down Expand Up @@ -120,15 +121,59 @@ private void beginCommissioning(
FailureCallback onConnectionFailure,
SuccessCallback<ContentApp> onNewOrUpdatedEndpoints) {
Log.d(TAG, "Running commissioning");
MatterCallbackHandler commissioningCompleteCallback =
new MatterCallbackHandler() {
@Override
public void handle(MatterError error) {
Log.d(TAG, "handle() called on CommissioningComplete event with " + error);
}
};

SuccessCallback<Void> sessionEstablishmentStartedCallback =
new SuccessCallback<Void>() {
@Override
public void handle(Void response) {
Log.d(TAG, "handle() called on SessionEstablishmentStartedCallback");
}
};

SuccessCallback<Void> sessionEstablishedCallback =
new SuccessCallback<Void>() {
@Override
public void handle(Void response) {
Log.d(TAG, "handle() called on SessionEstablishedCallback");
}
};

FailureCallback sessionEstablishmentErrorCallback =
new FailureCallback() {
@Override
public void handle(MatterError error) {
Log.d(TAG, "handle() called on SessionEstablishmentError event with " + error);
}
};

FailureCallback sessionEstablishmentStoppedCallback =
new FailureCallback() {
@Override
public void handle(MatterError error) {
Log.d(TAG, "handle() called on SessionEstablishmentStopped event with " + error);
}
};

CommissioningCallbacks commissioningCallbacks =
new CommissioningCallbacks.Builder()
.commissioningComplete(commissioningCompleteCallback)
.sessionEstablishmentStarted(sessionEstablishmentStartedCallback)
.sessionEstablished(sessionEstablishedCallback)
.sessionEstablishmentError(sessionEstablishmentErrorCallback)
.sessionEstablishmentStopped(sessionEstablishmentStoppedCallback)
.build();

this.openCommissioningWindowSuccess =
tvCastingApp.openBasicCommissioningWindow(
GlobalCastingConstants.CommissioningWindowDurationSecs,
new MatterCallbackHandler() {
@Override
public void handle(MatterError error) {
Log.d(TAG, "handle() called on CommissioningComplete event with " + error);
}
},
commissioningCallbacks,
onConnectionSuccess,
onConnectionFailure,
onNewOrUpdatedEndpoints);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
/*
* Copyright (c) 2023 Project CHIP Authors
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.chip.casting;

public class CommissioningCallbacks {
/**
* This is called when the PBKDFParamRequest is received and indicates the start of the session
* establishment process
*/
private SuccessCallback<Void> sessionEstablishmentStarted;

/** This is called when the commissioning session has been established */
private SuccessCallback<Void> sessionEstablished;

/**
* This is called when the PASE establishment failed (such as, when an invalid passcode is
* provided) or PASE was established fine but then the fail-safe expired (including being expired
* by the commissioner). The error param indicates the error that occurred during session
* establishment or the error accompanying the fail-safe timeout.
*/
private FailureCallback sessionEstablishmentError;

/**
* This is called when the PASE establishment failed or PASE was established fine but then the
* fail-safe expired (including being expired by the commissioner) AND the commissioning window is
* closed. The window may be closed because the commissioning attempts limit was reached or
* advertising/listening for PASE failed.
*/
private FailureCallback sessionEstablishmentStopped;

/** This is called when the commissioning has been completed */
private Object commissioningComplete;

private CommissioningCallbacks(Builder builder) {
this.sessionEstablishmentStarted = builder.sessionEstablishmentStarted;
this.sessionEstablished = builder.sessionEstablished;
this.sessionEstablishmentError = builder.sessionEstablishmentError;
this.sessionEstablishmentStopped = builder.sessionEstablishmentStopped;
this.commissioningComplete = builder.commissioningComplete;
}

public SuccessCallback<Void> getSessionEstablishmentStarted() {
return sessionEstablishmentStarted;
}

public SuccessCallback<Void> getSessionEstablished() {
return sessionEstablished;
}

public FailureCallback getSessionEstablishmentError() {
return sessionEstablishmentError;
}

public FailureCallback getSessionEstablishmentStopped() {
return sessionEstablishmentStopped;
}

public Object getCommissioningComplete() {
return commissioningComplete;
}

public static class Builder {
private SuccessCallback<Void> sessionEstablishmentStarted;
private SuccessCallback<Void> sessionEstablished;
private FailureCallback sessionEstablishmentError;
private FailureCallback sessionEstablishmentStopped;
private Object commissioningComplete;

public Builder sessionEstablishmentStarted(SuccessCallback<Void> sessionEstablishmentStarted) {
this.sessionEstablishmentStarted = sessionEstablishmentStarted;
return this;
}

public Builder sessionEstablished(SuccessCallback<Void> sessionEstablished) {
this.sessionEstablished = sessionEstablished;
return this;
}

public Builder sessionEstablishmentError(FailureCallback sessionEstablishmentError) {
this.sessionEstablishmentError = sessionEstablishmentError;
return this;
}

public Builder sessionEstablishmentStopped(FailureCallback sessionEstablishmentStopped) {
this.sessionEstablishmentStopped = sessionEstablishmentStopped;
return this;
}

public Builder commissioningComplete(Object commissioningComplete) {
this.commissioningComplete = commissioningComplete;
return this;
}

public CommissioningCallbacks build() {
return new CommissioningCallbacks(this);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ public void stopVideoPlayerDiscovery() {

public native boolean openBasicCommissioningWindow(
int duration,
Object commissioningCompleteHandler,
CommissioningCallbacks commissioningCallbacks,
SuccessCallback<VideoPlayer> onConnectionSuccess,
FailureCallback onConnectionFailure,
SuccessCallback<ContentApp> onNewOrUpdatedEndpointCallback);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,30 @@ template <typename T>
SuccessHandlerJNI<T>::~SuccessHandlerJNI(){};

// COMMISSIONING AND CONNECTION
class SessionEstablishmentStartedHandlerJNI : public SuccessHandlerJNI<void *>
{
public:
SessionEstablishmentStartedHandlerJNI() : SuccessHandlerJNI("(Ljava/lang/Object;)V") {}
jobject ConvertToJObject(void * responseData)
{
// return nullptr because the Java callback extends SuccessCallback<Void> and its handle() expects a Void param.
// It expects a Void becauase no value is passed as part of this callback.
return nullptr;
}
};

class SessionEstablishedHandlerJNI : public SuccessHandlerJNI<void *>
{
public:
SessionEstablishedHandlerJNI() : SuccessHandlerJNI("(Ljava/lang/Object;)V") {}
jobject ConvertToJObject(void * responseData)
{
// return nullptr because the Java callback extends SuccessCallback<Void> and its handle() expects a Void param.
// It expects a Void becauase no value is passed as part of this callback.
return nullptr;
}
};

class OnConnectionSuccessHandlerJNI : public SuccessHandlerJNI<TargetVideoPlayerInfo *>
{
public:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,15 +113,82 @@ JNI_METHOD(void, setDACProvider)(JNIEnv *, jobject, jobject provider)
}

JNI_METHOD(jboolean, openBasicCommissioningWindow)
(JNIEnv * env, jobject, jint duration, jobject jCommissioningCompleteHandler, jobject jOnConnectionSuccessHandler,
(JNIEnv * env, jobject, jint duration, jobject jCommissioningCallbacks, jobject jOnConnectionSuccessHandler,
jobject jOnConnectionFailureHandler, jobject jOnNewOrUpdatedEndpointHandler)
{
chip::DeviceLayer::StackLock lock;

ChipLogProgress(AppServer, "JNI_METHOD openBasicCommissioningWindow called with duration %d", duration);
CHIP_ERROR err = TvCastingAppJNIMgr().getCommissioningCompleteHandler().SetUp(env, jCommissioningCompleteHandler);
VerifyOrExit(CHIP_NO_ERROR == err,
ChipLogError(AppServer, "MatterCallbackHandlerJNI::SetUp failed %" CHIP_ERROR_FORMAT, err.Format()));

CHIP_ERROR err = CHIP_NO_ERROR;

CommissioningCallbacks commissioningCallbacks;
jclass jCommissioningCallbacksClass;
chip::JniReferences::GetInstance().GetClassRef(env, "com/chip/casting/CommissioningCallbacks", jCommissioningCallbacksClass);

jfieldID jCommissioningCompleteField =
env->GetFieldID(jCommissioningCallbacksClass, "commissioningComplete", "Ljava/lang/Object;");
jobject jCommissioningComplete = env->GetObjectField(jCommissioningCallbacks, jCommissioningCompleteField);
if (jCommissioningComplete != nullptr)
{
err = TvCastingAppJNIMgr().getCommissioningCompleteHandler().SetUp(env, jCommissioningComplete);
VerifyOrReturnValue(err == CHIP_NO_ERROR, false,
ChipLogError(AppServer, "MatterCallbackHandlerJNI::SetUp failed %" CHIP_ERROR_FORMAT, err.Format()));
commissioningCallbacks.commissioningComplete = [](CHIP_ERROR err) {
TvCastingAppJNIMgr().getCommissioningCompleteHandler().Handle(err);
};
}

jfieldID jSessionEstablishmentStartedField =
env->GetFieldID(jCommissioningCallbacksClass, "sessionEstablishmentStarted", "Lcom/chip/casting/SuccessCallback;");
jobject jSessionEstablishmentStarted = env->GetObjectField(jCommissioningCallbacks, jSessionEstablishmentStartedField);
if (jSessionEstablishmentStarted != nullptr)
{
err = TvCastingAppJNIMgr().getSessionEstablishmentStartedHandler().SetUp(env, jSessionEstablishmentStarted);
VerifyOrReturnValue(
err == CHIP_NO_ERROR, false,
ChipLogError(AppServer, "SessionEstablishmentStartedHandler.SetUp failed %" CHIP_ERROR_FORMAT, err.Format()));
commissioningCallbacks.sessionEstablishmentStarted = []() {
TvCastingAppJNIMgr().getSessionEstablishmentStartedHandler().Handle(nullptr);
};
}

jfieldID jSessionEstablishedField =
env->GetFieldID(jCommissioningCallbacksClass, "sessionEstablished", "Lcom/chip/casting/SuccessCallback;");
jobject jSessionEstablished = env->GetObjectField(jCommissioningCallbacks, jSessionEstablishedField);
if (jSessionEstablished != nullptr)
{
err = TvCastingAppJNIMgr().getSessionEstablishedHandler().SetUp(env, jSessionEstablished);
VerifyOrReturnValue(err == CHIP_NO_ERROR, false,
ChipLogError(AppServer, "SessionEstablishedHandler.SetUp failed %" CHIP_ERROR_FORMAT, err.Format()));
commissioningCallbacks.sessionEstablished = []() { TvCastingAppJNIMgr().getSessionEstablishedHandler().Handle(nullptr); };
}

jfieldID jSessionEstablishmentErrorField =
env->GetFieldID(jCommissioningCallbacksClass, "sessionEstablishmentError", "Lcom/chip/casting/FailureCallback;");
jobject jSessionEstablishmentError = env->GetObjectField(jCommissioningCallbacks, jSessionEstablishmentErrorField);
if (jSessionEstablishmentError != nullptr)
{
err = TvCastingAppJNIMgr().getSessionEstablishmentErrorHandler().SetUp(env, jSessionEstablishmentError);
VerifyOrReturnValue(err == CHIP_NO_ERROR, false);
commissioningCallbacks.sessionEstablishmentError = [](CHIP_ERROR err) {
TvCastingAppJNIMgr().getSessionEstablishmentErrorHandler().Handle(err);
};
}

jfieldID jSessionEstablishmentStoppedField =
env->GetFieldID(jCommissioningCallbacksClass, "sessionEstablishmentStopped", "Lcom/chip/casting/FailureCallback;");
jobject jSessionEstablishmentStopped = env->GetObjectField(jCommissioningCallbacks, jSessionEstablishmentStoppedField);
if (jSessionEstablishmentStopped != nullptr)
{
err = TvCastingAppJNIMgr().getSessionEstablishmentStoppedHandler().SetUp(env, jSessionEstablishmentStopped);
VerifyOrReturnValue(
err == CHIP_NO_ERROR, false,
ChipLogError(AppServer, "SessionEstablishmentStoppedHandler.SetUp failed %" CHIP_ERROR_FORMAT, err.Format()));
commissioningCallbacks.sessionEstablishmentStopped = []() {
TvCastingAppJNIMgr().getSessionEstablishmentStoppedHandler().Handle(CHIP_NO_ERROR);
};
}

err = TvCastingAppJNIMgr().getOnConnectionSuccessHandler(false).SetUp(env, jOnConnectionSuccessHandler);
VerifyOrExit(CHIP_NO_ERROR == err,
Expand All @@ -136,7 +203,7 @@ JNI_METHOD(jboolean, openBasicCommissioningWindow)
ChipLogError(AppServer, "OnNewOrUpdatedEndpointHandler.SetUp failed %" CHIP_ERROR_FORMAT, err.Format()));

err = CastingServer::GetInstance()->OpenBasicCommissioningWindow(
[](CHIP_ERROR err) { TvCastingAppJNIMgr().getCommissioningCompleteHandler().Handle(err); },
commissioningCallbacks,
[](TargetVideoPlayerInfo * videoPlayer) { TvCastingAppJNIMgr().getOnConnectionSuccessHandler(false).Handle(videoPlayer); },
[](CHIP_ERROR err) { TvCastingAppJNIMgr().getOnConnectionFailureHandler(false).Handle(err); },
[](TargetEndpointInfo * endpoint) { TvCastingAppJNIMgr().getOnNewOrUpdatedEndpointHandler(false).Handle(endpoint); });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,20 @@ class TvCastingAppJNI
{
public:
MatterCallbackHandlerJNI & getCommissioningCompleteHandler() { return mCommissioningCompleteHandler; }

SessionEstablishmentStartedHandlerJNI & getSessionEstablishmentStartedHandler() { return mSessionEstablishmentStartedHandler; }

SessionEstablishedHandlerJNI & getSessionEstablishedHandler() { return mSessionEstablishedHandler; }

FailureHandlerJNI & getSessionEstablishmentErrorHandler() { return mSessionEstablishmentErrorHandler; }

FailureHandlerJNI & getSessionEstablishmentStoppedHandler() { return mSessionEstablishmentStoppedHandler; }

OnConnectionSuccessHandlerJNI & getOnConnectionSuccessHandler(bool preCommissioned)
{
return preCommissioned ? mPreCommissionedOnConnectionSuccessHandler : mCommissioningOnConnectionSuccessHandler;
}

FailureHandlerJNI & getOnConnectionFailureHandler(bool preCommissioned)
{
return preCommissioned ? mPreCommissionedOnConnectionFailureHandler : mCommissioningOnConnectionFailureHandler;
Expand Down Expand Up @@ -100,6 +110,10 @@ class TvCastingAppJNI
static TvCastingAppJNI sInstance;

MatterCallbackHandlerJNI mCommissioningCompleteHandler;
SessionEstablishmentStartedHandlerJNI mSessionEstablishmentStartedHandler;
SessionEstablishedHandlerJNI mSessionEstablishedHandler;
FailureHandlerJNI mSessionEstablishmentErrorHandler;
FailureHandlerJNI mSessionEstablishmentStoppedHandler;
OnConnectionSuccessHandlerJNI mCommissioningOnConnectionSuccessHandler;
FailureHandlerJNI mCommissioningOnConnectionFailureHandler;
OnNewOrUpdatedEndpointHandlerJNI mCommissioningOnNewOrUpdatedEndpointHandler;
Expand Down
1 change: 1 addition & 0 deletions examples/tv-casting-app/android/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ android_library("java") {

sources = [
"App/app/src/main/jni/com/chip/casting/AppParameters.java",
"App/app/src/main/jni/com/chip/casting/CommissioningCallbacks.java",
"App/app/src/main/jni/com/chip/casting/ContentApp.java",
"App/app/src/main/jni/com/chip/casting/ContentLauncherTypes.java",
"App/app/src/main/jni/com/chip/casting/DACProvider.java",
Expand Down
Loading

0 comments on commit 1069951

Please sign in to comment.