Skip to content

Commit

Permalink
Merge branch 'master' into fix-pw-config-file
Browse files Browse the repository at this point in the history
  • Loading branch information
andy31415 authored Sep 20, 2022
2 parents 60901a5 + 3aa138f commit 6e3841c
Show file tree
Hide file tree
Showing 26 changed files with 685 additions and 82 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/zap_templates.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ concurrency:
jobs:
zap_templates:
name: ZAP templates generation
timeout-minutes: 120
timeout-minutes: 90

runs-on: ubuntu-20.04
container:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
{{~#if (isStrEqual constraint "hasValue")}}
{{~! Already handled above~}}
{{~else if (isStrEqual constraint "type")}}
{{~assertSameTestType (asTestType ../type ../isArray) value~}}
VerifyOrReturn(CheckConstraintType("{{asPropertyValue context=..}}", "{{asTestType ../type ../isArray}}", "{{value}}"));
{{~else if (isStrEqual constraint "format")}}VerifyOrReturn(CheckConstraintFormat("{{asPropertyValue context=..}}", "", "{{value}}"));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
package com.matter.tv.app.api;

import com.matter.tv.app.api.SetSupportedClustersRequest;
import com.matter.tv.app.api.ReportAttributeChangeRequest;

/*
* To use this interface, partners should query for and bind to a service that handles the "com.matter.tv.app.api.action.MatterAppAgent" Action.
Expand All @@ -29,5 +28,5 @@ interface IMatterAppAgent {
* @return - ReportAttributeChangeResult, returns success or error code
*/
// TODO : replace the boolean with some kind of enumerated status field
boolean reportAttributeChange(in ReportAttributeChangeRequest request);
boolean reportAttributeChange(in int clusterId, in int attributeId);
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.matter.tv.app.api;

public class Clusters {
// Clusters
public static class MediaPlayback {
public static final int Id = 1286;

public static class Attributes {
public static final int CurrentState = 0;
}

public static class PlaybackStateEnum {
public static final int Playing = 0;
public static final int Paused = 1;
public static final int NotPlaying = 2;
public static final int Buffering = 3;
}
}

public static class ContentLauncher {
public static final int Id = 1290;

public static class Attributes {
public static final int AcceptHeader = 0;
public static final int SupportedStreamingProtocols = 1;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.example.contentapp;

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<Long, Map<Long, Object>> attributeValues = new HashMap<>();

private AttributeHolder() {};

public static AttributeHolder getInstance() {
return instance;
}

public void setAttributeValue(long clusterId, long attributeId, Object value) {
Map<Long, Object> attributes = attributeValues.get(clusterId);
if (attributes == null) {
attributes = new HashMap<>();
attributeValues.put(clusterId, attributes);
}
attributes.put(attributeId, value);
}

public Object getAttributeValue(long clusterId, long attributeId) {
Map<Long, Object> attributes = attributeValues.get(clusterId);
return attributes.get(attributeId);
}
}
Original file line number Diff line number Diff line change
@@ -1,21 +1,121 @@
package com.example.contentapp;

import android.content.Intent;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.Spinner;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import com.example.contentapp.matter.MatterAgentClient;
import com.matter.tv.app.api.Clusters;
import com.matter.tv.app.api.MatterIntentConstants;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class MainActivity extends AppCompatActivity {

private static final String TAG = "ContentAppMainActivity";
private static final String ATTR_PS_PLAYING = "Playback State : PLAYING";
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 final ExecutorService executorService = Executors.newSingleThreadExecutor();

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

MatterAgentClient.initialize(getApplicationContext());

setContentView(R.layout.activity_main);
MatterAgentClient matterAgentClient = MatterAgentClient.getInstance(getApplicationContext());
final ExecutorService executorService = Executors.newSingleThreadExecutor();

Intent intent = getIntent();
String command = intent.getStringExtra(MatterIntentConstants.EXTRA_COMMAND_PAYLOAD);

// use the text in a TextView
TextView textView = (TextView) findViewById(R.id.commandTextView);
textView.setText("Command Payload : " + command);

Button sendMessageButton = findViewById(R.id.sendMessageButton);

sendMessageButton.setOnClickListener(
view -> {
Spinner dropdown = findViewById(R.id.spinnerAttribute);
String attribute = (String) dropdown.getSelectedItem();
switch (attribute) {
case ATTR_PS_PLAYING:
AttributeHolder.getInstance()
.setAttributeValue(
Clusters.MediaPlayback.Id,
Clusters.MediaPlayback.Attributes.CurrentState,
Clusters.MediaPlayback.PlaybackStateEnum.Playing);
reportAttributeChange(
Clusters.MediaPlayback.Id, Clusters.MediaPlayback.Attributes.CurrentState);
break;
case ATTR_PS_PAUSED:
AttributeHolder.getInstance()
.setAttributeValue(
Clusters.MediaPlayback.Id,
Clusters.MediaPlayback.Attributes.CurrentState,
Clusters.MediaPlayback.PlaybackStateEnum.Paused);
reportAttributeChange(
Clusters.MediaPlayback.Id, Clusters.MediaPlayback.Attributes.CurrentState);
break;
case ATTR_PS_BUFFERING:
AttributeHolder.getInstance()
.setAttributeValue(
Clusters.MediaPlayback.Id,
Clusters.MediaPlayback.Attributes.CurrentState,
Clusters.MediaPlayback.PlaybackStateEnum.Buffering);
reportAttributeChange(
Clusters.MediaPlayback.Id, Clusters.MediaPlayback.Attributes.CurrentState);
break;
case ATTR_PS_NOT_PLAYING:
AttributeHolder.getInstance()
.setAttributeValue(
Clusters.MediaPlayback.Id,
Clusters.MediaPlayback.Attributes.CurrentState,
Clusters.MediaPlayback.PlaybackStateEnum.NotPlaying);
reportAttributeChange(
Clusters.MediaPlayback.Id, Clusters.MediaPlayback.Attributes.CurrentState);
break;
}
});
Spinner dropdown = findViewById(R.id.spinnerAttribute);
String[] items =
new String[] {ATTR_PS_PLAYING, ATTR_PS_PAUSED, ATTR_PS_NOT_PLAYING, ATTR_PS_BUFFERING};
ArrayAdapter<String> adapter =
new ArrayAdapter<>(this, android.R.layout.simple_spinner_dropdown_item, items);
dropdown.setAdapter(adapter);

MatterAgentClient matterAgentClient = MatterAgentClient.getInstance();
executorService.execute(matterAgentClient::reportClusters);

// Setting up attribute defaults
AttributeHolder.getInstance()
.setAttributeValue(
Clusters.ContentLauncher.Id,
Clusters.ContentLauncher.Attributes.AcceptHeader,
"[\"video/mp4\", \"application/x-mpegURL\", \"application/dash+xml\"]");
AttributeHolder.getInstance()
.setAttributeValue(
Clusters.ContentLauncher.Id,
Clusters.ContentLauncher.Attributes.SupportedStreamingProtocols,
3);
AttributeHolder.getInstance()
.setAttributeValue(
Clusters.MediaPlayback.Id, Clusters.MediaPlayback.Attributes.CurrentState, 2);
}

private void reportAttributeChange(final int clusterId, final int attributeId) {
executorService.execute(
new Runnable() {
@Override
public void run() {
MatterAgentClient client = MatterAgentClient.getInstance();
client.reportAttributeChange(clusterId, attributeId);
}
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public class MatterAgentClient {
// TODO : Introduce dependency injection
private MatterAgentClient() {};

public static synchronized MatterAgentClient getInstance(Context context) {
public static synchronized void initialize(Context context) {
if (instance == null || (instance.service == null && !instance.bound)) {
instance = new MatterAgentClient();
if (!instance.bindService(context)) {
Expand All @@ -39,6 +39,9 @@ public static synchronized MatterAgentClient getInstance(Context context) {
Log.d(TAG, "Matter agent binding request successful.");
}
}
}

public static MatterAgentClient getInstance() {
return instance;
}

Expand All @@ -62,6 +65,19 @@ public void reportClusters() {
}
}

public void reportAttributeChange(int clusterId, int attributeId) {
IMatterAppAgent matterAgent = instance.getMatterAgent();
if (matterAgent == null) {
Log.e(TAG, "Matter agent not retrieved.");
return;
}
try {
matterAgent.reportAttributeChange(clusterId, attributeId);
} catch (RemoteException e) {
Log.e(TAG, "Error invoking remote method to report attribute change to Matter agent");
}
}

private IMatterAppAgent getMatterAgent() {
try {
latch.await();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import com.example.contentapp.AttributeHolder;
import com.example.contentapp.MainActivity;
import com.matter.tv.app.api.MatterIntentConstants;

public class MatterCommandReceiver extends BroadcastReceiver {
private static final String TAG = "MatterCommandReceiver";
private static final int ACCEPT_HEADER = 0;
private static final int SUPPORTED_STREAMING_PROTOCOLS = 1;

@Override
public void onReceive(Context context, Intent intent) {
Expand All @@ -24,36 +24,41 @@ public void onReceive(Context context, Intent intent) {
switch (intentAction) {
case MatterIntentConstants.ACTION_MATTER_COMMAND:
int commandId = intent.getIntExtra(MatterIntentConstants.EXTRA_COMMAND_ID, -1);
int clusterId = intent.getIntExtra(MatterIntentConstants.EXTRA_CLUSTER_ID, -1);
if (commandId != -1) {
int clusterId = intent.getIntExtra(MatterIntentConstants.EXTRA_CLUSTER_ID, -1);
byte[] commandPayload =
intent.getByteArrayExtra(MatterIntentConstants.EXTRA_COMMAND_PAYLOAD);
Log.d(
TAG,
String command = new String(commandPayload);
String message =
new StringBuilder()
.append("Received matter command ")
.append(commandId)
.append(" on cluster ")
.append(clusterId)
.append(" with payload : ")
.append(new String(commandPayload))
.toString());
.append(command)
.toString();
Log.d(TAG, message);
String response = "{\"0\":1, \"1\":\"custom response from content app\"}";

Intent in = new Intent(context, MainActivity.class);
in.putExtra(MatterIntentConstants.EXTRA_COMMAND_PAYLOAD, command);
context.startActivity(in);

Log.d(TAG, "Started activity. Now sending response");

sendResponseViaPendingIntent(context, intent, response);
} else {
int attributeId = intent.getIntExtra(MatterIntentConstants.EXTRA_ATTRIBUTE_ID, -1);
String attributeAction =
intent.getStringExtra(MatterIntentConstants.EXTRA_ATTRIBUTE_ACTION);
if (attributeAction.equals(MatterIntentConstants.ATTRIBUTE_ACTION_READ)) {
String response;
if (attributeId == ACCEPT_HEADER) {
response =
"{\"0\": [\"video/mp4\", \"application/x-mpegURL\", \"application/dash+xml\"] }";
} else if (attributeId == SUPPORTED_STREAMING_PROTOCOLS) {
response = "{\"1\":3}";
} else {
response = "";
}
String response =
"{\""
+ attributeId
+ "\":"
+ AttributeHolder.getInstance().getAttributeValue(clusterId, attributeId)
+ "}";
sendResponseViaPendingIntent(context, intent, response);
} else {
Log.e(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,49 @@
tools:context=".MainActivity">

<TextView
android:id="@+id/helloTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:textSize="10pt"
app:layout_constraintBottom_toTopOf="@+id/commandTextView"
app:layout_constraintTop_toTopOf="parent" />

<TextView
android:id="@+id/commandTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toEndOf="@id/helloTextView"
android:textSize="10pt"
android:text="No Command!!"
app:layout_constraintBottom_toTopOf="@+id/sendMessageButton"
app:layout_constraintTop_toBottomOf="@+id/helloTextView" />

<Spinner
android:id="@+id/spinnerAttribute"
android:layout_width="239dp"
android:layout_height="40dp"
android:background="@android:drawable/btn_dropdown"
android:spinnerMode="dropdown"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@+id/sendMessageButton"
app:layout_constraintTop_toBottomOf="@+id/commandTextView" />


<Button
android:id="@+id/sendMessageButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toEndOf="@id/helloTextView"
android:text="Update"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/spinnerAttribute"
app:layout_constraintTop_toBottomOf="@+id/commandTextView" />

<androidx.constraintlayout.widget.Group
android:id="@+id/group"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:constraint_referenced_ids="spinnerAttribute,sendMessageButton" />

</androidx.constraintlayout.widget.ConstraintLayout>
Loading

0 comments on commit 6e3841c

Please sign in to comment.