Skip to content

Commit

Permalink
Persist the endpoints that were discovered to maintain endpointIds ac…
Browse files Browse the repository at this point in the history
…ross restart of tv-app (#22354)

* Persist the endpoints that were discovered to maintain endpointIds across startup.

* Refactor to remove commissioner initialization from AppImpl to TvApp.

* Restyled by google-java-format

* Restyled by clang-format

* Roll back change because of lint error.

* Address review comments regarding memory alocation and logs.

* Restyled by google-java-format

* Restyled by clang-format

Co-authored-by: Restyled.io <[email protected]>
  • Loading branch information
2 people authored and pull[bot] committed Aug 30, 2023
1 parent 8d7765c commit 1728914
Show file tree
Hide file tree
Showing 15 changed files with 266 additions and 140 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import com.matter.tv.server.fragments.ContentAppFragment;
import com.matter.tv.server.fragments.QrCodeFragment;
import com.matter.tv.server.fragments.TerminalFragment;
import com.matter.tv.server.service.AppPlatformService;
import com.matter.tv.server.service.MatterServant;
import java.util.LinkedHashMap;

public class MainActivity extends AppCompatActivity {
Expand Down Expand Up @@ -43,7 +43,7 @@ protected void onCreate(Bundle savedInstanceState) {

// MainActivity is needed to launch dialog prompt
// in UserPrompter
AppPlatformService.get().setActivity(this);
MatterServant.get().setActivity(this);

BottomNavigationView bottomNavigationView = findViewById(R.id.bottom_navigation);
bottomNavigationView.setOnItemSelectedListener(navListener);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,30 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.util.Log;
import androidx.annotation.NonNull;
import com.matter.tv.server.MatterCommissioningPrompter;
import com.matter.tv.server.handlers.ContentAppEndpointManagerImpl;
import com.matter.tv.server.model.ContentApp;
import com.matter.tv.server.receivers.ContentAppDiscoveryService;
import com.matter.tv.server.tvapp.AppPlatform;
import java.util.HashMap;
import java.util.Map;

/**
* This class facilitates the communication with the ContentAppPlatform. It uses the JNI interface
* provided via the {@link AppPlatform} class to communicate with the linux layer of the
* platform-app. This class also manages the content app endpoints that get added via the
* ContentAppPlatform. It manages the persistence of the endpoints that were discovered to be able
* to reuse endpointIds after restart of the platform-app.
*/
public class AppPlatformService {

private static final String TAG = "AppPlatformService";
private static final String MATTER_APPPLATFORM_ENDPOINTS = "matter.appplatform.endpoints";
private AppPlatform mAppPlatform;
private BroadcastReceiver mBroadcastReceiver;
private SharedPreferences discoveredEndpoints;

private AppPlatformService() {}

Expand All @@ -49,14 +62,23 @@ public static AppPlatformService get() {

public void init(@NonNull Context context) {
this.context = context;
mAppPlatform =
new AppPlatform(
new MatterCommissioningPrompter(activity), new ContentAppEndpointManagerImpl(context));
discoveredEndpoints =
context.getSharedPreferences(MATTER_APPPLATFORM_ENDPOINTS, Context.MODE_PRIVATE);
mAppPlatform = new AppPlatform(new ContentAppEndpointManagerImpl(context));
ContentAppDiscoveryService.getReceiverInstance().registerSelf(context.getApplicationContext());
Map<String, Integer> previouslyPersistedEndpoints = new HashMap();
previouslyPersistedEndpoints.putAll((Map<String, Integer>) discoveredEndpoints.getAll());
for (ContentApp app :
ContentAppDiscoveryService.getReceiverInstance().getDiscoveredContentApps().values()) {
addContentApp(app);
previouslyPersistedEndpoints.remove(app.getAppName());
}
SharedPreferences.Editor editor = discoveredEndpoints.edit();
for (Map.Entry<String, Integer> appEntry : previouslyPersistedEndpoints.entrySet()) {
editor.remove(appEntry.getKey());
// TODO : Figure out how to cleanup ACLs
}
editor.apply();
registerReceiver();
}

Expand All @@ -80,7 +102,7 @@ public void onReceive(Context context, Intent intent) {
intent.getIntExtra(
ContentAppDiscoveryService.DISCOVERY_APPAGENT_EXTRA_ENDPOINTID, -1);
if (endpointId != -1) {
removeContentApp(endpointId);
removeContentApp(endpointId, packageName);
}
}
}
Expand All @@ -98,17 +120,41 @@ public void setActivity(Activity activity) {
}

public void addContentApp(ContentApp app) {
app.setEndpointId(
mAppPlatform.addContentApp(
app.getVendorName(),
app.getVendorId(),
app.getAppName(),
app.getProductId(),
"1.0",
new ContentAppEndpointManagerImpl(context)));
int retEndpointId = -1;
int desiredEndpointId = discoveredEndpoints.getInt(app.getAppName(), -1);
if (desiredEndpointId > 0) {
retEndpointId =
mAppPlatform.addContentAppAtEndpoint(
app.getVendorName(),
app.getVendorId(),
app.getAppName(),
app.getProductId(),
"1.0",
desiredEndpointId,
new ContentAppEndpointManagerImpl(context));
} else {
retEndpointId =
mAppPlatform.addContentApp(
app.getVendorName(),
app.getVendorId(),
app.getAppName(),
app.getProductId(),
"1.0",
new ContentAppEndpointManagerImpl(context));
}
if (retEndpointId > 0) {
app.setEndpointId(retEndpointId);
discoveredEndpoints.edit().putInt(app.getAppName(), app.getEndpointId()).apply();
} else {
Log.e(TAG, "Could not add content app as endpoint. App Name " + app.getAppName());
}
}

public int removeContentApp(int endpointID) {
return mAppPlatform.removeContentApp(endpointID);
public int removeContentApp(int endpointID, String appName) {
int retEndpointId = mAppPlatform.removeContentApp(endpointID);
if (endpointID == retEndpointId) {
discoveredEndpoints.edit().remove(appName).apply();
}
return retEndpointId;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
*/
package com.matter.tv.server.service;

import android.app.Activity;
import android.content.Context;
import android.util.Log;
import androidx.annotation.NonNull;
Expand All @@ -29,6 +30,7 @@
import chip.platform.NsdManagerServiceResolver;
import chip.platform.PreferencesConfigurationManager;
import chip.platform.PreferencesKeyValueStoreManager;
import com.matter.tv.server.MatterCommissioningPrompter;
import com.matter.tv.server.tvapp.ChannelManagerStub;
import com.matter.tv.server.tvapp.Clusters;
import com.matter.tv.server.tvapp.ContentLaunchManagerStub;
Expand Down Expand Up @@ -65,6 +67,7 @@ public static MatterServant get() {
}

private Context context;
private Activity activity;

public void init(@NonNull Context context) {

Expand Down Expand Up @@ -140,6 +143,10 @@ public void onCommissioningComplete() {
chipAppServer.startApp();
}

public void initCommissioner() {
mTvApp.initializeCommissioner(new MatterCommissioningPrompter(activity));
}

public void restart() {
chipAppServer.stopApp();
chipAppServer.startApp();
Expand All @@ -150,6 +157,10 @@ public void toggleOnOff() {
mIsOn = !mIsOn;
}

public void setActivity(Activity activity) {
this.activity = activity;
}

public void sendCustomCommand(String customCommand) {
Log.i(MatterServant.class.getName(), customCommand);
// TODO: insert logic ot send custom command here
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public void onCreate() {
super.onCreate();
// Start Matter Server
MatterServant.get().init(this.getApplicationContext());
MatterServant.get().initCommissioner();

AppPlatformService.get().init(this.getApplicationContext());
}
Expand Down
1 change: 0 additions & 1 deletion examples/tv-app/android/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ shared_library("jni") {
"java/AppImpl.cpp",
"java/AppImpl.h",
"java/AppPlatform-JNI.cpp",
"java/AppPlatform-JNI.h",
"java/AppPlatformShellCommands-JNI.cpp",
"java/AppPlatformShellCommands-JNI.h",
"java/ChannelManager.cpp",
Expand Down
120 changes: 49 additions & 71 deletions examples/tv-app/android/java/AppImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@
#include <inttypes.h>
#include <jni.h>
#include <lib/core/CHIPCore.h>
#include <lib/core/DataModelTypes.h>
#include <lib/shell/Commands.h>
#include <lib/shell/Engine.h>
#include <lib/shell/commands/Help.h>
Expand All @@ -49,49 +48,6 @@ using namespace chip;
using namespace chip::AppPlatform;

#if CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED
class MyPincodeService : public PincodeService
{
uint32_t FetchCommissionPincodeFromContentApp(uint16_t vendorId, uint16_t productId, CharSpan rotatingId) override
{
return ContentAppPlatform::GetInstance().GetPincodeFromContentApp(vendorId, productId, rotatingId);
}
};
MyPincodeService gMyPincodeService;

class MyPostCommissioningListener : public PostCommissioningListener
{
void CommissioningCompleted(uint16_t vendorId, uint16_t productId, NodeId nodeId, Messaging::ExchangeManager & exchangeMgr,
SessionHandle & sessionHandle) override
{

ContentAppPlatform::GetInstance().ManageClientAccess(
exchangeMgr, sessionHandle, vendorId, GetDeviceCommissioner()->GetNodeId(), OnSuccessResponse, OnFailureResponse);
}

/* Callback when command results in success */
static void OnSuccessResponse(void * context)
{
ChipLogProgress(Controller, "OnSuccessResponse - Binding Add Successfully");
CommissionerDiscoveryController * cdc = GetCommissionerDiscoveryController();
if (cdc != nullptr)
{
cdc->PostCommissioningSucceeded();
}
}

/* Callback when command results in failure */
static void OnFailureResponse(void * context, CHIP_ERROR error)
{
ChipLogProgress(Controller, "OnFailureResponse - Binding Add Failed");
CommissionerDiscoveryController * cdc = GetCommissionerDiscoveryController();
if (cdc != nullptr)
{
cdc->PostCommissioningFailed(error);
}
}
};

MyPostCommissioningListener gMyPostCommissioningListener;
ContentAppFactoryImpl gFactory;

ContentAppFactoryImpl * GetContentAppFactoryImpl()
Expand Down Expand Up @@ -363,14 +319,36 @@ ContentApp * ContentAppFactoryImpl::LoadContentApp(const CatalogVendorApp & vend
return nullptr;
}

EndpointId ContentAppFactoryImpl::AddContentApp(ContentAppImpl * app, jobject contentAppEndpointManager)
EndpointId ContentAppFactoryImpl::AddContentApp(const char * szVendorName, uint16_t vendorId, const char * szApplicationName,
uint16_t productId, const char * szApplicationVersion, jobject manager)
{
DataVersion * dataVersionBuf = new DataVersion[ArraySize(contentAppClusters)];
ContentAppImpl * app =
new ContentAppImpl(szVendorName, vendorId, szApplicationName, productId, szApplicationVersion, "20202021", manager);
EndpointId epId = ContentAppPlatform::GetInstance().AddContentApp(
app, &contentAppEndpoint, Span<DataVersion>(dataVersionBuf, ArraySize(contentAppClusters)),
Span<const EmberAfDeviceType>(gContentAppDeviceType));
ChipLogProgress(DeviceLayer, "ContentAppFactoryImpl AddContentApp endpoint returned %d. Endpoint set %d", epId,
app->GetEndpointId());
mContentApps.push_back(app);
mDataVersions.push_back(dataVersionBuf);
return epId;
}

EndpointId ContentAppFactoryImpl::AddContentApp(const char * szVendorName, uint16_t vendorId, const char * szApplicationName,
uint16_t productId, const char * szApplicationVersion, jobject manager,
EndpointId desiredEndpointId)
{
DataVersion dataVersionBuf[ArraySize(contentAppClusters)];
EndpointId epId = ContentAppPlatform::GetInstance().AddContentApp(app, &contentAppEndpoint, Span<DataVersion>(dataVersionBuf),
Span<const EmberAfDeviceType>(gContentAppDeviceType));
DataVersion * dataVersionBuf = new DataVersion[ArraySize(contentAppClusters)];
ContentAppImpl * app =
new ContentAppImpl(szVendorName, vendorId, szApplicationName, productId, szApplicationVersion, "20202021", manager);
EndpointId epId = ContentAppPlatform::GetInstance().AddContentApp(
app, &contentAppEndpoint, Span<DataVersion>(dataVersionBuf, ArraySize(contentAppClusters)),
Span<const EmberAfDeviceType>(gContentAppDeviceType), desiredEndpointId);
ChipLogProgress(DeviceLayer, "ContentAppFactoryImpl AddContentApp endpoint returned %d. Endpoint set %d", epId,
app->GetEndpointId());
mContentApps.push_back(app);
mDataVersions.push_back(dataVersionBuf);
return epId;
}

Expand All @@ -383,14 +361,21 @@ EndpointId ContentAppFactoryImpl::RemoveContentApp(EndpointId epId)
{
ChipLogProgress(DeviceLayer, "ContentAppFactoryImpl RemoveContentApp endpointId %d", epId);
EndpointId removedEndpointID = ContentAppPlatform::GetInstance().RemoveContentApp(app);
if (removedEndpointID != 0)
// Only remove the app from the set of content apps if they were dynamically added and not part of the static list of
// apps
if (removedEndpointID != 0 && i > APP_LIBRARY_SIZE)
{
mContentApps.erase(mContentApps.begin() + static_cast<int>(i));
DataVersion * dataVersionBuf = mDataVersions.at(i - APP_LIBRARY_SIZE);
mDataVersions.erase(mDataVersions.begin() + static_cast<int>(i - APP_LIBRARY_SIZE));
// deallocate memory for objects that were created when adding the content app dynamically.
delete[] dataVersionBuf;
delete app;
}
return removedEndpointID;
}
}
return 0;
return kInvalidEndpointId;
}

void ContentAppFactoryImpl::AddAdminVendorId(uint16_t vendorId)
Expand All @@ -416,7 +401,7 @@ Access::Privilege ContentAppFactoryImpl::GetVendorPrivilege(uint16_t vendorId)

#endif // CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED

CHIP_ERROR InitVideoPlayerPlatform(JNIMyUserPrompter * userPrompter, jobject contentAppEndpointManager)
CHIP_ERROR InitVideoPlayerPlatform(jobject contentAppEndpointManager)
{
#if CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED
ContentAppPlatform::GetInstance().SetupAppPlatform();
Expand All @@ -433,21 +418,6 @@ CHIP_ERROR InitVideoPlayerPlatform(JNIMyUserPrompter * userPrompter, jobject con

#endif // CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED

#if CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE
CommissionerDiscoveryController * cdc = GetCommissionerDiscoveryController();
if (cdc != nullptr && userPrompter != nullptr)
{
cdc->SetPincodeService(&gMyPincodeService);
cdc->SetUserPrompter(userPrompter);
cdc->SetPostCommissioningListener(&gMyPostCommissioningListener);
}

ChipLogProgress(AppServer, "Starting commissioner");
ReturnErrorOnFailure(InitCommissioner(CHIP_PORT + 2 + 10, CHIP_UDC_PORT));
ChipLogProgress(AppServer, "Started commissioner");

#endif // CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE

// Disable last fixed endpoint, which is used as a placeholder for all of the
// supported clusters so that ZAP will generated the requisite code.
ChipLogDetail(DeviceLayer, "TV App: Disabling Fixed Content App Endpoints");
Expand All @@ -459,12 +429,20 @@ EndpointId AddContentApp(const char * szVendorName, uint16_t vendorId, const cha
const char * szApplicationVersion, jobject manager)
{
#if CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED
ContentAppImpl * app =
new ContentAppImpl(szVendorName, vendorId, szApplicationName, productId, szApplicationVersion, "20202021", manager);
ChipLogProgress(DeviceLayer, "AppImpl: AddContentApp vendorId=%d applicationName=%s ", vendorId, szApplicationName);
return gFactory.AddContentApp(app, manager);
return gFactory.AddContentApp(szVendorName, vendorId, szApplicationName, productId, szApplicationVersion, manager);
#endif // CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED
return kInvalidEndpointId;
}

EndpointId AddContentApp(const char * szVendorName, uint16_t vendorId, const char * szApplicationName, uint16_t productId,
const char * szApplicationVersion, EndpointId endpointId, jobject manager)
{
#if CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED
ChipLogProgress(DeviceLayer, "AppImpl: AddContentApp vendorId=%d applicationName=%s ", vendorId, szApplicationName);
return gFactory.AddContentApp(szVendorName, vendorId, szApplicationName, productId, szApplicationVersion, manager, endpointId);
#endif // CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED
return 0;
return kInvalidEndpointId;
}

EndpointId RemoveContentApp(EndpointId epId)
Expand All @@ -473,5 +451,5 @@ EndpointId RemoveContentApp(EndpointId epId)
ChipLogProgress(DeviceLayer, "AppImpl: RemoveContentApp endpointId=%d ", epId);
return gFactory.RemoveContentApp(epId);
#endif // CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED
return 0;
return kInvalidEndpointId;
}
Loading

0 comments on commit 1728914

Please sign in to comment.