Skip to content

Commit

Permalink
[wakelock] Refactor and simplify the implementation (flutter-tizen#583)
Browse files Browse the repository at this point in the history
  • Loading branch information
swift-kim authored Jun 7, 2023
1 parent 4110b10 commit 37a7540
Show file tree
Hide file tree
Showing 7 changed files with 89 additions and 184 deletions.
5 changes: 4 additions & 1 deletion packages/wakelock/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
## NEXT
## 1.0.2

* Switch to a MethodChannel-based implementation.
* Update wakelock to 0.6.2.
* Remove pedantic dependency and replace with flutter_lints.
* Increase the minimum Flutter version to 3.3.

## 1.0.1
Expand Down
8 changes: 6 additions & 2 deletions packages/wakelock/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ This package is not an _endorsed_ implementation of `wakelock`. Therefore, you h

```yaml
dependencies:
wakelock: ^0.5.6
wakelock_tizen: ^1.0.1
wakelock: ^0.6.2
wakelock_tizen: ^1.0.2
```
Then you can import `wakelock` in your Dart code:
Expand All @@ -31,3 +31,7 @@ To use the wakelock plugin in a Tizen application, the display privilege must be
<privilege>http://tizen.org/privilege/display</privilege>
</privileges>
```

## Supported devices

- Galaxy Watch series (running Tizen 4.0 or later)
4 changes: 1 addition & 3 deletions packages/wakelock/analysis_options.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
# This file was copied from wakelock/analysis_options.yaml.

include: package:pedantic/analysis_options.yaml
include: package:flutter_lints/flutter.yaml

linter:
rules:
Expand Down
3 changes: 1 addition & 2 deletions packages/wakelock/example/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ environment:
dependencies:
flutter:
sdk: flutter
wakelock: ^0.5.6
wakelock: ^0.6.2
wakelock_tizen:
path: ../

Expand All @@ -22,4 +22,3 @@ dev_dependencies:
sdk: flutter
integration_test_tizen:
path: ../../integration_test/
pedantic: ^1.11.0
25 changes: 25 additions & 0 deletions packages/wakelock/lib/wakelock_tizen.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Copyright 2023 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.

import 'package:flutter/services.dart';
import 'package:wakelock_platform_interface/wakelock_platform_interface.dart';

const MethodChannel _channel = MethodChannel('tizen/wakelock_plugin');

/// A Tizen implementation of [WakelockPlatformInterface].
class WakelockTizen extends WakelockPlatformInterface {
/// Registers this class as the default platform implementation.
static void register() {
WakelockPlatformInterface.instance = WakelockTizen();
}

@override
Future<void> toggle({required bool enable}) async {
await _channel.invokeMethod<void>('toggle', enable);
}

@override
Future<bool> get enabled async =>
await _channel.invokeMethod<bool>('isEnabled') ?? false;
}
5 changes: 3 additions & 2 deletions packages/wakelock/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: wakelock_tizen
description: Tizen implementation of the wakelock plugin.
homepage: https://github.com/flutter-tizen/plugins
repository: https://github.com/flutter-tizen/plugins/tree/master/packages/wakelock
version: 1.0.1
version: 1.0.2

environment:
sdk: ">=2.18.0 <4.0.0"
Expand All @@ -14,11 +14,12 @@ flutter:
tizen:
pluginClass: WakelockTizenPlugin
fileName: wakelock_tizen_plugin.h
dartPluginClass: WakelockTizen

dependencies:
flutter:
sdk: flutter
wakelock_platform_interface: ^0.3.0

dev_dependencies:
pedantic: ^1.11.0
flutter_lints: ^1.0.4
223 changes: 49 additions & 174 deletions packages/wakelock/tizen/src/wakelock_tizen_plugin.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,201 +5,76 @@
#include "wakelock_tizen_plugin.h"

#include <device/power.h>
#include <flutter/basic_message_channel.h>
#include <flutter/method_channel.h>
#include <flutter/plugin_registrar.h>
#include <flutter/standard_message_codec.h>
#include <flutter/standard_method_codec.h>

#include <typeinfo>
#include <memory>
#include <string>
#include <variant>

#include "log.h"

class IsEnabledMessage {
public:
flutter::EncodableValue encode() const {
flutter::EncodableMap wrapped = {
{flutter::EncodableValue("enabled"), flutter::EncodableValue(enabled)}};
return flutter::EncodableValue(wrapped);
}

static flutter::EncodableValue decode(flutter::EncodableValue value) {
auto &map = std::get<flutter::EncodableMap>(value);
IsEnabledMessage message;
message.enabled = std::get<bool>(map[flutter::EncodableValue("enabled")]);
return flutter::CustomEncodableValue(message);
}

bool enabled;
};

class ToggleMessage {
public:
flutter::EncodableValue encode() const {
flutter::EncodableMap wrapped = {
{flutter::EncodableValue("enable"), flutter::EncodableValue(enable)}};
return flutter::EncodableValue(wrapped);
}

static flutter::EncodableValue decode(flutter::EncodableValue value) {
auto &map = std::get<flutter::EncodableMap>(value);
ToggleMessage message;
message.enable = std::get<bool>(map[flutter::EncodableValue("enable")]);
return flutter::CustomEncodableValue(message);
}

bool enable;
};

class WakelockApiCodec : public flutter::StandardCodecSerializer {
public:
static const WakelockApiCodec &GetInstance() {
static WakelockApiCodec sInstance;
return sInstance;
}

// Prevent copying.
WakelockApiCodec(WakelockApiCodec const &) = delete;
WakelockApiCodec &operator=(WakelockApiCodec const &) = delete;

void WriteValue(const flutter::EncodableValue &value,
flutter::ByteStreamWriter *stream) const override {
if (std::holds_alternative<flutter::CustomEncodableValue>(value)) {
const auto &custom_type = std::get<flutter::CustomEncodableValue>(value);
if (custom_type.type() == typeid(IsEnabledMessage)) {
const IsEnabledMessage &my_type_value =
std::any_cast<IsEnabledMessage>(custom_type);
stream->WriteByte(static_cast<uint8_t>(128));
StandardCodecSerializer::WriteValue(my_type_value.encode(), stream);
} else if (custom_type.type() == typeid(ToggleMessage)) {
const ToggleMessage &my_type_value =
std::any_cast<ToggleMessage>(custom_type);
stream->WriteByte(static_cast<uint8_t>(129));
StandardCodecSerializer::WriteValue(my_type_value.encode(), stream);
}
} else {
StandardCodecSerializer::WriteValue(value, stream);
}
}

protected:
WakelockApiCodec() = default;

flutter::EncodableValue ReadValueOfType(
uint8_t type, flutter::ByteStreamReader *stream) const override {
switch (type) {
case 128:
return IsEnabledMessage::decode(ReadValue(stream));
break;
case 129:
return ToggleMessage::decode(ReadValue(stream));
default:
return StandardCodecSerializer::ReadValueOfType(type, stream);
}
}
};
namespace {

class WakelockTizenPlugin : public flutter::Plugin {
public:
static void RegisterWithRegistrar(flutter::PluginRegistrar *registrar) {
auto enabled_channel =
std::make_unique<flutter::BasicMessageChannel<flutter::EncodableValue>>(
registrar->messenger(), "dev.flutter.pigeon.WakelockApi.isEnabled",
&flutter::StandardMessageCodec::GetInstance(
&WakelockApiCodec::GetInstance()));
auto toggle_channel =
std::make_unique<flutter::BasicMessageChannel<flutter::EncodableValue>>(
registrar->messenger(), "dev.flutter.pigeon.WakelockApi.toggle",
&flutter::StandardMessageCodec::GetInstance(
&WakelockApiCodec::GetInstance()));
auto channel =
std::make_unique<flutter::MethodChannel<flutter::EncodableValue>>(
registrar->messenger(), "tizen/wakelock_plugin",
&flutter::StandardMethodCodec::GetInstance());

auto plugin = std::make_unique<WakelockTizenPlugin>();
enabled_channel->SetMessageHandler(
[plugin_pointer = plugin.get()](const auto &message, auto &reply) {
LOG_DEBUG("Fetching wakelock status: %s",
plugin_pointer->wakelocked_ ? "enabled" : "disabled");

IsEnabledMessage is_enabled_message;
is_enabled_message.enabled = plugin_pointer->wakelocked_;
flutter::EncodableMap wrapped = {
{flutter::EncodableValue("result"),
flutter::CustomEncodableValue(is_enabled_message)}};
reply(flutter::EncodableValue(wrapped));
});

toggle_channel->SetMessageHandler(
[plugin_pointer = plugin.get()](const auto &message, auto &reply) {
bool enable;
bool argument_parsed = false;
if (std::holds_alternative<flutter::EncodableList>(message)) {
const flutter::EncodableList &elist =
std::get<flutter::EncodableList>(message);
if (!elist.empty()) {
const flutter::EncodableValue &args = elist[0];
if (std::holds_alternative<flutter::CustomEncodableValue>(args)) {
const auto &custom_type =
std::get<flutter::CustomEncodableValue>(args);
if (custom_type.type() == typeid(ToggleMessage)) {
const ToggleMessage &toggle_message =
std::any_cast<ToggleMessage>(custom_type);
enable = toggle_message.enable;
argument_parsed = true;
}
}
}
}

if (!argument_parsed) {
reply(WrapError("Invalid arguments for toggle.", ""));
return;
}

flutter::EncodableMap result_map = {
{flutter::EncodableValue("result"), flutter::EncodableValue()}};
flutter::EncodableValue wrapped = flutter::EncodableValue(result_map);
LOG_DEBUG("Toggling wakelock status to %s",
enable ? "enable" : "disable");
if (enable != plugin_pointer->wakelocked_) {
const int kTimeoutPermanent = 0;
int ret = enable ? device_power_request_lock(POWER_LOCK_DISPLAY,
kTimeoutPermanent)
: device_power_release_lock(POWER_LOCK_DISPLAY);
if (ret == DEVICE_ERROR_NONE) {
plugin_pointer->wakelocked_ = enable;
} else {
std::string details =
ret == DEVICE_ERROR_PERMISSION_DENIED
? "You need to declare "
"\"http://tizen.org/privilege/display\" "
"privilege in your tizen manifest to toggle wakelock."
: "";
wrapped = WrapError(get_error_message(ret), details);
}
}
reply(wrapped);
channel->SetMethodCallHandler(
[plugin_pointer = plugin.get()](const auto &call, auto result) {
plugin_pointer->HandleMethodCall(call, std::move(result));
});

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

WakelockTizenPlugin() : wakelocked_(false) {}
WakelockTizenPlugin() {}

virtual ~WakelockTizenPlugin() = default;

private:
bool wakelocked_;

static flutter::EncodableValue WrapError(const std::string &message,
const std::string &details) {
flutter::EncodableMap error_map = {
{flutter::EncodableValue("code"), flutter::EncodableValue("1")},
{flutter::EncodableValue("message"), flutter::EncodableValue(message)},
{flutter::EncodableValue("details"), flutter::EncodableValue(details)},
};
flutter::EncodableMap wrapped = {
{flutter::EncodableValue("error"), flutter::EncodableValue(error_map)},
};
return flutter::EncodableValue(wrapped);
void HandleMethodCall(
const flutter::MethodCall<flutter::EncodableValue> &method_call,
std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result) {
const auto &method_name = method_call.method_name();

if (method_name == "toggle") {
const auto &arguments = *method_call.arguments();
if (std::holds_alternative<bool>(arguments)) {
bool enable = std::get<bool>(arguments);
int ret = DEVICE_ERROR_NONE;
if (enable) {
ret = device_power_request_lock(POWER_LOCK_DISPLAY, 0);
} else {
ret = device_power_release_lock(POWER_LOCK_DISPLAY);
}
if (ret == DEVICE_ERROR_NONE) {
enabled_ = enable;
result->Success();
} else {
result->Error(std::to_string(ret), get_error_message(ret));
}
} else {
result->Error("Invalid argument",
"The argument must be a boolean value.");
}
} else if (method_name == "isEnabled") {
result->Success(flutter::EncodableValue(enabled_));
} else {
result->NotImplemented();
}
}

bool enabled_ = false;
};

} // namespace

void WakelockTizenPluginRegisterWithRegistrar(
FlutterDesktopPluginRegistrarRef registrar) {
WakelockTizenPlugin::RegisterWithRegistrar(
Expand Down

0 comments on commit 37a7540

Please sign in to comment.