Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AccountLogin Login/Logout command support #34162

Merged
merged 74 commits into from
Aug 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
74 commits
Select commit Hold shift + click to select a range
8f98caf
AccountLogin Login/Logout command support
mthiesc Jun 28, 2024
2b99f24
HandleLogin in ContentAppPlatform::ManageClientAccess
mthiesc Jul 4, 2024
5c1bb91
Cache rotating ID in OnUserDirectedCommissioningRequest
mthiesc Jul 6, 2024
33fad6d
Restyled by google-java-format
restyled-commits Jul 6, 2024
2713b60
Restyled by clang-format
restyled-commits Jul 6, 2024
cb826a5
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 10, 2024
2029347
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 11, 2024
473c3ab
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 11, 2024
d7747b0
Update content app
lazarkov Jul 11, 2024
d5915a3
Restyled by whitespace
restyled-commits Jul 11, 2024
c4489c4
Restyled by clang-format
restyled-commits Jul 11, 2024
343f1bf
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 11, 2024
b86f8ba
Update response
lazarkov Jul 11, 2024
fe52e9b
Update method name
lazarkov Jul 11, 2024
3f9ba8c
Restyled by google-java-format
restyled-commits Jul 11, 2024
4b8d323
Update src/app/app-platform/ContentApp.h
lazarkov Jul 11, 2024
d995175
Update content app platform validation
lazarkov Jul 11, 2024
9067357
Update validation logic
lazarkov Jul 11, 2024
8957b1f
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 11, 2024
7289e08
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 11, 2024
b6b2927
Update logic
lazarkov Jul 11, 2024
5cb6dd6
Update responses
lazarkov Jul 11, 2024
471d838
Restyled by clang-format
restyled-commits Jul 11, 2024
968adfe
Simplify logic
lazarkov Jul 11, 2024
45a3f12
Restyled by whitespace
restyled-commits Jul 11, 2024
8836681
clean up
lazarkov Jul 11, 2024
e1cb367
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 11, 2024
15c904f
Update code
lazarkov Jul 12, 2024
0e910fe
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 12, 2024
af9d528
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 12, 2024
d422046
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 13, 2024
57894e4
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 15, 2024
ee443e3
Update content app with dynamic pin code
lazarkov Jul 15, 2024
8fa8ae2
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 15, 2024
8ec3d2a
Restyled by google-java-format
restyled-commits Jul 15, 2024
dde2830
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 16, 2024
82dab86
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 16, 2024
9d68f73
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 16, 2024
b208c46
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 17, 2024
35155b7
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 17, 2024
1d28980
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 17, 2024
580605d
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 17, 2024
5c76617
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 18, 2024
5356da2
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 19, 2024
2ca28f6
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 19, 2024
cb9feba
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 19, 2024
46cb529
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 19, 2024
0d9dc71
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 20, 2024
04726e4
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 20, 2024
538425c
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 22, 2024
5d27aba
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 22, 2024
fee0b92
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 22, 2024
40057a0
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 23, 2024
e765019
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 24, 2024
fb33ae2
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 24, 2024
092cdb2
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 24, 2024
cebfe2e
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 25, 2024
768f608
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 25, 2024
a9d1067
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 26, 2024
9ce6830
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 26, 2024
7feb6ef
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 26, 2024
0cc3860
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 26, 2024
6f598e9
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 26, 2024
43c87e8
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 29, 2024
1da644e
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Jul 29, 2024
3929ab6
Merge branch 'master' into accountlogin-login-logout-support
mthiesc Aug 2, 2024
d48832c
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Aug 2, 2024
c863bae
Merge branch 'master' into accountlogin-login-logout-support
mthiesc Aug 5, 2024
9c9e036
Remove getRotatingIdSpan class methods
mthiesc Aug 19, 2024
9dd0a50
Merge branch 'master' into accountlogin-login-logout-support
mthiesc Aug 19, 2024
ac49ea3
Restyled by clang-format
restyled-commits Aug 19, 2024
3b70d26
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Aug 21, 2024
9632993
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Aug 22, 2024
f187308
Merge branch 'master' into accountlogin-login-logout-support
lazarkov Aug 22, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,16 @@ private CommandResponseHolder() {
Clusters.AccountLogin.Id,
Clusters.AccountLogin.Commands.GetSetupPIN.ID,
"{\"0\":\"20202021\"}");
setResponseValue(
Clusters.AccountLogin.Id,
Clusters.AccountLogin.Commands.Login.ID,
// 0 is for success, you can return 1 for failure
"{\"Status\":0}");
setResponseValue(
Clusters.AccountLogin.Id,
Clusters.AccountLogin.Commands.Logout.ID,
// 0 is for success, you can return 1 for failure
"{\"Status\":0}");
};

public static CommandResponseHolder getInstance() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.provider.Settings;
import android.util.Log;
import com.example.contentapp.AttributeHolder;
import com.example.contentapp.CommandResponseHolder;
import com.example.contentapp.MainActivity;
import com.example.contentapp.matter.MatterAgentClient;
import com.matter.tv.app.api.Clusters;
import com.matter.tv.app.api.MatterIntentConstants;

public class MatterCommandReceiver extends BroadcastReceiver {
Expand Down Expand Up @@ -44,6 +46,21 @@ public void onReceive(Context context, Intent intent) {
.append(command)
.toString();
Log.d(TAG, message);

int pinCode =
Settings.Secure.getInt(context.getContentResolver(), "matter_pin_code", 20202021);
Log.d(TAG, "Retrieved pin code:" + pinCode);

CommandResponseHolder.getInstance()
.setResponseValue(
Clusters.AccountLogin.Id,
Clusters.AccountLogin.Commands.GetSetupPIN.ID,
"{\""
+ Clusters.AccountLogin.Commands.GetSetupPINResponse.Fields.SetupPIN
+ "\":\""
+ pinCode
+ "\"}");

String response =
CommandResponseHolder.getInstance().getCommandResponse(clusterId, commandId);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,38 +24,105 @@
#include <lib/core/DataModelTypes.h>

using namespace std;
using namespace chip::app::Clusters;
using namespace chip::app::Clusters::AccountLogin;
using Status = chip::Protocols::InteractionModel::Status;

namespace {

const auto loginTempAccountIdentifierFieldId =
to_string(chip::to_underlying(AccountLogin::Commands::Login::Fields::kTempAccountIdentifier));
const auto loginSetupPINFieldId = to_string(chip::to_underlying(AccountLogin::Commands::Login::Fields::kSetupPIN));
const auto loginNodeFieldId = to_string(chip::to_underlying(AccountLogin::Commands::Login::Fields::kNode));
const auto logoutNodeFieldId = to_string(chip::to_underlying(AccountLogin::Commands::Logout::Fields::kNode));

string charSpanToString(const CharSpan & charSpan)
{
return { charSpan.data(), charSpan.size() };
}

std::string serializeLoginCommand(AccountLogin::Commands::Login::Type cmd)
{
return R"({")" + loginTempAccountIdentifierFieldId + R"(":")" + charSpanToString(cmd.tempAccountIdentifier) + R"(",)" + R"(")" +
loginSetupPINFieldId + R"(":")" + charSpanToString(cmd.setupPIN) + R"(",)" + R"(")" + loginNodeFieldId + R"(":")" +
to_string(cmd.node.Value()) + R"("})";
}

std::string serializeLogoutCommand(AccountLogin::Commands::Logout::Type cmd)
{
return R"({")" + logoutNodeFieldId + R"(":")" + to_string(cmd.node.Value()) + R"("})";
}

} // namespace

AccountLoginManager::AccountLoginManager(ContentAppCommandDelegate * commandDelegate, const char * setupPin) :
mCommandDelegate(commandDelegate)
{
CopyString(mSetupPin, sizeof(mSetupPin), setupPin);
}

bool AccountLoginManager::HandleLogin(const CharSpan & tempAccountIdentifier, const CharSpan & setupPin,
bool AccountLoginManager::HandleLogin(const CharSpan & tempAccountIdentifier, const CharSpan & setupPIN,
const chip::Optional<chip::NodeId> & nodeId)
{
ChipLogProgress(DeviceLayer, "AccountLoginManager::HandleLogin called for endpoint %d", mEndpointId);
string tempAccountIdentifierString(tempAccountIdentifier.data(), tempAccountIdentifier.size());
string setupPinString(setupPin.data(), setupPin.size());

if (strcmp(mSetupPin, setupPinString.c_str()) == 0)
if (mCommandDelegate == nullptr)
{
ChipLogProgress(Zcl, "AccountLoginManager::HandleLogin success");
return true;
ChipLogError(Zcl, "CommandDelegate not found");
return false;
}
else

if (tempAccountIdentifier.empty() || setupPIN.empty() || !nodeId.HasValue())
{
ChipLogProgress(Zcl, "AccountLoginManager::HandleLogin failed expected pin %s", mSetupPin);
ChipLogError(Zcl, "Invalid parameters");
return false;
}

Json::Value response;
bool commandHandled = true;
AccountLogin::Commands::Login::Type cmd = { tempAccountIdentifier, setupPIN, nodeId };

auto status = mCommandDelegate->InvokeCommand(mEndpointId, AccountLogin::Id, AccountLogin::Commands::Login::Id,
serializeLoginCommand(cmd), commandHandled, response);
if (status == Status::Success)
{
// Format status response to verify that response is non-failure.
status = mCommandDelegate->FormatStatusResponse(response);
}
ChipLogProgress(Zcl, "AccountLoginManager::HandleLogin command returned with status: %d", chip::to_underlying(status));
return status == chip::Protocols::InteractionModel::Status::Success;
}

bool AccountLoginManager::HandleLogout(const chip::Optional<chip::NodeId> & nodeId)
{
// TODO: Insert your code here to send logout request
return true;
ChipLogProgress(DeviceLayer, "AccountLoginManager::HandleLogout called for endpoint %d", mEndpointId);

if (mCommandDelegate == nullptr)
{
ChipLogError(Zcl, "CommandDelegate not found");
return false;
}

if (!nodeId.HasValue())
{
ChipLogError(Zcl, "Invalid parameters");
return false;
}

Json::Value response;
bool commandHandled = true;
AccountLogin::Commands::Logout::Type cmd = { nodeId };

auto status = mCommandDelegate->InvokeCommand(mEndpointId, AccountLogin::Id, AccountLogin::Commands::Logout::Id,
serializeLogoutCommand(cmd), commandHandled, response);

if (status == Status::Success)
{
// Format status response to verify that response is non-failure.
status = mCommandDelegate->FormatStatusResponse(response);
}
ChipLogProgress(Zcl, "AccountLoginManager::HandleLogout command returned with status: %d", chip::to_underlying(status));
return status == chip::Protocols::InteractionModel::Status::Success;
}

void AccountLoginManager::HandleGetSetupPin(CommandResponseHelper<GetSetupPINResponse> & helper,
Expand Down
2 changes: 1 addition & 1 deletion examples/tv-app/android/java/AppImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,7 @@ void refreshConnectedClientsAcl(uint16_t vendorId, uint16_t productId, ContentAp

for (const auto & allowedVendor : app->GetApplicationBasicDelegate()->GetAllowedVendorList())
{
std::set<NodeId> tempNodeIds = ContentAppPlatform::GetInstance().GetNodeIdsForAllowVendorId(allowedVendor);
std::set<NodeId> tempNodeIds = ContentAppPlatform::GetInstance().GetNodeIdsForAllowedVendorId(allowedVendor);

nodeIds.insert(tempNodeIds.begin(), tempNodeIds.end());
}
Expand Down
66 changes: 44 additions & 22 deletions examples/tv-app/android/java/ContentAppCommandDelegate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,9 @@
namespace chip {
namespace AppPlatform {

using CommandHandlerInterface = chip::app::CommandHandlerInterface;
using LaunchResponseType = chip::app::Clusters::ContentLauncher::Commands::LauncherResponse::Type;
using PlaybackResponseType = chip::app::Clusters::MediaPlayback::Commands::PlaybackResponse::Type;
using NavigateTargetResponseType = chip::app::Clusters::TargetNavigator::Commands::NavigateTargetResponse::Type;
using GetSetupPINResponseType = chip::app::Clusters::AccountLogin::Commands::GetSetupPINResponse::Type;
using Status = chip::Protocols::InteractionModel::Status;

const std::string FAILURE_KEY = "PlatformError";
const std::string FAILURE_STATUS_KEY = "Status";
const std::string FAILURE_KEY = "PlatformError";
const std::string FAILURE_STATUS_KEY = "Status";
const std::string RESPONSE_STATUS_KEY = "Status";

bool isValidJson(const char * response)
{
Expand Down Expand Up @@ -166,6 +160,7 @@ Status ContentAppCommandDelegate::InvokeCommand(EndpointId epId, ClusterId clust
ChipLogError(Zcl, "Java exception in ContentAppCommandDelegate::sendCommand");
env->ExceptionDescribe();
env->ExceptionClear();
return chip::Protocols::InteractionModel::Status::Failure;
}
else
{
Expand Down Expand Up @@ -198,7 +193,8 @@ Status ContentAppCommandDelegate::InvokeCommand(EndpointId epId, ClusterId clust
}
env->DeleteLocalRef(resp);

// handle errors from platform-app
// Parse response here in case there is failure response.
// Return non-success error code to indicate to caller it should not parse response.
if (!value[FAILURE_KEY].empty())
{
value = value[FAILURE_KEY];
Expand All @@ -209,7 +205,9 @@ Status ContentAppCommandDelegate::InvokeCommand(EndpointId epId, ClusterId clust
return chip::Protocols::InteractionModel::Status::Failure;
}

return chip::Protocols::InteractionModel::Status::UnsupportedEndpoint;
// Return success to indicate command has been sent, response returned and parsed successfully.
// Caller has to manually parse value input/output parameter to get response status/object.
return chip::Protocols::InteractionModel::Status::Success;
}
else
{
Expand Down Expand Up @@ -282,20 +280,31 @@ void ContentAppCommandDelegate::FormatResponseData(CommandHandlerInterface::Hand
}

case app::Clusters::AccountLogin::Id: {
if (app::Clusters::AccountLogin::Commands::GetSetupPIN::Id != handlerContext.mRequestPath.mCommandId)
switch (handlerContext.mRequestPath.mCommandId)
{
// No response for other commands in this cluster
case app::Clusters::AccountLogin::Commands::GetSetupPIN::Id: {
Status status;
GetSetupPINResponseType getSetupPINresponse = FormatGetSetupPINResponse(value, status);
if (status != chip::Protocols::InteractionModel::Status::Success)
{
handlerContext.mCommandHandler.AddStatus(handlerContext.mRequestPath, status);
}
else
{
handlerContext.mCommandHandler.AddResponse(handlerContext.mRequestPath, getSetupPINresponse);
}
break;
}
Status status;
GetSetupPINResponseType getSetupPINresponse = FormatGetSetupPINResponse(value, status);
if (status != chip::Protocols::InteractionModel::Status::Success)
{
handlerContext.mCommandHandler.AddStatus(handlerContext.mRequestPath, status);
case app::Clusters::AccountLogin::Commands::Login::Id: {
handlerContext.mCommandHandler.AddStatus(handlerContext.mRequestPath, FormatStatusResponse(value));
break;
}
else
{
handlerContext.mCommandHandler.AddResponse(handlerContext.mRequestPath, getSetupPINresponse);
case app::Clusters::AccountLogin::Commands::Logout::Id: {
handlerContext.mCommandHandler.AddStatus(handlerContext.mRequestPath, FormatStatusResponse(value));
break;
}
default:
break;
}
break;
}
Expand Down Expand Up @@ -388,10 +397,23 @@ GetSetupPINResponseType ContentAppCommandDelegate::FormatGetSetupPINResponse(Jso
}
else
{
getSetupPINresponse.setupPIN = "";
status = chip::Protocols::InteractionModel::Status::Failure;
}
return getSetupPINresponse;
}

Status ContentAppCommandDelegate::FormatStatusResponse(Json::Value value)
{
// check if JSON has "Status" key
if (!value[RESPONSE_STATUS_KEY].empty() && !value[RESPONSE_STATUS_KEY].isUInt())
{
return static_cast<Protocols::InteractionModel::Status>(value.asUInt());
}
else
{
return chip::Protocols::InteractionModel::Status::Failure;
}
}

} // namespace AppPlatform
} // namespace chip
2 changes: 2 additions & 0 deletions examples/tv-app/android/java/ContentAppCommandDelegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include <json/json.h>
#include <lib/core/DataModelTypes.h>
#include <lib/support/JniReferences.h>
#include <protocols/interaction_model/StatusCode.h>

#include <string>

Expand Down Expand Up @@ -75,6 +76,7 @@ class ContentAppCommandDelegate : public CommandHandlerInterface
LaunchResponseType FormatContentLauncherResponse(Json::Value value, Status & status);
NavigateTargetResponseType FormatNavigateTargetResponse(Json::Value value, Status & status);
PlaybackResponseType FormatMediaPlaybackResponse(Json::Value value, Status & status);
Status FormatStatusResponse(Json::Value value);

private:
void InitializeJNIObjects(jobject manager)
Expand Down
35 changes: 23 additions & 12 deletions examples/tv-app/android/java/TVApp-JNI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -258,15 +258,15 @@ SampleTvAppInstallationService gSampleTvAppInstallationService;

class MyPostCommissioningListener : public PostCommissioningListener
{
void CommissioningCompleted(uint16_t vendorId, uint16_t productId, NodeId nodeId, Messaging::ExchangeManager & exchangeMgr,
const SessionHandle & sessionHandle) override
void CommissioningCompleted(uint16_t vendorId, uint16_t productId, NodeId nodeId, CharSpan rotatingId, uint32_t passcode,
Messaging::ExchangeManager & exchangeMgr, const SessionHandle & sessionHandle) override
{
// read current binding list
chip::Controller::ClusterBase cluster(exchangeMgr, sessionHandle, kTargetBindingClusterEndpointId);

ContentAppPlatform::GetInstance().StoreNodeIdForContentApp(vendorId, productId, nodeId);

cacheContext(vendorId, productId, nodeId, exchangeMgr, sessionHandle);
cacheContext(vendorId, productId, nodeId, rotatingId, passcode, exchangeMgr, sessionHandle);

CHIP_ERROR err =
cluster.ReadAttribute<Binding::Attributes::Binding::TypeInfo>(this, OnReadSuccessResponse, OnReadFailureResponse);
Expand Down Expand Up @@ -350,17 +350,23 @@ class MyPostCommissioningListener : public PostCommissioningListener

Optional<SessionHandle> opt = mSecureSession.Get();
SessionHandle & sessionHandle = opt.Value();
auto rotatingIdSpan = CharSpan{ mRotatingId.data(), mRotatingId.size() };
ContentAppPlatform::GetInstance().ManageClientAccess(*mExchangeMgr, sessionHandle, mVendorId, mProductId, localNodeId,
bindings, OnSuccessResponse, OnFailureResponse);
rotatingIdSpan, mPasscode, bindings, OnSuccessResponse,
OnFailureResponse);
clearContext();
}

void cacheContext(uint16_t vendorId, uint16_t productId, NodeId nodeId, Messaging::ExchangeManager & exchangeMgr,
const SessionHandle & sessionHandle)
void cacheContext(uint16_t vendorId, uint16_t productId, NodeId nodeId, CharSpan rotatingId, uint32_t passcode,
Messaging::ExchangeManager & exchangeMgr, const SessionHandle & sessionHandle)
{
mVendorId = vendorId;
mProductId = productId;
mNodeId = nodeId;
mVendorId = vendorId;
mProductId = productId;
mNodeId = nodeId;
mRotatingId = std::string{
rotatingId.data(), rotatingId.size()
}; // Allocates and copies to string instead of storing span to make sure lifetime is valid.
mPasscode = passcode;
mExchangeMgr = &exchangeMgr;
mSecureSession.ShiftToSession(sessionHandle);
}
Expand All @@ -370,12 +376,17 @@ class MyPostCommissioningListener : public PostCommissioningListener
mVendorId = 0;
mProductId = 0;
mNodeId = 0;
mRotatingId = {};
mPasscode = 0;
mExchangeMgr = nullptr;
mSecureSession.SessionReleased();
}
uint16_t mVendorId = 0;
uint16_t mProductId = 0;
NodeId mNodeId = 0;

uint16_t mVendorId = 0;
uint16_t mProductId = 0;
NodeId mNodeId = 0;
std::string mRotatingId;
uint32_t mPasscode = 0;
Messaging::ExchangeManager * mExchangeMgr = nullptr;
SessionHolder mSecureSession;
};
Expand Down
Loading
Loading