diff --git a/examples/tv-app/android/App/platform-app/src/main/AndroidManifest.xml b/examples/tv-app/android/App/platform-app/src/main/AndroidManifest.xml
index b6e00cd75d0365..476faa2030c7a2 100644
--- a/examples/tv-app/android/App/platform-app/src/main/AndroidManifest.xml
+++ b/examples/tv-app/android/App/platform-app/src/main/AndroidManifest.xml
@@ -26,6 +26,9 @@
tools:ignore="QueryAllPackagesPermission" />
+
+
+
tasks = activityManager.getRunningTasks(1);
+ if (tasks != null && !tasks.isEmpty()) {
+ ActivityManager.RunningTaskInfo taskInfo = tasks.get(0);
+ String packageName =
+ taskInfo.topActivity != null ? taskInfo.topActivity.getPackageName() : "";
+ return packageName.equals(contentAppPackageName);
+ }
+ return false;
+ }
+
public String sendCommand(int endpointId, long clusterId, long commandId, String commandPayload) {
Log.d(TAG, "Received a command for endpointId " + endpointId + ". Message " + commandPayload);
@@ -26,6 +55,17 @@ public String sendCommand(int endpointId, long clusterId, long commandId, String
ContentAppDiscoveryService.getReceiverInstance().getDiscoveredContentApps().values(),
endpointId);
if (discoveredApp != null) {
+ // Intercept NavigateTarget and LaunchContent commands and launch content app if necessary
+ if (isForegroundCommand(clusterId, commandId)) {
+ // Check if contentapp main/launch activity is already in foreground before launching.
+ if (!isAppInForeground(discoveredApp.getAppName())) {
+ Intent launchIntent =
+ context.getPackageManager().getLaunchIntentForPackage(discoveredApp.getAppName());
+ if (launchIntent != null) {
+ context.startActivity(launchIntent);
+ }
+ }
+ }
Log.d(TAG, "Sending a command for endpointId " + endpointId + ". Message " + commandPayload);
return ContentAppAgentService.sendCommand(
context, discoveredApp.getAppName(), clusterId, commandId, commandPayload);
diff --git a/examples/tv-app/android/App/platform-app/src/main/java/com/matter/tv/server/model/ContentApp.java b/examples/tv-app/android/App/platform-app/src/main/java/com/matter/tv/server/model/ContentApp.java
index e30a75a00d98b2..0cd12b404d6fcf 100644
--- a/examples/tv-app/android/App/platform-app/src/main/java/com/matter/tv/server/model/ContentApp.java
+++ b/examples/tv-app/android/App/platform-app/src/main/java/com/matter/tv/server/model/ContentApp.java
@@ -25,6 +25,7 @@ public ContentApp(
this.vendorId = vendorId;
this.productId = productId;
this.version = version;
+ this.supportedClusters = Collections.EMPTY_SET;
}
public ContentApp(
@@ -67,9 +68,7 @@ public void setEndpointId(int endpoint) {
}
public Set getSupportedClusters() {
- return supportedClusters != null
- ? Collections.unmodifiableSet(supportedClusters)
- : Collections.EMPTY_SET;
+ return Collections.unmodifiableSet(supportedClusters);
}
public String getVersion() {
diff --git a/examples/tv-app/android/App/platform-app/src/main/java/com/matter/tv/server/utils/EndpointsDataStore.java b/examples/tv-app/android/App/platform-app/src/main/java/com/matter/tv/server/utils/EndpointsDataStore.java
index f587905fb09145..227ea9326be538 100644
--- a/examples/tv-app/android/App/platform-app/src/main/java/com/matter/tv/server/utils/EndpointsDataStore.java
+++ b/examples/tv-app/android/App/platform-app/src/main/java/com/matter/tv/server/utils/EndpointsDataStore.java
@@ -4,13 +4,18 @@
import android.content.SharedPreferences;
import android.util.JsonReader;
import android.util.JsonWriter;
+import com.matter.tv.app.api.SupportedCluster;
import com.matter.tv.server.model.ContentApp;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
import java.util.Map;
+import java.util.Set;
public class EndpointsDataStore {
@@ -21,6 +26,11 @@ public class EndpointsDataStore {
private static final String KEY_PRODUCTID = "PID";
private static final String KEY_VERSION = "VER";
private static final String KEY_ENDPOINTID = "EPID";
+ private static final String KEY_SUPPORTED_CLUSTERS = "supportedClusters";
+ private static final String KEY_CLUSTER_IDENTIFIER = "clusterIdentifier";
+ private static final String KEY_FEATURES = "features";
+ private static final String KEY_OPTIONAL_COMMAND_IDENTIFIERS = "optionalCommandIdentifiers";
+ private static final String KEY_OPTIONAL_ATTRIBUTES_IDENTIFIERS = "optionalAttributesIdentifiers";
private static EndpointsDataStore instance;
private final SharedPreferences discoveredEndpoints;
Map persistedContentApps = new HashMap<>();
@@ -57,19 +67,20 @@ private String serializeContentApp(ContentApp app) {
StringWriter stringWriter = new StringWriter();
JsonWriter jsonWriter = new JsonWriter(stringWriter);
try {
- jsonWriter
- .beginObject()
- .name(KEY_VENDORID)
- .value(app.getVendorId())
- .name(KEY_VENDORNAME)
- .value(app.getVendorName())
- .name(KEY_PRODUCTID)
- .value(app.getProductId())
- .name(KEY_VERSION)
- .value(app.getVersion())
- .name(KEY_ENDPOINTID)
- .value(app.getEndpointId())
- .endObject();
+ jsonWriter.beginObject();
+ jsonWriter.name(KEY_VENDORID);
+ jsonWriter.value(app.getVendorId());
+ jsonWriter.name(KEY_VENDORNAME);
+ jsonWriter.value(app.getVendorName());
+ jsonWriter.name(KEY_PRODUCTID);
+ jsonWriter.value(app.getProductId());
+ jsonWriter.name(KEY_VERSION);
+ jsonWriter.value(app.getVersion());
+ jsonWriter.name(KEY_ENDPOINTID);
+ jsonWriter.value(app.getEndpointId());
+ jsonWriter.name(KEY_SUPPORTED_CLUSTERS);
+ serializeSupportedClusters(jsonWriter, app.getSupportedClusters());
+ jsonWriter.endObject();
jsonWriter.flush();
jsonWriter.close();
} catch (IOException e) {
@@ -88,6 +99,7 @@ private ContentApp deserializeContentApp(String appName, String appMetadata) {
int vendorId = 0;
int productId = 0;
int endpoint = ContentApp.INVALID_ENDPOINTID;
+ Set supportedClusters = new HashSet<>();
while (jsonReader.hasNext()) {
String name = jsonReader.nextName();
switch (name) {
@@ -106,9 +118,12 @@ private ContentApp deserializeContentApp(String appName, String appMetadata) {
case KEY_ENDPOINTID:
endpoint = jsonReader.nextInt();
break;
+ case KEY_SUPPORTED_CLUSTERS:
+ supportedClusters = deserializeSupportedClusters(jsonReader);
+ break;
}
}
- app = new ContentApp(appName, vendorName, vendorId, productId, version);
+ app = new ContentApp(appName, vendorName, vendorId, productId, version, supportedClusters);
jsonReader.endObject();
jsonReader.close();
} catch (IOException e) {
@@ -116,4 +131,86 @@ private ContentApp deserializeContentApp(String appName, String appMetadata) {
}
return app;
}
+
+ private void serializeSupportedClusters(
+ JsonWriter jsonWriter, Set supportedClusters) throws IOException {
+ if (supportedClusters != null) {
+ jsonWriter.beginArray();
+ for (SupportedCluster supportedCluster : supportedClusters) {
+ if (supportedCluster != null) {
+ serializeSupportedCluster(jsonWriter, supportedCluster);
+ }
+ }
+ jsonWriter.endArray();
+ }
+ }
+
+ private Set deserializeSupportedClusters(JsonReader jsonReader)
+ throws IOException {
+ Set supportedClusters = new HashSet<>();
+ jsonReader.beginArray();
+ while (jsonReader.hasNext()) {
+ supportedClusters.add(deserializeSupportedCluster(jsonReader));
+ }
+ jsonReader.endArray();
+ return supportedClusters;
+ }
+
+ private void serializeSupportedCluster(JsonWriter jsonWriter, SupportedCluster supportedCluster)
+ throws IOException {
+ jsonWriter.beginObject();
+ jsonWriter.name(KEY_CLUSTER_IDENTIFIER);
+ jsonWriter.value(supportedCluster.clusterIdentifier);
+ jsonWriter.name(KEY_FEATURES);
+ jsonWriter.value(supportedCluster.features);
+ jsonWriter.name(KEY_OPTIONAL_COMMAND_IDENTIFIERS);
+ serializeIntArray(jsonWriter, supportedCluster.optionalCommandIdentifiers);
+ jsonWriter.name(KEY_OPTIONAL_ATTRIBUTES_IDENTIFIERS);
+ serializeIntArray(jsonWriter, supportedCluster.optionalAttributesIdentifiers);
+ jsonWriter.endObject();
+ }
+
+ private SupportedCluster deserializeSupportedCluster(JsonReader jsonReader) throws IOException {
+ SupportedCluster supportedCluster = new SupportedCluster();
+ jsonReader.beginObject();
+ while (jsonReader.hasNext()) {
+ String name = jsonReader.nextName();
+ switch (name) {
+ case KEY_CLUSTER_IDENTIFIER:
+ supportedCluster.clusterIdentifier = jsonReader.nextInt();
+ break;
+ case KEY_FEATURES:
+ supportedCluster.features = jsonReader.nextInt();
+ break;
+ case KEY_OPTIONAL_COMMAND_IDENTIFIERS:
+ supportedCluster.optionalCommandIdentifiers = deserializeIntArray(jsonReader);
+ break;
+ case KEY_OPTIONAL_ATTRIBUTES_IDENTIFIERS:
+ supportedCluster.optionalAttributesIdentifiers = deserializeIntArray(jsonReader);
+ break;
+ }
+ }
+ jsonReader.endObject();
+ return supportedCluster;
+ }
+
+ private void serializeIntArray(JsonWriter jsonWriter, int[] array) throws IOException {
+ jsonWriter.beginArray();
+ if (array != null) {
+ for (int value : array) {
+ jsonWriter.value(value);
+ }
+ }
+ jsonWriter.endArray();
+ }
+
+ private int[] deserializeIntArray(JsonReader jsonReader) throws IOException {
+ List dynamicArray = new ArrayList<>();
+ jsonReader.beginArray();
+ while (jsonReader.hasNext()) {
+ dynamicArray.add(jsonReader.nextInt());
+ }
+ jsonReader.endArray();
+ return dynamicArray.stream().mapToInt(Integer::intValue).toArray();
+ }
}