Skip to content

Commit

Permalink
tv-casting-app: ShutdownAllSubscriptions and Disconnect APIs (#23350)
Browse files Browse the repository at this point in the history
  • Loading branch information
sharadb-amazon authored Oct 26, 2022
1 parent 8a24670 commit e3ed287
Show file tree
Hide file tree
Showing 13 changed files with 177 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public void handleCommissioningButtonClicked(DiscoveredNodeData commissioner) {

@Override
public void handleCommissioningComplete() {
showFragment(SelectClusterFragment.newInstance());
showFragment(SelectClusterFragment.newInstance(tvCastingApp));
}

@Override
Expand All @@ -66,6 +66,11 @@ public void handleMediaPlaybackSelected() {
showFragment(MediaPlaybackFragment.newInstance(tvCastingApp));
}

@Override
public void handleDisconnect() {
showFragment(CommissionerDiscoveryFragment.newInstance(tvCastingApp));
}

/**
* The order is important, must first new TvCastingApp to load dynamic library, then
* AndroidChipPlatform to prepare platform, then start ChipAppServer, then call init on
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ public class MediaPlaybackFragment extends Fragment {

private View.OnClickListener subscribeToCurrentStateButtonClickListener;

private View.OnClickListener shutdownALlSubscriptionsButtonClickListener;

private static final ContentApp kContentApp = new ContentApp((short) 4, null);

public MediaPlaybackFragment(TvCastingApp tvCastingApp) {
Expand Down Expand Up @@ -123,6 +125,15 @@ public void run() {
}
};

this.shutdownALlSubscriptionsButtonClickListener =
new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d(TAG, "Shutting down all subscriptions");
tvCastingApp.shutdownAllSubscriptions();
}
};

return inflater.inflate(R.layout.fragment_media_playback, container, false);
}

Expand All @@ -133,5 +144,9 @@ public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
getView()
.findViewById(R.id.subscribeToCurrentStateButton)
.setOnClickListener(subscribeToCurrentStateButtonClickListener);

getView()
.findViewById(R.id.shutdownAllSubscriptionsButton)
.setOnClickListener(shutdownALlSubscriptionsButtonClickListener);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,31 @@
import android.view.ViewGroup;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import com.chip.casting.TvCastingApp;

/** An interstitial {@link Fragment} to select one of the supported media actions to perform */
public class SelectClusterFragment extends Fragment {
private static final String TAG = SelectClusterFragment.class.getSimpleName();

private final TvCastingApp tvCastingApp;

private View.OnClickListener selectContentLauncherButtonClickListener;
private View.OnClickListener selectMediaPlaybackButtonClickListener;
private View.OnClickListener disconnectButtonClickListener;

public SelectClusterFragment(TvCastingApp tvCastingApp) {
this.tvCastingApp = tvCastingApp;
}

/**
* Use this factory method to create a new instance of this fragment using the provided
* parameters.
*
* @param tvCastingApp TV Casting App (JNI)
* @return A new instance of fragment SelectActionFragment.
*/
public static SelectClusterFragment newInstance() {
return new SelectClusterFragment();
public static SelectClusterFragment newInstance(TvCastingApp tvCastingApp) {
return new SelectClusterFragment(tvCastingApp);
}

@Override
Expand Down Expand Up @@ -52,6 +61,16 @@ public void onClick(View v) {
}
};

this.disconnectButtonClickListener =
new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d(TAG, "Disconnecting from current video player");
tvCastingApp.disconnect();
callback.handleDisconnect();
}
};

return inflater.inflate(R.layout.fragment_select_cluster, container, false);
}

Expand All @@ -65,6 +84,7 @@ public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
getView()
.findViewById(R.id.selectMediaPlaybackButton)
.setOnClickListener(selectMediaPlaybackButtonClickListener);
getView().findViewById(R.id.disconnectButton).setOnClickListener(disconnectButtonClickListener);
}

/** Interface for notifying the host. */
Expand All @@ -74,5 +94,8 @@ public interface Callback {

/** Notifies listener to trigger transition on selection of Media Playback cluster */
void handleMediaPlaybackSelected();

/** Notifies listener to trigger transition on click of the Disconnect button */
void handleDisconnect();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,10 @@ public native boolean verifyOrEstablishConnection(
FailureCallback onConnectionFailure,
SuccessCallback<ContentApp> onNewOrUpdatedEndpointCallback);

public native void shutdownAllSubscriptions();

public native void disconnect();

public native List<VideoPlayer> getActiveTargetVideoPlayers();

/*
Expand Down Expand Up @@ -328,7 +332,7 @@ public native boolean applicationBasic_readVendorName(

public native boolean applicationBasic_readVendorID(
ContentApp contentApp,
SuccessCallback<Short> readSuccessHandler,
SuccessCallback<Integer> readSuccessHandler,
FailureCallback readFailureHandler);

public native boolean applicationBasic_readApplicationName(
Expand All @@ -338,7 +342,7 @@ public native boolean applicationBasic_readApplicationName(

public native boolean applicationBasic_readProductID(
ContentApp contentApp,
SuccessCallback<Short> readSuccessHandler,
SuccessCallback<Integer> readSuccessHandler,
FailureCallback readFailureHandler);

public native boolean applicationBasic_readApplicationVersion(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ CHIP_ERROR CallbackBaseJNI::SetUp(JNIEnv * env, jobject inHandler)
mMethod = env->GetMethodID(mClazz, "handle", mMethodSignature);
if (mMethod == nullptr)
{
ChipLogError(AppServer, "Failed to access 'handle' method");
ChipLogError(AppServer, "Failed to access 'handle' method with signature %s", mMethodSignature);
env->ExceptionClear();
}

Expand All @@ -50,7 +50,7 @@ CHIP_ERROR CallbackBaseJNI::SetUp(JNIEnv * env, jobject inHandler)

void FailureHandlerJNI::Handle(CHIP_ERROR callbackErr)
{
ChipLogProgress(AppServer, "FailureHandlerJNI::Handle called");
ChipLogProgress(AppServer, "Handle(CHIP_ERROR) called");

JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread();
UtfString jniCallbackErrString(env, callbackErr.AsString());
Expand All @@ -63,7 +63,7 @@ void FailureHandlerJNI::Handle(CHIP_ERROR callbackErr)
exit:
if (err != CHIP_NO_ERROR)
{
ChipLogError(AppServer, "FailureHandlerJNI::Handle status error: %s", err.AsString());
ChipLogError(AppServer, "Handle(CHIP_ERROR) status error: %s", err.AsString());
}
}

Expand Down Expand Up @@ -332,9 +332,10 @@ jobject TargetListSuccessHandlerJNI::ConvertToJObject(
return nullptr;
}

jmethodID constructor = env->GetMethodID(responseTypeClass, "<init>", "(Ljava/lang/Integer;java/lang/String;)V");
jmethodID constructor = env->GetMethodID(responseTypeClass, "<init>", "(Ljava/lang/Integer;Ljava/lang/String;)V");
chip::UtfString targetInfoName(env, targetInfo.name);
jobject jTargetInfo = env->NewObject(responseTypeClass, constructor, targetInfo.identifier, targetInfoName.jniValue());
jobject jTargetInfo = env->NewObject(responseTypeClass, constructor, ConvertToIntegerJObject(targetInfo.identifier),
targetInfoName.jniValue());

chip::JniReferences::GetInstance().AddToList(jArrayList, jTargetInfo);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,21 @@ JNI_METHOD(jboolean, verifyOrEstablishConnection)
return true;
}

JNI_METHOD(void, shutdownAllSubscriptions)(JNIEnv * env, jobject)
{
chip::DeviceLayer::StackLock lock;
ChipLogProgress(AppServer, "JNI_METHOD shutdownAllSubscriptions called");

CastingServer::GetInstance()->ShutdownAllSubscriptions();
}

JNI_METHOD(void, disconnect)(JNIEnv * env, jobject)
{
chip::DeviceLayer::StackLock lock;
ChipLogProgress(AppServer, "JNI_METHOD disconnect called");
CastingServer::GetInstance()->Disconnect();
}

JNI_METHOD(jobject, getActiveTargetVideoPlayers)(JNIEnv * env, jobject)
{
chip::DeviceLayer::StackLock lock;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,5 +102,19 @@
android:layout_height="wrap_content"
android:textAppearance="@style/TextAppearance.AppCompat.Large" />
</LinearLayout>

<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<Button
android:id="@+id/shutdownAllSubscriptionsButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/shutdown_all_subscriptions_button_text"
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
android:layout_marginRight="10sp" />
</LinearLayout>

</LinearLayout>
</FrameLayout>
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@
android:layout_height="match_parent"
tools:context=".SelectClusterFragment">

<LinearLayout
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="10sp">

<TextView
android:id="@+id/select_cluster_heading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/select_cluster_text"
Expand All @@ -23,14 +24,25 @@
android:layout_height="wrap_content"
android:text="@string/select_content_launcher_button_text"
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
android:layout_marginRight="10sp" />
android:layout_marginRight="10sp"
android:layout_below="@id/select_cluster_heading" />

<Button
android:id="@+id/selectMediaPlaybackButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/select_media_playback_button_text"
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
android:layout_marginRight="10sp" />
</LinearLayout>
android:layout_marginRight="10sp"
android:layout_below="@id/selectContentLauncherButton"/>

<Button
android:id="@+id/disconnectButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/disconnect_button_text"
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
android:layout_marginRight="10sp"
android:layout_alignParentBottom="true" />
</RelativeLayout>
</FrameLayout>
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,6 @@
<string name="subscribe_to_current_state_button_text">Subscribe</string>
<string name="current_state_text">Reported Current State</string>
<string name="endpoint_prompt_text">Endpoint ID</string>
<string name="shutdown_all_subscriptions_button_text">Shutdown all Subscriptions</string>
<string name="disconnect_button_text">Disconnect from Video Player</string>
</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,24 @@
onConnectionFailureCallback:(void (^_Nonnull)(MatterError * _Nonnull))onConnectionFailureCallback
onNewOrUpdatedEndpointCallback:(void (^_Nonnull)(ContentApp * _Nonnull))onNewOrUpdatedEndpointCallback;

/*!
@brief Tears down all active subscriptions.
@param clientQueue Queue to invoke callbacks on
@param requestSentHandler Called after the request has been sent
*/
- (void)shutdownAllSubscriptions:(dispatch_queue_t _Nonnull)clientQueue requestSentHandler:(nullable void (^)())requestSentHandler;

/*!
@brief Mark any open session with the currently connected Video player as expired.
@param clientQueue Queue to invoke callbacks on
@param requestSentHandler Called after the request has been sent
*/
- (void)disconnect:(dispatch_queue_t _Nonnull)clientQueue requestSentHandler:(nullable void (^)())requestSentHandler;

/*!
@brief Send a ContentLauncher:LaunchURL request to a TV
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,28 @@ - (void)verifyOrEstablishConnection:(VideoPlayer * _Nonnull)videoPlayer
});
}

- (void)shutdownAllSubscriptions:(dispatch_queue_t _Nonnull)clientQueue requestSentHandler:(nullable void (^)())requestSentHandler
{
ChipLogProgress(AppServer, "CastingServerBridge().shutdownAllSubscriptions() called");
dispatch_async(_chipWorkQueue, ^{
CastingServer::GetInstance()->ShutdownAllSubscriptions();
dispatch_async(clientQueue, ^{
requestSentHandler();
});
});
}

- (void)disconnect:(dispatch_queue_t _Nonnull)clientQueue requestSentHandler:(nullable void (^)())requestSentHandler
{
ChipLogProgress(AppServer, "CastingServerBridge().disconnect() called");
dispatch_async(_chipWorkQueue, ^{
CastingServer::GetInstance()->Disconnect();
dispatch_async(clientQueue, ^{
requestSentHandler();
});
});
}

- (void)contentLauncher_launchUrl:(ContentApp * _Nonnull)contentApp
contentUrl:(NSString * _Nonnull)contentUrl
contentDisplayStr:(NSString * _Nonnull)contentDisplayStr
Expand Down
10 changes: 10 additions & 0 deletions examples/tv-casting-app/tv-casting-common/include/CastingServer.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,16 @@ class CastingServer

CHIP_ERROR PurgeVideoPlayerCache();

/**
* Tears down all active subscriptions.
*/
void ShutdownAllSubscriptions();

/**
* Mark any open session with the currently connected Video player as expired.
*/
void Disconnect();

/**
* @brief Content Launcher cluster
*/
Expand Down
22 changes: 22 additions & 0 deletions examples/tv-casting-app/tv-casting-common/src/CastingServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,28 @@ void CastingServer::SetDefaultFabricIndex(std::function<void(TargetVideoPlayerIn
ChipLogError(AppServer, " -- No initialized fabrics with video players");
}

void CastingServer::ShutdownAllSubscriptions()
{
ChipLogProgress(AppServer, "Shutting down ALL Subscriptions");
app::InteractionModelEngine::GetInstance()->ShutdownAllSubscriptions();
}

void CastingServer::Disconnect()
{
TargetVideoPlayerInfo * currentVideoPlayer = GetActiveTargetVideoPlayer();

if (currentVideoPlayer != nullptr && currentVideoPlayer->IsInitialized())
{
chip::OperationalDeviceProxy * operationalDeviceProxy = currentVideoPlayer->GetOperationalDeviceProxy();
if (operationalDeviceProxy != nullptr)
{
ChipLogProgress(AppServer, "Disconnecting from VideoPlayer with nodeId=0x" ChipLogFormatX64 " fabricIndex=%d",
ChipLogValueX64(currentVideoPlayer->GetNodeId()), currentVideoPlayer->GetFabricIndex());
operationalDeviceProxy->Disconnect();
}
}
}

/**
* @brief Content Launcher cluster
*/
Expand Down

0 comments on commit e3ed287

Please sign in to comment.