Skip to content

Commit

Permalink
Implement message queue for native license request
Browse files Browse the repository at this point in the history
1.Create a new thread for native license request.
2.Spearate channel and native code from drm manager.
  • Loading branch information
xiaowei-guan committed Dec 27, 2023
1 parent 0d363f0 commit 393dc17
Show file tree
Hide file tree
Showing 12 changed files with 401 additions and 123 deletions.
4 changes: 2 additions & 2 deletions packages/video_player_videohole/tizen/project_def.prop
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ type = staticLib
profile = common-5.5

# Source files
USER_SRCS += src/*.cc
USER_SRCS += src/*.cc src/drm/*.cc

# User defines
USER_DEFS =
Expand All @@ -15,6 +15,6 @@ USER_CPP_DEFS = FLUTTER_PLUGIN_IMPL
USER_CPP_UNDEFS =

# User includes
USER_INC_DIRS = inc src
USER_INC_DIRS = inc src src/drm
USER_INC_FILES =
USER_CPP_INC_FILES =
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// 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.

#ifndef FLUTTER_PLUGIN_DRM_LICENSE_REQUEST_H_
#define FLUTTER_PLUGIN_DRM_LICENSE_REQUEST_H_

#include <functional>
#include <string>

using OnLicenseRequestDone = std::function<void(
const std::string& session_id, std::vector<uint8_t>& response_data)>;
class DrmLicenseRequest
: public std::enable_shared_from_this<DrmLicenseRequest> {
public:
DrmLicenseRequest(OnLicenseRequestDone on_license_request_done_callback)
: on_license_request_done_callback_(on_license_request_done_callback) {}
virtual ~DrmLicenseRequest(){};
virtual void RequestLicense(void* session_id, int message_type, void* message,
int message_length) = 0;
virtual void OnLicenseResponse(const std::string& session_id,
std::vector<uint8_t>& response_data) = 0;

protected:
std::shared_ptr<DrmLicenseRequest> getShared() { return shared_from_this(); }
OnLicenseRequestDone on_license_request_done_callback_ = nullptr;
};
#endif // FLUTTER_PLUGIN_DRM_LICENSE_REQUEST_H_
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// 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.

#include "drm_license_request_channel.h"

#include <flutter/method_result_functions.h>
#include <flutter/standard_method_codec.h>

#include "log.h"

DrmLicenseRequestChannel::DrmLicenseRequestChannel(
flutter::BinaryMessenger *binary_messenger,
OnLicenseRequestDone on_license_request_done_callback)
: DrmLicenseRequest(on_license_request_done_callback),
request_license_channel_(
std::make_unique<flutter::MethodChannel<flutter::EncodableValue>>(
binary_messenger, "dev.flutter.videoplayer.drm",
&flutter::StandardMethodCodec::GetInstance())) {
license_request_pipe_ = ecore_pipe_add(
[](void *data, void *buffer, unsigned int nbyte) -> void {
auto *self = static_cast<DrmLicenseRequestChannel *>(data);
self->ExecuteRequest();
},
this);
}

void DrmLicenseRequestChannel::RequestLicense(void *session_id,
int message_type, void *message,
int message_length) {
DataForLicenseProcess process_message(session_id, message, message_length);
PushLicenseRequestData(process_message);
}

void DrmLicenseRequestChannel::ExecuteRequest() {
std::lock_guard<std::mutex> lock(queue_mutex_);
while (!license_request_queue_.empty()) {
DataForLicenseProcess data = license_request_queue_.front();
RequestLicense(data.session_id, data.message);
license_request_queue_.pop();
}
}

void DrmLicenseRequestChannel::PushLicenseRequestData(
DataForLicenseProcess &data) {
std::lock_guard<std::mutex> lock(queue_mutex_);
license_request_queue_.push(data);
ecore_pipe_write(license_request_pipe_, nullptr, 0);
}

void DrmLicenseRequestChannel::RequestLicense(std::string &session_id,
std::string &message) {
LOG_INFO("[DrmLicenseRequestChannel] Start request license.");

if (request_license_channel_ == nullptr) {
LOG_ERROR("[DrmLicenseRequestChannel] request license channel is null.");
return;
}

std::vector<uint8_t> message_vec(message.begin(), message.end());
flutter::EncodableMap args_map = {
{flutter::EncodableValue("message"),
flutter::EncodableValue(message_vec)},
};
auto result_handler =
std::make_unique<flutter::MethodResultFunctions<flutter::EncodableValue>>(

[session_id, this](const flutter::EncodableValue *success_value) {
std::vector<uint8_t> response;
if (std::holds_alternative<std::vector<uint8_t>>(*success_value)) {
response = std::get<std::vector<uint8_t>>(*success_value);
} else {
LOG_ERROR("[DrmLicenseRequestChannel] Fail to get response.");
return;
}
LOG_INFO("[DrmLicenseRequestChannel] Response length : %d",
response.size());
OnLicenseResponse(session_id, response);
},
nullptr, nullptr);
request_license_channel_->InvokeMethod(
"requestLicense",
std::make_unique<flutter::EncodableValue>(
flutter::EncodableValue(args_map)),
std::move(result_handler));
}

void DrmLicenseRequestChannel::OnLicenseResponse(
const std::string &session_id, std::vector<uint8_t> &response_data) {
if (on_license_request_done_callback_) {
on_license_request_done_callback_(session_id, response_data);
}
}

DrmLicenseRequestChannel::~DrmLicenseRequestChannel() {
if (license_request_pipe_) {
ecore_pipe_del(license_request_pipe_);
license_request_pipe_ = nullptr;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// 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.

#ifndef FLUTTER_PLUGIN_DRM_LICENSE_REQUEST_CHANNEL_H_
#define FLUTTER_PLUGIN_DRM_LICENSE_REQUEST_CHANNEL_H_

#include <Ecore.h>
#include <flutter/method_channel.h>

#include <memory>
#include <mutex>
#include <queue>

#include "drm_license_request.h"

struct DataForLicenseProcess {
DataForLicenseProcess(void *session_id, void *message, int message_length)
: session_id(static_cast<char *>(session_id)),
message(static_cast<char *>(message), message_length) {}
std::string session_id;
std::string message;
};

class DrmLicenseRequestChannel : public DrmLicenseRequest {
public:
explicit DrmLicenseRequestChannel(
flutter::BinaryMessenger *binary_messenger,
OnLicenseRequestDone on_license_request_done_callback);
void RequestLicense(void *session_id, int message_type, void *message,
int message_length) override;
~DrmLicenseRequestChannel();
void OnLicenseResponse(const std::string& session_id,
std::vector<uint8_t>& response_data) override;

private:
void ExecuteRequest();
void PushLicenseRequestData(DataForLicenseProcess &data);
void RequestLicense(std::string &session_id, std::string &message);
std::unique_ptr<flutter::MethodChannel<flutter::EncodableValue>>
request_license_channel_;
std::mutex queue_mutex_;
Ecore_Pipe *license_request_pipe_ = nullptr;
std::queue<DataForLicenseProcess> license_request_queue_;
};
#endif
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
// 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.

#include "drm_license_request_native.h"

#include <string>
#include <vector>

#include "drm_license_helper.h"
#include "log.h"

constexpr int kMessageQuit = -1;
constexpr int kMessageRequestLicense = 0;

struct Message {
Eina_Thread_Queue_Msg head;
int event;
std::string license_server_url;
std::string challenge;
std::string session_id;
int drm_type;
};

DrmLicenseRequestNative::DrmLicenseRequestNative(
int drm_type, const std::string& license_server_url,
OnLicenseRequestDone on_license_request_done_callback)
: DrmLicenseRequest(on_license_request_done_callback),
drm_type_(drm_type),
license_server_url_(license_server_url) {
license_request_thread_ = ecore_thread_feedback_run(RunLoop, nullptr, nullptr,
nullptr, this, EINA_TRUE);
license_response_pipe_ = ecore_pipe_add(
[](void* data, void* buffer, unsigned int nbyte) -> void {
auto* self = static_cast<DrmLicenseRequestNative*>(data);
self->ExecuteResponse();
},
this);
}

void DrmLicenseRequestNative::RequestLicense(void* session_id, int message_type,
void* message,
int message_length) {
if (!license_request_thread_ || ecore_thread_check(license_request_thread_)) {
LOG_ERROR("Invalid license request thread.");
return;
}

if (!license_request_queue_) {
LOG_ERROR("Invalid license request thread queue.");
return;
}

void* ref;
Message* request_message = static_cast<Message*>(
eina_thread_queue_send(license_request_queue_, sizeof(Message), &ref));
request_message->event = kMessageRequestLicense;
request_message->drm_type = drm_type_;
request_message->challenge =
std::string(static_cast<char*>(message), message_length);
request_message->license_server_url = license_server_url_;
request_message->session_id = std::string(static_cast<char*>(session_id));
eina_thread_queue_send_done(license_request_queue_, ref);
}

void DrmLicenseRequestNative::StopMessageQueue() {
if (!license_request_thread_ || ecore_thread_check(license_request_thread_)) {
LOG_ERROR("Invalid license request thread.");
return;
}

if (!license_request_queue_) {
LOG_ERROR("Invalid license request thread queue.");
return;
}

void* ref;
Message* message = static_cast<Message*>(
eina_thread_queue_send(license_request_queue_, sizeof(Message), &ref));
message->event = kMessageQuit;
eina_thread_queue_send_done(license_request_queue_, ref);
}

void DrmLicenseRequestNative::RunLoop(void* data, Ecore_Thread* thread) {
Eina_Thread_Queue* license_request_queue = eina_thread_queue_new();
if (!license_request_queue) {
LOG_ERROR("Invalid license request thread queue.");
ecore_thread_cancel(thread);
return;
}
auto* self = static_cast<DrmLicenseRequestNative*>(data);
self->license_request_queue_ = license_request_queue;
std::weak_ptr<DrmLicenseRequest> weak_self = self->getShared();
while (!ecore_thread_check(thread)) {
void* ref;
Message* message = static_cast<Message*>(
eina_thread_queue_wait(license_request_queue, &ref));
if (message->event == kMessageQuit) {
eina_thread_queue_wait_done(license_request_queue, ref);
break;
}
std::string license_server_url = message->license_server_url;
std::string challenge = message->challenge;
std::string session_id = message->session_id;
int drm_type = message->drm_type;
eina_thread_queue_wait_done(license_request_queue, ref);
// Get license via the license server.
unsigned char* response_data = nullptr;
unsigned long response_len = 0;
std::vector<uint8_t> response;
DRM_RESULT ret = DrmLicenseHelper::DoTransactionTZ(
license_server_url.c_str(), challenge.c_str(), challenge.size(),
&response_data, &response_len,
static_cast<DrmLicenseHelper::DrmType>(drm_type), nullptr, nullptr);
if (DRM_SUCCESS != ret || nullptr == response_data || 0 == response_len) {
LOG_ERROR("Fail to get respone by license server url.");
continue;
}
LOG_INFO("Response length : %lu", response_len);
if (weak_self.expired()) {
free(response_data);
break;
}
auto response_vec =
std::vector<uint8_t>(response_data, response_data + response_len);
weak_self.lock()->OnLicenseResponse(session_id, response_vec);
free(response_data);
}
if (license_request_queue) {
eina_thread_queue_free(license_request_queue);
}
}

void DrmLicenseRequestNative::ExecuteResponse() {
std::lock_guard<std::mutex> lock(queue_mutex_);
while (!license_response_queue_.empty()) {
if (on_license_request_done_callback_) {
auto response_data = license_response_queue_.front();
on_license_request_done_callback_(response_data.first,
response_data.second);
}
license_response_queue_.pop();
}
}

void DrmLicenseRequestNative::OnLicenseResponse(
const std::string& session_id, std::vector<uint8_t>& response_data) {
std::lock_guard<std::mutex> lock(queue_mutex_);
license_response_queue_.push(std::make_pair(session_id, response_data));
ecore_pipe_write(license_response_pipe_, nullptr, 0);
}

DrmLicenseRequestNative::~DrmLicenseRequestNative() {
StopMessageQueue();
if (license_request_thread_) {
ecore_thread_cancel(license_request_thread_);
license_request_thread_ = nullptr;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// 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.
#ifndef FLUTTER_PLUGIN_DRM_LICENSE_REQUEST_NATIVE_H_
#define FLUTTER_PLUGIN_DRM_LICENSE_REQUEST_NATIVE_H_

#include <Ecore.h>

#include <memory>
#include <mutex>
#include <queue>
#include <utility>


#include "drm_license_request.h"

class DrmLicenseRequestNative : public DrmLicenseRequest {
public:
explicit DrmLicenseRequestNative(
int drm_type, const std::string& license_server_url,
OnLicenseRequestDone on_license_request_done_callback);
virtual ~DrmLicenseRequestNative();
void RequestLicense(void* session_id, int message_type, void* message,
int message_length) override;
protected:
void OnLicenseResponse(const std::string& session_id, std::vector<uint8_t>& response_data) override;
private:
void StopMessageQueue();
void ExecuteResponse();
static void RunLoop(void* data, Ecore_Thread* thread);
Ecore_Thread* license_request_thread_ = nullptr;
Eina_Thread_Queue* license_request_queue_ = nullptr;
int drm_type_;
std::string license_server_url_;
std::mutex queue_mutex_;
Ecore_Pipe *license_response_pipe_ = nullptr;
std::queue<std::pair<std::string, std::vector<uint8_t>>> license_response_queue_;
};

#endif
Loading

0 comments on commit 393dc17

Please sign in to comment.