Skip to content

[connectivity_plus] Refactor the C++ code #352

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

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
74 changes: 74 additions & 0 deletions packages/connectivity_plus/tizen/src/connection.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// Copyright 2022 Samsung Electronics Co., Ltd. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "connection.h"

#include "log.h"

static ConnectionType ToConnectionType(connection_type_e type) {
switch (type) {
case CONNECTION_TYPE_WIFI:
return ConnectionType::kWiFi;
case CONNECTION_TYPE_CELLULAR:
return ConnectionType::kMobile;
case CONNECTION_TYPE_ETHERNET:
return ConnectionType::kEthernet;
case CONNECTION_TYPE_DISCONNECTED:
default:
return ConnectionType::kNone;
}
}

Connection::Connection() {
int ret = connection_create(&connection_);
if (ret != CONNECTION_ERROR_NONE) {
LOG_ERROR("Failed to create handle: %s", get_error_message(ret));
last_error_ = ret;
}
}

Connection::~Connection() {
if (connection_) {
connection_unset_type_changed_cb(connection_);
connection_destroy(connection_);
connection_ = nullptr;
}
}

bool Connection::StartListen(ConnectionTypeCallback callback) {
int ret = connection_set_type_changed_cb(
connection_,
[](connection_type_e type, void *user_data) -> void {
auto *self = static_cast<Connection *>(user_data);
self->callback_(ToConnectionType(type));
},
this);
if (ret != CONNECTION_ERROR_NONE) {
LOG_ERROR("Failed to add callback: %s", get_error_message(ret));
last_error_ = ret;
return false;
}

callback_ = callback;
return true;
}

void Connection::StopListen() {
int ret = connection_unset_type_changed_cb(connection_);
if (ret != CONNECTION_ERROR_NONE) {
LOG_ERROR("Failed to remove callback: %s", get_error_message(ret));
last_error_ = ret;
}
}

ConnectionType Connection::GetType() {
connection_type_e type;
int ret = connection_get_type(connection_, &type);
if (ret != CONNECTION_ERROR_NONE) {
LOG_ERROR("Failed to get connection type: %s", get_error_message(ret));
last_error_ = ret;
return ConnectionType::kError;
}
return ToConnectionType(type);
}
39 changes: 39 additions & 0 deletions packages/connectivity_plus/tizen/src/connection.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright 2022 Samsung Electronics Co., Ltd. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef FLUTTER_PLUGIN_CONNECTION_H_
#define FLUTTER_PLUGIN_CONNECTION_H_

#include <net_connection.h>
#include <tizen.h>

#include <functional>
#include <string>

enum class ConnectionType { kNone, kEthernet, kWiFi, kMobile, kError };

typedef std::function<void(ConnectionType)> ConnectionTypeCallback;

class Connection {
public:
Connection();
~Connection();

int GetLastError() { return last_error_; }

std::string GetLastErrorString() { return get_error_message(last_error_); }

bool StartListen(ConnectionTypeCallback callback);

void StopListen();

ConnectionType GetType();

private:
int last_error_ = TIZEN_ERROR_NONE;
ConnectionTypeCallback callback_ = nullptr;
connection_h connection_;
};

#endif // FLUTTER_PLUGIN_CONNECTION_H_
224 changes: 95 additions & 129 deletions packages/connectivity_plus/tizen/src/connectivity_plus_tizen_plugin.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,162 +6,128 @@

#include <flutter/event_channel.h>
#include <flutter/event_sink.h>
#include <flutter/event_stream_handler_functions.h>
#include <flutter/event_stream_handler.h>
#include <flutter/method_channel.h>
#include <flutter/plugin_registrar.h>
#include <flutter/standard_method_codec.h>
#include <net_connection.h>
#include <wifi-manager.h>

#include <memory>
#include <string>

#include "log.h"

class ConnectivityPlusTizenPlugin : public flutter::Plugin {
public:
static void RegisterWithRegistrar(flutter::PluginRegistrar *registrar) {
auto plugin = std::make_unique<ConnectivityPlusTizenPlugin>();
plugin->SetupChannels(registrar);
registrar->AddPlugin(std::move(plugin));
}

ConnectivityPlusTizenPlugin() : connection_(nullptr), events_(nullptr) {
EnsureConnectionHandle();
#include "connection.h"

namespace {

typedef flutter::EventChannel<flutter::EncodableValue> FlEventChannel;
typedef flutter::EventSink<flutter::EncodableValue> FlEventSink;
typedef flutter::MethodCall<flutter::EncodableValue> FlMethodCall;
typedef flutter::MethodResult<flutter::EncodableValue> FlMethodResult;
typedef flutter::MethodChannel<flutter::EncodableValue> FlMethodChannel;
typedef flutter::StreamHandler<flutter::EncodableValue> FlStreamHandler;
typedef flutter::StreamHandlerError<flutter::EncodableValue>
FlStreamHandlerError;

std::string ConnectionTypeToString(ConnectionType type) {
switch (type) {
case ConnectionType::kEthernet:
return "ethernet";
case ConnectionType::kWiFi:
return "wifi";
case ConnectionType::kMobile:
return "mobile";
case ConnectionType::kNone:
default:
return "none";
}
}

virtual ~ConnectivityPlusTizenPlugin() {
if (connection_ != nullptr) {
connection_destroy(connection_);
connection_ = nullptr;
}
}
class ConnectivityStreamHandler : public FlStreamHandler {
protected:
std::unique_ptr<FlStreamHandlerError> OnListenInternal(
const flutter::EncodableValue *arguments,
std::unique_ptr<FlEventSink> &&events) override {
events_ = std::move(events);

void RegisterObserver(
std::unique_ptr<flutter::EventSink<flutter::EncodableValue>> &&events) {
EnsureConnectionHandle();
if (connection_set_type_changed_cb(
connection_,
[](connection_type_e state, void *data) -> void {
auto *self = static_cast<ConnectivityPlusTizenPlugin *>(data);
self->SendConnectivityChangedEvent(state);
},
this) != CONNECTION_ERROR_NONE) {
return;
ConnectionTypeCallback callback = [this](ConnectionType type) -> void {
if (type != ConnectionType::kError) {
events_->Success(flutter::EncodableValue(ConnectionTypeToString(type)));
} else {
events_->Error(std::to_string(connection_.GetLastError()),
connection_.GetLastErrorString());
}
};
if (!connection_.StartListen(callback)) {
return std::make_unique<FlStreamHandlerError>(
std::to_string(connection_.GetLastError()),
connection_.GetLastErrorString(), nullptr);
}
events_ = std::move(events);
}

void ClearObserver() {
if (connection_ == nullptr || events_ == nullptr) return;
// Send an initial event once the stream has been set up.
callback(connection_.GetType());

connection_unset_type_changed_cb(connection_);
events_ = nullptr;
return nullptr;
}

void SendConnectivityChangedEvent(connection_type_e state) {
if (events_ == nullptr) {
return;
}
std::string replay = ConvertConnectionTypeToString(state);
flutter::EncodableValue msg(replay);
events_->Success(msg);
std::unique_ptr<FlStreamHandlerError> OnCancelInternal(
const flutter::EncodableValue *arguments) override {
connection_.StopListen();
events_.reset();
return nullptr;
}

private:
void EnsureConnectionHandle() {
if (connection_ == nullptr) {
if (connection_create(&connection_) != CONNECTION_ERROR_NONE) {
connection_ = nullptr;
}
}
}
Connection connection_;
std::unique_ptr<FlEventSink> events_;
};

std::string ConvertConnectionTypeToString(connection_type_e net_state) {
std::string result;
switch (net_state) {
case CONNECTION_TYPE_WIFI:
result = "wifi";
break;
case CONNECTION_TYPE_ETHERNET:
result = "ethernet";
break;
case CONNECTION_TYPE_CELLULAR:
result = "mobile";
break;
case CONNECTION_TYPE_DISCONNECTED:
default:
result = "none";
}
return result;
class ConnectivityPlusTizenPlugin : public flutter::Plugin {
public:
static void RegisterWithRegistrar(flutter::PluginRegistrar *registrar) {
auto plugin = std::make_unique<ConnectivityPlusTizenPlugin>();

auto method_channel = std::make_unique<FlMethodChannel>(
registrar->messenger(), "dev.fluttercommunity.plus/connectivity",
&flutter::StandardMethodCodec::GetInstance());
method_channel->SetMethodCallHandler(
[plugin_pointer = plugin.get()](const auto &call, auto result) {
plugin_pointer->HandleMethodCall(call, std::move(result));
});

auto event_channel = std::make_unique<FlEventChannel>(
registrar->messenger(), "dev.fluttercommunity.plus/connectivity_status",
&flutter::StandardMethodCodec::GetInstance());
event_channel->SetStreamHandler(
std::make_unique<ConnectivityStreamHandler>());

registrar->AddPlugin(std::move(plugin));
}

void HandleMethodCall(
const flutter::MethodCall<flutter::EncodableValue> &method_call,
std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result) {
EnsureConnectionHandle();
LOG_INFO("method : %s", method_call.method_name().data());

std::string replay = "";
if (method_call.method_name().compare("check") == 0) {
connection_type_e net_state;
if (connection_get_type(connection_, &net_state) !=
CONNECTION_ERROR_NONE) {
result->Error("-1", "Couldn't know current connection type");
return;
ConnectivityPlusTizenPlugin() {}

virtual ~ConnectivityPlusTizenPlugin() {}

private:
void HandleMethodCall(const FlMethodCall &method_call,
std::unique_ptr<FlMethodResult> result) {
const auto &method_name = method_call.method_name();

if (method_name == "check") {
Connection connection;
ConnectionType type = connection.GetType();
if (type != ConnectionType::kError) {
result->Success(flutter::EncodableValue(ConnectionTypeToString(type)));
} else {
result->Error(std::to_string(connection.GetLastError()),
connection.GetLastErrorString());
}
replay = ConvertConnectionTypeToString(net_state);
} else {
result->Error("-1", "Not supported method");
return;
result->NotImplemented();
}
if (replay.length() == 0) {
result->Error("-1", "Not valid result");
return;
}

flutter::EncodableValue msg(replay);
result->Success(msg);
}

void SetupChannels(flutter::PluginRegistrar *registrar) {
auto method_channel =
std::make_unique<flutter::MethodChannel<flutter::EncodableValue>>(
registrar->messenger(), "dev.fluttercommunity.plus/connectivity",
&flutter::StandardMethodCodec::GetInstance());
event_channel_ =
std::make_unique<flutter::EventChannel<flutter::EncodableValue>>(
registrar->messenger(),
"dev.fluttercommunity.plus/connectivity_status",
&flutter::StandardMethodCodec::GetInstance());
method_channel->SetMethodCallHandler([this](const auto &call, auto result) {
HandleMethodCall(call, std::move(result));
});

auto event_channel_handler =
std::make_unique<flutter::StreamHandlerFunctions<>>(
[this](const flutter::EncodableValue *arguments,
std::unique_ptr<flutter::EventSink<>> &&events)
-> std::unique_ptr<flutter::StreamHandlerError<>> {
LOG_INFO("OnListen");
RegisterObserver(std::move(events));
return nullptr;
},
[this](const flutter::EncodableValue *arguments)
-> std::unique_ptr<flutter::StreamHandlerError<>> {
LOG_INFO("OnCancel");
ClearObserver();
return nullptr;
});
event_channel_->SetStreamHandler(std::move(event_channel_handler));
}

std::unique_ptr<flutter::EventChannel<flutter::EncodableValue>>
event_channel_;
connection_h connection_;
std::unique_ptr<flutter::EventSink<flutter::EncodableValue>> events_;
};

} // namespace

void ConnectivityPlusTizenPluginRegisterWithRegistrar(
FlutterDesktopPluginRegistrarRef registrar) {
ConnectivityPlusTizenPlugin::RegisterWithRegistrar(
Expand Down