blob: 088d00582b8cfaad322e8c0d1e3a44dc99a85834 [file]
//
// Copyright 2020 Comcast Cable Communications Management, LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// SPDX-License-Identifier: Apache-2.0
#include "third_party/starboard/rdk/shared/libcobalt.h"
#include <cstring>
#include "starboard/common/condition_variable.h"
#include "starboard/common/mutex.h"
#include "starboard/common/semaphore.h"
#include "starboard/once.h"
#include "starboard/memory.h"
#include "starboard/string.h"
#include "third_party/starboard/rdk/shared/rdkservices.h"
#include "third_party/starboard/rdk/shared/application_rdk.h"
using namespace third_party::starboard::rdk::shared;
namespace
{
struct APIContext
{
APIContext()
: mutex_()
, condition_(mutex_)
{ }
void OnInitialize()
{
starboard::ScopedLock lock(mutex_);
running_ = (nullptr != Application::Get());
condition_.Broadcast();
}
void OnTeardown()
{
starboard::ScopedLock lock(mutex_);
running_ = false;
}
void SendLink(const char* link)
{
starboard::ScopedLock lock(mutex_);
WaitForApp(lock);
Application::Get()->Link(link);
}
void RequestFreeze() {
starboard::ScopedLock lock(mutex_);
WaitForApp(lock);
starboard::Semaphore sem;
Application::Get()->Freeze(
&sem,
[](void* ctx) {
reinterpret_cast<starboard::Semaphore*>(ctx)->Put();
});
sem.Take();
}
void RequestFocus() {
starboard::ScopedLock lock(mutex_);
WaitForApp(lock);
starboard::Semaphore sem;
Application::Get()->Focus(
&sem,
[](void* ctx) {
reinterpret_cast<starboard::Semaphore*>(ctx)->Put();
});
sem.Take();
}
void RequestBlur() {
starboard::ScopedLock lock(mutex_);
WaitForApp(lock);
starboard::Semaphore sem;
Application::Get()->Blur(
&sem,
[](void* ctx) {
reinterpret_cast<starboard::Semaphore*>(ctx)->Put();
});
sem.Take();
}
void RequestQuit()
{
starboard::ScopedLock lock(mutex_);
stop_request_cb_ = nullptr;
stop_request_cb_data_ = nullptr;
if (running_)
Application::Get()->Stop(0);
}
void SetStopRequestHandler(SbRdkCallbackFunc cb, void* user_data)
{
starboard::ScopedLock lock(mutex_);
stop_request_cb_ = cb;
stop_request_cb_data_ = user_data;
}
void RequestStop()
{
SbRdkCallbackFunc cb;
void* user_data;
int should_invoke_default = 1;
mutex_.Acquire();
cb = stop_request_cb_;
user_data = stop_request_cb_data_;
mutex_.Release();
if (cb) {
should_invoke_default = cb(user_data);
}
if (should_invoke_default) {
RequestQuit();
}
}
void SetConcealRequestHandler(SbRdkCallbackFunc cb, void* user_data)
{
starboard::ScopedLock lock(mutex_);
conceal_request_cb_ = cb;
conceal_request_cb_data_ = user_data;
}
void RequestConceal()
{
SbRdkCallbackFunc cb;
void* user_data;
int should_invoke_default = 1;
mutex_.Acquire();
cb = conceal_request_cb_;
user_data = conceal_request_cb_data_;
mutex_.Release();
if (cb) {
should_invoke_default = cb(user_data);
}
if (should_invoke_default) {
Application::Get()->Conceal(NULL, NULL);
}
}
void SetCobaltExitStrategy(const char* strategy)
{
if (running_) {
SB_LOG(WARNING) << "Ignore exit strategy change, app is already running.";
return;
}
// Supported values(src/cobalt/extension/configuration.h): stop, suspend, noexit.
if (strncmp(strategy, "suspend", 7) == 0)
exit_strategy_ = "suspend";
else if (strncmp(strategy, "noexit", 6) == 0)
exit_strategy_ = "noexit";
else
exit_strategy_ = "stop";
}
const char* GetCobaltExitStrategy()
{
return exit_strategy_.c_str();
}
private:
void WaitForApp(starboard::ScopedLock &)
{
while ( running_ == false )
condition_.Wait();
}
bool running_ { false };
starboard::Mutex mutex_;
starboard::ConditionVariable condition_;
SbRdkCallbackFunc stop_request_cb_ { nullptr };
void* stop_request_cb_data_ { nullptr };
SbRdkCallbackFunc conceal_request_cb_ { nullptr };
void* conceal_request_cb_data_ { nullptr };
std::string exit_strategy_ { "stop" };
};
SB_ONCE_INITIALIZE_FUNCTION(APIContext, GetContext);
} // namespace
namespace third_party {
namespace starboard {
namespace rdk {
namespace shared {
namespace libcobalt_api {
void Initialize()
{
GetContext()->OnInitialize();
}
void Teardown()
{
GetContext()->OnTeardown();
}
} // namespace libcobalt_api
} // namespace shared
} // namespace rdk
} // namespace starboard
} // namespace third_party
extern "C" {
void SbRdkHandleDeepLink(const char* link) {
GetContext()->SendLink(link);
}
void SbRdkSuspend() {
GetContext()->RequestFreeze();
}
void SbRdkResume() {
GetContext()->RequestFocus();
}
void SbRdkPause() {
GetContext()->RequestBlur();
}
void SbRdkUnpause() {
GetContext()->RequestFocus();
}
void SbRdkQuit() {
GetContext()->RequestQuit();
}
void SbRdkSetSetting(const char* key, const char* json) {
if (!key || key[0] == '\0' || !json)
return;
if (strcmp(key, "accessibility") == 0) {
Accessibility::SetSettings(json);
}
else if (strcmp(key, "systemproperties") == 0) {
SystemProperties::SetSettings(json);
}
else if (strcmp(key, "advertisingid") == 0) {
AdvertisingId::SetSettings(json);
}
}
int SbRdkGetSetting(const char* key, char** out_json) {
if (!key || key[0] == '\0' || !out_json || *out_json != nullptr)
return -1;
bool result = false;
std::string tmp;
if (strcmp(key, "accessibility") == 0) {
result = Accessibility::GetSettings(tmp);
}
else if (strcmp(key, "systemproperties") == 0) {
result = SystemProperties::GetSettings(tmp);
}
else if (strcmp(key, "advertisingid") == 0) {
result = AdvertisingId::GetSettings(tmp);
}
if (result && !tmp.empty()) {
char *out = (char*)malloc(tmp.size() + 1);
memcpy(out, tmp.c_str(), tmp.size());
out[tmp.size()] = '\0';
*out_json = out;
return 0;
}
return -1;
}
void SbRdkSetStopRequestHandler(SbRdkCallbackFunc cb, void* user_data) {
GetContext()->SetStopRequestHandler(cb, user_data);
}
void SbRdkRequestStop() {
GetContext()->RequestStop();
}
void SbRdkSetConcealRequestHandler(SbRdkCallbackFunc cb, void* user_data) {
GetContext()->SetConcealRequestHandler(cb, user_data);
}
void SbRdkRequestConceal() {
GetContext()->RequestConceal();
}
void SbRdkSetCobaltExitStrategy(const char* strategy) {
GetContext()->SetCobaltExitStrategy(strategy);
}
const char* SbRdkGetCobaltExitStrategy() {
return GetContext()->GetCobaltExitStrategy();
}
} // extern "C"