From fd7558eff7e04185d362926fcbcab497e1568c94 Mon Sep 17 00:00:00 2001 From: amitnj <74272437+amitnj@users.noreply.github.com> Date: Thu, 12 Jan 2023 06:21:17 -0800 Subject: [PATCH] Fix issue of content app losing connection to the platform-app. (#23536) * Fix issue of content app losing connection to the platform-app. * Restyled by google-java-format * Added comments to the attribute holder class. * Restyled by google-java-format * Fix styling Co-authored-by: Restyled.io --- .../example/contentapp/AttributeHolder.java | 96 ++++++++++++++++++- .../com/example/contentapp/MainActivity.java | 52 +++++++++- .../contentapp/matter/MatterAgentClient.java | 93 +++++++++++------- .../receiver/MatterCommandReceiver.java | 4 + 4 files changed, 205 insertions(+), 40 deletions(-) diff --git a/examples/tv-app/android/App/content-app/src/main/java/com/example/contentapp/AttributeHolder.java b/examples/tv-app/android/App/content-app/src/main/java/com/example/contentapp/AttributeHolder.java index e6ff2c695357fa..1a8d93e737bf0b 100644 --- a/examples/tv-app/android/App/content-app/src/main/java/com/example/contentapp/AttributeHolder.java +++ b/examples/tv-app/android/App/content-app/src/main/java/com/example/contentapp/AttributeHolder.java @@ -1,13 +1,100 @@ package com.example.contentapp; +import android.util.Log; import com.matter.tv.app.api.Clusters; import java.util.HashMap; import java.util.Map; /** Class to hold attribute values to help test attribute read and subscribe use cases. */ public class AttributeHolder { - private static AttributeHolder instance = new AttributeHolder(); private Map> attributeValues = new HashMap<>(); + private static final String TAG = "AttributeHolder"; + + // The following are the various values of the target list that can be set using the UI of the + // content app for testing. + // We have a short version (TL_SHORT) which is a simple target list. A long version (TL_LONG) + // which has several large values in the target list but always less than the single message + // limit(can be chunked) and a bad version (TL_LONG_BAD) which puts a value that is larger + // than can be handled by a single message and hence cannot be chunked. + // This is only for testing. These are public since they are used in the Main Activity(which + // renders the UI). + public static final String TL_LONG = + "[{\"0\":1, \"1\":\"Home\"},{\"0\":2, \"1\":\"Settings\"},{\"0\":3, \"1\":\"Casting Home\"}" + + ",{\"0\":249, \"1\":\"" + + "1skfguioufgirufgieufgifugaeifugaeifugadifugbdifugadfiugawdfiuawgdfiuawdbvawiufvafuvwiufgwieufgdhtskhtdhhtbbsagthdkgusdfjgfghdgrbt" + + "skfguioufgirufgieufgifugaeifugaeifugadifugbdifugadfiugawdfiuawgdfiuawdbvawiufvafuvwiufgwieufgdhtskhtdhhtbbsagthdkgusdfjgfghdgrbt" + + "skfguioufgirufgieufgifugaeifugaeifugadifugbdifugadfiugawdfiuawgdfiuawdbvawiufvafuvwiufgwieufgdhtskhtdhhtbbsagthdkgusdfjgfghdgrbt" + + "skfguioufgirufgieufgifugaeifugaeifugadifugbdifugadfiugawdfiuawgdfiuawdbvawiufvafuvwiufgwieufgdhtskhtdhhtbbsagthdkgusdfjgfghdgrbt" + + "skfguioufgirufgieufgifugaeifugaeifugadifugbdifugadfiugawdfiuawgdfiuawdbvawiufvafuvwiufgwieufgdhtskhtdhhtbbsagthdkgusdfjgfghdgrbt" + + "skfguioufgirufgieufgifugaeifugaeifugadifugbdifugadfiugawdfiuawgdfiuawdbvawiufvafuvwiufgwieufgdhtskhtdhhtbbsagthdkgusdfjgfghdgrbt" + + "skfguioufgirufgieufgifugaeifugaeifugadifugbdifugadfiugawdfiuawgdfiuawdbvawiufvafuvwiufgwieufgdhtskhtdhhtbbsagthdkgusdfjgfghdgrbt\"}" + + ",{\"0\":250, \"1\":\"" + + "2skfguioufgirufgieufgifugaeifugaeifugadifugbdifugadfiugawdfiuawgdfiuawdbvawiufvafuvwiufgwieufgdhtskhtdhhtbbsagthdkgusdfjgfghdgrbt" + + "skfguioufgirufgieufgifugaeifugaeifugadifugbdifugadfiugawdfiuawgdfiuawdbvawiufvafuvwiufgwieufgdhtskhtdhhtbbsagthdkgusdfjgfghdgrbt" + + "skfguioufgirufgieufgifugaeifugaeifugadifugbdifugadfiugawdfiuawgdfiuawdbvawiufvafuvwiufgwieufgdhtskhtdhhtbbsagthdkgusdfjgfghdgrbt" + + "skfguioufgirufgieufgifugaeifugaeifugadifugbdifugadfiugawdfiuawgdfiuawdbvawiufvafuvwiufgwieufgdhtskhtdhhtbbsagthdkgusdfjgfghdgrbt" + + "skfguioufgirufgieufgifugaeifugaeifugadifugbdifugadfiugawdfiuawgdfiuawdbvawiufvafuvwiufgwieufgdhtskhtdhhtbbsagthdkgusdfjgfghdgrbt" + + "skfguioufgirufgieufgifugaeifugaeifugadifugbdifugadfiugawdfiuawgdfiuawdbvawiufvafuvwiufgwieufgdhtskhtdhhtbbsagthdkgusdfjgfghdgrbt" + + "skfguioufgirufgieufgifugaeifugaeifugadifugbdifugadfiugawdfiuawgdfiuawdbvawiufvafuvwiufgwieufgdhtskhtdhhtbbsagthdkgusdfjgfghdgrbt\"}" + + ",{\"0\":251, \"1\":\"" + + "3skfguioufgirufgieufgifugaeifugaeifugadifugbdifugadfiugawdfiuawgdfiuawdbvawiufvafuvwiufgwieufgdhtskhtdhhtbbsagthdkgusdfjgfghdgrbt" + + "skfguioufgirufgieufgifugaeifugaeifugadifugbdifugadfiugawdfiuawgdfiuawdbvawiufvafuvwiufgwieufgdhtskhtdhhtbbsagthdkgusdfjgfghdgrbt" + + "skfguioufgirufgieufgifugaeifugaeifugadifugbdifugadfiugawdfiuawgdfiuawdbvawiufvafuvwiufgwieufgdhtskhtdhhtbbsagthdkgusdfjgfghdgrbt" + + "skfguioufgirufgieufgifugaeifugaeifugadifugbdifugadfiugawdfiuawgdfiuawdbvawiufvafuvwiufgwieufgdhtskhtdhhtbbsagthdkgusdfjgfghdgrbt" + + "skfguioufgirufgieufgifugaeifugaeifugadifugbdifugadfiugawdfiuawgdfiuawdbvawiufvafuvwiufgwieufgdhtskhtdhhtbbsagthdkgusdfjgfghdgrbt" + + "skfguioufgirufgieufgifugaeifugaeifugadifugbdifugadfiugawdfiuawgdfiuawdbvawiufvafuvwiufgwieufgdhtskhtdhhtbbsagthdkgusdfjgfghdgrbt" + + "skfguioufgirufgieufgifugaeifugaeifugadifugbdifugadfiugawdfiuawgdfiuawdbvawiufvafuvwiufgwieufgdhtskhtdhhtbbsagthdkgusdfjgfghdgrbt\"}" + + ",{\"0\":252, \"1\":\"" + + "4skfguioufgirufgieufgifugaeifugaeifugadifugbdifugadfiugawdfiuawgdfiuawdbvawiufvafuvwiufgwieufgdhtskhtdhhtbbsagthdkgusdfjgfghdgrbt" + + "skfguioufgirufgieufgifugaeifugaeifugadifugbdifugadfiugawdfiuawgdfiuawdbvawiufvafuvwiufgwieufgdhtskhtdhhtbbsagthdkgusdfjgfghdgrbt" + + "skfguioufgirufgieufgifugaeifugaeifugadifugbdifugadfiugawdfiuawgdfiuawdbvawiufvafuvwiufgwieufgdhtskhtdhhtbbsagthdkgusdfjgfghdgrbt" + + "skfguioufgirufgieufgifugaeifugaeifugadifugbdifugadfiugawdfiuawgdfiuawdbvawiufvafuvwiufgwieufgdhtskhtdhhtbbsagthdkgusdfjgfghdgrbt" + + "skfguioufgirufgieufgifugaeifugaeifugadifugbdifugadfiugawdfiuawgdfiuawdbvawiufvafuvwiufgwieufgdhtskhtdhhtbbsagthdkgusdfjgfghdgrbt" + + "skfguioufgirufgieufgifugaeifugaeifugadifugbdifugadfiugawdfiuawgdfiuawdbvawiufvafuvwiufgwieufgdhtskhtdhhtbbsagthdkgusdfjgfghdgrbt" + + "skfguioufgirufgieufgifugaeifugaeifugadifugbdifugadfiugawdfiuawgdfiuawdbvawiufvafuvwiufgwieufgdhtskhtdhhtbbsagthdkgusdfjgfghdgrbt\"}" + + ",{\"0\":253, \"1\":\"" + + "5skfguioufgirufgieufgifugaeifugaeifugadifugbdifugadfiugawdfiuawgdfiuawdbvawiufvafuvwiufgwieufgdhtskhtdhhtbbsagthdkgusdfjgfghdgrbt" + + "skfguioufgirufgieufgifugaeifugaeifugadifugbdifugadfiugawdfiuawgdfiuawdbvawiufvafuvwiufgwieufgdhtskhtdhhtbbsagthdkgusdfjgfghdgrbt" + + "skfguioufgirufgieufgifugaeifugaeifugadifugbdifugadfiugawdfiuawgdfiuawdbvawiufvafuvwiufgwieufgdhtskhtdhhtbbsagthdkgusdfjgfghdgrbt" + + "skfguioufgirufgieufgifugaeifugaeifugadifugbdifugadfiugawdfiuawgdfiuawdbvawiufvafuvwiufgwieufgdhtskhtdhhtbbsagthdkgusdfjgfghdgrbt" + + "skfguioufgirufgieufgifugaeifugaeifugadifugbdifugadfiugawdfiuawgdfiuawdbvawiufvafuvwiufgwieufgdhtskhtdhhtbbsagthdkgusdfjgfghdgrbt" + + "skfguioufgirufgieufgifugaeifugaeifugadifugbdifugadfiugawdfiuawgdfiuawdbvawiufvafuvwiufgwieufgdhtskhtdhhtbbsagthdkgusdfjgfghdgrbt" + + "skfguioufgirufgieufgifugaeifugaeifugadifugbdifugadfiugawdfiuawgdfiuawdbvawiufvafuvwiufgwieufgdhtskhtdhhtbbsagthdkgusdfjgfghdgrbt\"}" + + ",{\"0\":254, \"1\":\"" + + "6skfguioufgirufgieufgifugaeifugaeifugadifugbdifugadfiugawdfiuawgdfiuawdbvawiufvafuvwiufgwieufgdhtskhtdhhtbbsagthdkgusdfjgfghdgrbt" + + "skfguioufgirufgieufgifugaeifugaeifugadifugbdifugadfiugawdfiuawgdfiuawdbvawiufvafuvwiufgwieufgdhtskhtdhhtbbsagthdkgusdfjgfghdgrbt" + + "skfguioufgirufgieufgifugaeifugaeifugadifugbdifugadfiugawdfiuawgdfiuawdbvawiufvafuvwiufgwieufgdhtskhtdhhtbbsagthdkgusdfjgfghdgrbt" + + "skfguioufgirufgieufgifugaeifugaeifugadifugbdifugadfiugawdfiuawgdfiuawdbvawiufvafuvwiufgwieufgdhtskhtdhhtbbsagthdkgusdfjgfghdgrbt" + + "skfguioufgirufgieufgifugaeifugaeifugadifugbdifugadfiugawdfiuawgdfiuawdbvawiufvafuvwiufgwieufgdhtskhtdhhtbbsagthdkgusdfjgfghdgrbt" + + "skfguioufgirufgieufgifugaeifugaeifugadifugbdifugadfiugawdfiuawgdfiuawdbvawiufvafuvwiufgwieufgdhtskhtdhhtbbsagthdkgusdfjgfghdgrbt" + + "skfguioufgirufgieufgifugaeifugaeifugadifugbdifugadfiugawdfiuawgdfiuawdbvawiufvafuvwiufgwieufgdhtskhtdhhtbbsagthdkgusdfjgfghdgrbt\"}" + + "]"; + public static final String TL_SHORT = + "[{\"0\":1, \"1\":\"Home\"},{\"0\":2, \"1\":\"Settings\"},{\"0\":3, \"1\":\"Casting Home\"}]"; + public static final String TL_LONG_BAD = + "[{\"0\":1, \"1\":\"Home\"},{\"0\":2, \"1\":\"Settings\"},{\"0\":3, \"1\":\"Casting Home\"}" + + ",{\"0\":254, \"1\":\"" + + "badskfguioufgirufgieufgifugaeifugaeifugadifugbdifugadfiugawdfiuawgdfiuawdbvawiufvafuvwiufgwieufgdhtskhtdhhtbbsagthdkgusdfjgfghdgrbt" + + "skfguioufgirufgieufgifugaeifugaeifugadifugbdifugadfiugawdfiuawgdfiuawdbvawiufvafuvwiufgwieufgdhtskhtdhhtbbsagthdkgusdfjgfghdgrbt" + + "skfguioufgirufgieufgifugaeifugaeifugadifugbdifugadfiugawdfiuawgdfiuawdbvawiufvafuvwiufgwieufgdhtskhtdhhtbbsagthdkgusdfjgfghdgrbt" + + "skfguioufgirufgieufgifugaeifugaeifugadifugbdifugadfiugawdfiuawgdfiuawdbvawiufvafuvwiufgwieufgdhtskhtdhhtbbsagthdkgusdfjgfghdgrbt" + + "skfguioufgirufgieufgifugaeifugaeifugadifugbdifugadfiugawdfiuawgdfiuawdbvawiufvafuvwiufgwieufgdhtskhtdhhtbbsagthdkgusdfjgfghdgrbt" + + "skfguioufgirufgieufgifugaeifugaeifugadifugbdifugadfiugawdfiuawgdfiuawdbvawiufvafuvwiufgwieufgdhtskhtdhhtbbsagthdkgusdfjgfghdgrbt" + + "skfguioufgirufgieufgifugaeifugaeifugadifugbdifugadfiugawdfiuawgdfiuawdbvawiufvafuvwiufgwieufgdhtskhtdhhtbbsagthdkgusdfjgfghdgrbt" + + "skfguioufgirufgieufgifugaeifugaeifugadifugbdifugadfiugawdfiuawgdfiuawdbvawiufvafuvwiufgwieufgdhtskhtdhhtbbsagthdkgusdfjgfghdgrbt" + + "skfguioufgirufgieufgifugaeifugaeifugadifugbdifugadfiugawdfiuawgdfiuawdbvawiufvafuvwiufgwieufgdhtskhtdhhtbbsagthdkgusdfjgfghdgrbt" + + "skfguioufgirufgieufgifugaeifugaeifugadifugbdifugadfiugawdfiuawgdfiuawdbvawiufvafuvwiufgwieufgdhtskhtdhhtbbsagthdkgusdfjgfghdgrbt" + + "skfguioufgirufgieufgifugaeifugaeifugadifugbdifugadfiugawdfiuawgdfiuawdbvawiufvafuvwiufgwieufgdhtskhtdhhtbbsagthdkgusdfjgfghdgrbt" + + "skfguioufgirufgieufgifugaeifugaeifugadifugbdifugadfiugawdfiuawgdfiuawdbvawiufvafuvwiufgwieufgdhtskhtdhhtbbsagthdkgusdfjgfghdgrbt" + + "skfguioufgirufgieufgifugaeifugaeifugadifugbdifugadfiugawdfiuawgdfiuawdbvawiufvafuvwiufgwieufgdhtskhtdhhtbbsagthdkgusdfjgfghdgrbt" + + "skfguioufgirufgieufgifugaeifugaeifugadifugbdifugadfiugawdfiuawgdfiuawdbvawiufvafuvwiufgwieufgdhtskhtdhhtbbsagthdkgusdfjgfghdgrbt" + + "skfguioufgirufgieufgifugaeifugaeifugadifugbdifugadfiugawdfiuawgdfiuawdbvawiufvafuvwiufgwieufgdhtskhtdhhtbbsagthdkgusdfjgfghdgrbt" + + "skfguioufgirufgieufgifugaeifugaeifugadifugbdifugadfiugawdfiuawgdfiuawdbvawiufvafuvwiufgwieufgdhtskhtdhhtbbsagthdkgusdfjgfghdgrbt" + + "skfguioufgirufgieufgifugaeifugaeifugadifugbdifugadfiugawdfiuawgdfiuawdbvawiufvafuvwiufgwieufgdhtskhtdhhtbbsagthdkgusdfjgfghdgrbt" + + "skfguioufgirufgieufgifugaeifugaeifugadifugbdifugadfiugawdfiuawgdfiuawdbvawiufvafuvwiufgwieufgdhtskhtdhhtbbsagthdkgusdfjgfghdgrbt" + + "skfguioufgirufgieufgifugaeifugaeifugadifugbdifugadfiugawdfiuawgdfiuawdbvawiufvafuvwiufgwieufgdhtskhtdhhtbbsagthdkgusdfjgfghdgrbt\"}" + + "]"; + private static AttributeHolder instance = new AttributeHolder(); private AttributeHolder() { // Setting up attribute defaults @@ -21,9 +108,7 @@ private AttributeHolder() { 3); setAttributeValue(Clusters.MediaPlayback.Id, Clusters.MediaPlayback.Attributes.CurrentState, 2); setAttributeValue( - Clusters.TargetNavigator.Id, - Clusters.TargetNavigator.Attributes.TargetList, - "[{\"0\":1, \"1\":\"Home\"},{\"0\":2, \"1\":\"Settings\"},{\"0\":3, \"1\":\"Casting Home\"}]"); + Clusters.TargetNavigator.Id, Clusters.TargetNavigator.Attributes.TargetList, TL_SHORT); setAttributeValue( Clusters.TargetNavigator.Id, Clusters.TargetNavigator.Attributes.CurrentTarget, 1); }; @@ -33,6 +118,9 @@ public static AttributeHolder getInstance() { } public void setAttributeValue(long clusterId, long attributeId, Object value) { + if (value == null) { + Log.d(TAG, "Setting null for cluster " + clusterId + " attribute " + attributeId); + } Map attributes = attributeValues.get(clusterId); if (attributes == null) { attributes = new HashMap<>(); diff --git a/examples/tv-app/android/App/content-app/src/main/java/com/example/contentapp/MainActivity.java b/examples/tv-app/android/App/content-app/src/main/java/com/example/contentapp/MainActivity.java index a5d6d706e35f34..70011e726bda38 100644 --- a/examples/tv-app/android/App/content-app/src/main/java/com/example/contentapp/MainActivity.java +++ b/examples/tv-app/android/App/content-app/src/main/java/com/example/contentapp/MainActivity.java @@ -10,6 +10,9 @@ import com.example.contentapp.matter.MatterAgentClient; import com.matter.tv.app.api.Clusters; import com.matter.tv.app.api.MatterIntentConstants; +import com.matter.tv.app.api.SetSupportedClustersRequest; +import com.matter.tv.app.api.SupportedCluster; +import java.util.ArrayList; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -20,6 +23,9 @@ public class MainActivity extends AppCompatActivity { private static final String ATTR_PS_PAUSED = "Playback State : PAUSED"; private static final String ATTR_PS_NOT_PLAYING = "Playback State : NOT_PLAYING"; private static final String ATTR_PS_BUFFERING = "Playback State : BUFFERING"; + private static final String ATTR_TL_LONG_BAD = "Target List : LONG BAD"; + private static final String ATTR_TL_LONG = "Target List : LONG"; + private static final String ATTR_TL_SHORT = "Target List : SHORT"; private final ExecutorService executorService = Executors.newSingleThreadExecutor(); @Override @@ -80,17 +86,59 @@ protected void onCreate(Bundle savedInstanceState) { reportAttributeChange( Clusters.MediaPlayback.Id, Clusters.MediaPlayback.Attributes.CurrentState); break; + case ATTR_TL_LONG_BAD: + AttributeHolder.getInstance() + .setAttributeValue( + Clusters.TargetNavigator.Id, + Clusters.TargetNavigator.Attributes.TargetList, + AttributeHolder.TL_LONG_BAD); + reportAttributeChange( + Clusters.TargetNavigator.Id, Clusters.TargetNavigator.Attributes.TargetList); + break; + case ATTR_TL_LONG: + AttributeHolder.getInstance() + .setAttributeValue( + Clusters.TargetNavigator.Id, + Clusters.TargetNavigator.Attributes.TargetList, + AttributeHolder.TL_LONG); + reportAttributeChange( + Clusters.TargetNavigator.Id, Clusters.TargetNavigator.Attributes.TargetList); + break; + case ATTR_TL_SHORT: + AttributeHolder.getInstance() + .setAttributeValue( + Clusters.TargetNavigator.Id, + Clusters.TargetNavigator.Attributes.TargetList, + AttributeHolder.TL_SHORT); + reportAttributeChange( + Clusters.TargetNavigator.Id, Clusters.TargetNavigator.Attributes.TargetList); + break; } }); Spinner dropdown = findViewById(R.id.spinnerAttribute); String[] items = - new String[] {ATTR_PS_PLAYING, ATTR_PS_PAUSED, ATTR_PS_NOT_PLAYING, ATTR_PS_BUFFERING}; + new String[] { + ATTR_PS_PLAYING, + ATTR_PS_PAUSED, + ATTR_PS_NOT_PLAYING, + ATTR_PS_BUFFERING, + ATTR_TL_LONG, + ATTR_TL_SHORT, + ATTR_TL_LONG_BAD + }; ArrayAdapter adapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_dropdown_item, items); dropdown.setAdapter(adapter); MatterAgentClient matterAgentClient = MatterAgentClient.getInstance(); - executorService.execute(matterAgentClient::reportClusters); + if (matterAgentClient != null) { + SetSupportedClustersRequest supportedClustersRequest = new SetSupportedClustersRequest(); + supportedClustersRequest.supportedClusters = new ArrayList(); + SupportedCluster supportedCluster = new SupportedCluster(); + supportedCluster.clusterIdentifier = 1; + supportedClustersRequest.supportedClusters.add(supportedCluster); + executorService.execute(() -> matterAgentClient.reportClusters(supportedClustersRequest)); + } } private void reportAttributeChange(final int clusterId, final int attributeId) { diff --git a/examples/tv-app/android/App/content-app/src/main/java/com/example/contentapp/matter/MatterAgentClient.java b/examples/tv-app/android/App/content-app/src/main/java/com/example/contentapp/matter/MatterAgentClient.java index 79287e7ca08194..8d34d7da5c80b6 100644 --- a/examples/tv-app/android/App/content-app/src/main/java/com/example/contentapp/matter/MatterAgentClient.java +++ b/examples/tv-app/android/App/content-app/src/main/java/com/example/contentapp/matter/MatterAgentClient.java @@ -10,31 +10,37 @@ import android.os.IBinder; import android.os.RemoteException; import android.util.Log; +import androidx.annotation.Nullable; import com.matter.tv.app.api.IMatterAppAgent; import com.matter.tv.app.api.MatterIntentConstants; import com.matter.tv.app.api.SetSupportedClustersRequest; -import com.matter.tv.app.api.SupportedCluster; -import java.util.ArrayList; import java.util.List; import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; public class MatterAgentClient { private static final String TAG = "MatterAgentClient"; - private static MatterAgentClient instance; + private static MatterAgentClient instance = new MatterAgentClient(); private IMatterAppAgent service; private boolean bound = false; private CountDownLatch latch = new CountDownLatch(1); + private static Context context; // TODO : Introduce dependency injection private MatterAgentClient() {}; + // This could be called from the main activity or the receiver. + // In either case cache the context in case the connection is lost and has to be reestablished. public static synchronized void initialize(Context context) { - if (instance == null || (instance.service == null && !instance.bound)) { - instance = new MatterAgentClient(); + instance.context = context; + initInternal(); + } + + private static void initInternal() { + if (instance.service == null || !instance.bound) { if (!instance.bindService(context)) { Log.e(TAG, "Matter agent binding request unsuccessful."); - instance = null; } else { Log.d(TAG, "Matter agent binding request successful."); } @@ -45,42 +51,57 @@ public static MatterAgentClient getInstance() { return instance; } - public void reportClusters() { - IMatterAppAgent matterAgent = instance.getMatterAgent(); - if (matterAgent == null) { - Log.e(TAG, "Matter agent not retrieved."); - return; - } - SetSupportedClustersRequest supportedClustersRequest = new SetSupportedClustersRequest(); - supportedClustersRequest.supportedClusters = new ArrayList(); - SupportedCluster supportedCluster = new SupportedCluster(); - supportedCluster.clusterIdentifier = 1; - - supportedClustersRequest.supportedClusters.add(supportedCluster); + public boolean reportClusters(SetSupportedClustersRequest supportedClustersRequest) { + IMatterAppAgent matterAgent = getOrReinitializeMatterAgent(); + if (matterAgent == null) return false; try { - boolean success = matterAgent.setSupportedClusters(supportedClustersRequest); - Log.d(TAG, "Setting supported clusters returned " + (success ? "True" : "False")); + return matterAgent.setSupportedClusters(supportedClustersRequest); } catch (RemoteException e) { - e.printStackTrace(); + Log.e(TAG, "Error invoking remote method to set supported clusters to Matter agent"); } + return false; } - public void reportAttributeChange(int clusterId, int attributeId) { - IMatterAppAgent matterAgent = instance.getMatterAgent(); - if (matterAgent == null) { - Log.e(TAG, "Matter agent not retrieved."); - return; - } + public boolean reportAttributeChange(int clusterId, int attributeId) { + IMatterAppAgent matterAgent = getOrReinitializeMatterAgent(); + if (matterAgent == null) return false; try { - matterAgent.reportAttributeChange(clusterId, attributeId); + return matterAgent.reportAttributeChange(clusterId, attributeId); } catch (RemoteException e) { Log.e(TAG, "Error invoking remote method to report attribute change to Matter agent"); } + return false; + } + + @Nullable + private IMatterAppAgent getOrReinitializeMatterAgent() { + IMatterAppAgent matterAgent = getMatterAgent(); + if (matterAgent == null) { + Log.w(TAG, "Matter agent not retrieved."); + if (context == null) { + Log.e(TAG, "Matter agent never initialized (missing context). Cannot reinitialize."); + return null; + } + initInternal(); + matterAgent = getMatterAgent(); + if (matterAgent == null) { + Log.e(TAG, "Matter agent could not be reinitialized."); + return null; + } + } + return matterAgent; } private IMatterAppAgent getMatterAgent() { try { - latch.await(); + // If this was the first call after trying to bind to the service, + // we have to wait till service connection is established. + // put a check for the latch existing. just in case someone makes this call before initialize. + if (latch != null) { + if (!latch.await(8, TimeUnit.SECONDS)) { + Log.e(TAG, "Timed out while waiting for service connection."); + } + } return service; } catch (InterruptedException e) { Log.e(TAG, "Interrupted while waiting for service connection.", e); @@ -89,7 +110,6 @@ private IMatterAppAgent getMatterAgent() { } private synchronized boolean bindService(Context context) { - ServiceConnection serviceConnection = new MyServiceConnection(); final Intent intent = new Intent(MatterIntentConstants.ACTION_MATTER_AGENT); if (intent.getComponent() == null) { @@ -109,9 +129,9 @@ private synchronized boolean bindService(Context context) { } try { - Log.e(TAG, "Binding to service"); - bound = context.bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE); - return bound; + Log.d(TAG, "Binding to service"); + latch = new CountDownLatch(1); + return context.bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE); } catch (final Throwable e) { Log.e(TAG, "Exception binding to service", e); } @@ -221,11 +241,16 @@ public void onServiceConnected(ComponentName name, IBinder binder) { "onServiceConnected for API with intent action %s", MatterIntentConstants.ACTION_MATTER_AGENT)); service = IMatterAppAgent.Stub.asInterface(binder); - latch.countDown(); + bound = true; + // latch could already be at zero but should never be null here. But check anyway. + if (latch != null) { + latch.countDown(); + } } @Override public void onServiceDisconnected(ComponentName name) { + bound = false; service = null; } } diff --git a/examples/tv-app/android/App/content-app/src/main/java/com/example/contentapp/receiver/MatterCommandReceiver.java b/examples/tv-app/android/App/content-app/src/main/java/com/example/contentapp/receiver/MatterCommandReceiver.java index c8d8987048be76..2fda386654a5c1 100644 --- a/examples/tv-app/android/App/content-app/src/main/java/com/example/contentapp/receiver/MatterCommandReceiver.java +++ b/examples/tv-app/android/App/content-app/src/main/java/com/example/contentapp/receiver/MatterCommandReceiver.java @@ -7,6 +7,7 @@ import android.util.Log; import com.example.contentapp.AttributeHolder; import com.example.contentapp.MainActivity; +import com.example.contentapp.matter.MatterAgentClient; import com.matter.tv.app.api.MatterIntentConstants; public class MatterCommandReceiver extends BroadcastReceiver { @@ -14,6 +15,9 @@ public class MatterCommandReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { + + MatterAgentClient.initialize(context.getApplicationContext()); + final String intentAction = intent.getAction(); Log.i(TAG, "Some Intent received from the matter server " + intentAction); if (intentAction == null || intentAction.isEmpty()) {