mirror of
https://gitee.com/openharmony/request_request
synced 2024-10-06 21:43:36 +00:00
code refactory and qos logic
Signed-off-by: fqwert <yanglv2@huawei.com> Change-Id: I9127a828a3239b38d51ea31ab19020e8cafd6a51
This commit is contained in:
parent
5fcb23e203
commit
818959303c
15
.gitignore
vendored
Normal file
15
.gitignore
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
# Copyright (C) 2023 Huawei Device Co., Ltd.
|
||||
# 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.
|
||||
|
||||
target
|
||||
Cargo.lock
|
@ -14,5 +14,5 @@
|
||||
# any change to frameworks/native/include/download_server_ipc_interface_code.h needs to be reviewed by @leonchan5
|
||||
frameworks/native/include/download_server_ipc_interface_code.h @leonchan5
|
||||
|
||||
# any change to services/service/rust/src/download_server_ipc_interface_code.rs needs to be reviewed by @leonchan5
|
||||
services/service/rust/src/download_server_ipc_interface_code.rs @leonchan5
|
||||
# any change to services/service/request/src/service/interface.rs needs to be reviewed by @leonchan5
|
||||
services/service/request/src/service/interface.rs @leonchan5
|
||||
|
19
Cargo.toml
Normal file
19
Cargo.toml
Normal file
@ -0,0 +1,19 @@
|
||||
# Copyright (C) 2023 Huawei Device Co., Ltd.
|
||||
# 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.
|
||||
|
||||
[workspace]
|
||||
resolver = "2"
|
||||
members = [
|
||||
"services/service/request",
|
||||
"services/service/download_server",
|
||||
]
|
@ -67,7 +67,7 @@
|
||||
"service_group": [
|
||||
"//base/request/request/services/etc/init:downloadservice.cfg",
|
||||
"//base/request/request/services/sa_profile:download_sa_profiles",
|
||||
"//base/request/request/services/service/rust:download_server"
|
||||
"//base/request/request/services/service/download_server:download_server"
|
||||
]
|
||||
},
|
||||
"inner_kits": [],
|
||||
|
@ -101,6 +101,7 @@ struct Config {
|
||||
uint32_t index = 0;
|
||||
int64_t begins = 0;
|
||||
int64_t ends = -1;
|
||||
uint32_t priority = 0;
|
||||
bool overwrite = false;
|
||||
bool metered = false;
|
||||
bool roaming = false;
|
||||
@ -209,6 +210,7 @@ struct TaskInfo {
|
||||
Reason code;
|
||||
std::string reason;
|
||||
bool withSystem = false;
|
||||
uint32_t priority;
|
||||
std::map<std::string, std::string> extras;
|
||||
std::vector<TaskState> taskStates;
|
||||
};
|
||||
|
@ -36,7 +36,6 @@ public:
|
||||
|
||||
private:
|
||||
void OnCallBack(MessageParcel &data);
|
||||
static void OnDone(MessageParcel &data);
|
||||
bool IsHeaderReceive(const std::string &type, const NotifyData ¬ifyData);
|
||||
static void GetDownloadNotify(const std::string &type, const NotifyData ¬ifyData, Notify ¬ify);
|
||||
static void GetUploadNotify(const std::string &type, const NotifyData ¬ifyData, Notify ¬ify);
|
||||
|
@ -48,10 +48,6 @@ public:
|
||||
static napi_value Stop(napi_env env, napi_callback_info info);
|
||||
static std::map<Reason, DownloadErrorCode> failMap_;
|
||||
|
||||
static void AddCache(const std::string &taskId, const std::shared_ptr<TaskInfo> &info);
|
||||
static bool GetCache(const std::string &taskId, std::shared_ptr<TaskInfo> &info);
|
||||
static void RemoveCache(const std::string &taskId);
|
||||
|
||||
private:
|
||||
struct JsParam {
|
||||
std::string type;
|
||||
@ -93,10 +89,6 @@ private:
|
||||
static NotifyData BuildNotifyData(const std::shared_ptr<TaskInfo> &taskInfo);
|
||||
static bool IsSupportType(const std::string &type, Version version);
|
||||
static void ConvertType(std::string &type);
|
||||
static bool NeedNotify(const std::string &type, std::shared_ptr<TaskInfo> &taskInfo);
|
||||
|
||||
static std::mutex taskCacheMutex_;
|
||||
static std::map<std::string, std::shared_ptr<TaskInfo>> taskCache_;
|
||||
};
|
||||
} // namespace OHOS::Request
|
||||
|
||||
|
@ -76,7 +76,6 @@ JsTask::~JsTask()
|
||||
{
|
||||
REQUEST_HILOGD("~JsTask()");
|
||||
ClearListener();
|
||||
RequestEvent::RemoveCache(tid_);
|
||||
}
|
||||
napi_value JsTask::JsUpload(napi_env env, napi_callback_info info)
|
||||
{
|
||||
|
@ -370,6 +370,7 @@ napi_value Convert2JSValue(napi_env env, TaskInfo &taskInfo)
|
||||
napi_set_named_property(env, value, "mimeType", Convert2JSValue(env, taskInfo.mimeType));
|
||||
napi_set_named_property(env, value, "progress", Convert2JSValue(env, taskInfo.progress));
|
||||
napi_set_named_property(env, value, "gauge", Convert2JSValue(env, taskInfo.gauge));
|
||||
napi_set_named_property(env, value, "priority", Convert2JSValue(env, taskInfo.priority));
|
||||
napi_set_named_property(env, value, "ctime", Convert2JSValue(env, taskInfo.ctime));
|
||||
napi_set_named_property(env, value, "mtime", Convert2JSValue(env, taskInfo.mtime));
|
||||
napi_set_named_property(env, value, "retry", Convert2JSValue(env, taskInfo.retry));
|
||||
|
@ -33,7 +33,6 @@ int32_t NotifyStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageP
|
||||
OnCallBack(data);
|
||||
break;
|
||||
case static_cast<uint32_t>(RequestNotifyInterfaceCode::REQUEST_DONE_NOTIFY):
|
||||
OnDone(data);
|
||||
break;
|
||||
default:
|
||||
REQUEST_HILOGE("Default value received, check needed.");
|
||||
@ -78,7 +77,8 @@ void NotifyStub::OnCallBack(MessageParcel &data)
|
||||
notifyData.taskStates.push_back(taskState);
|
||||
}
|
||||
RequestCallBack(type, tid, notifyData);
|
||||
if (notifyData.version == Version::API10 && (type == "complete" || type == "fail")) {
|
||||
|
||||
if (type == "complete" || type == "fail") {
|
||||
JsTask::ClearTaskContext(tid);
|
||||
}
|
||||
}
|
||||
@ -187,19 +187,4 @@ void NotifyStub::GetUploadNotify(const std::string &type, const NotifyData ¬i
|
||||
notify.progress.extras = notifyData.progress.extras;
|
||||
}
|
||||
}
|
||||
|
||||
void NotifyStub::OnDone(MessageParcel &data)
|
||||
{
|
||||
auto taskInfo = std::make_shared<TaskInfo>();
|
||||
ParcelHelper::UnMarshal(data, *taskInfo);
|
||||
REQUEST_HILOGI("task %{public}s done", taskInfo->tid.c_str());
|
||||
std::lock_guard<std::mutex> lockGuard(JsTask::taskMutex_);
|
||||
auto item = JsTask::taskMap_.find(taskInfo->tid);
|
||||
if (item == JsTask::taskMap_.end()) {
|
||||
REQUEST_HILOGW("Task ID not found");
|
||||
return;
|
||||
}
|
||||
RequestEvent::AddCache(taskInfo->tid, taskInfo);
|
||||
JsTask::ClearTaskContext(taskInfo->tid);
|
||||
}
|
||||
} // namespace OHOS::Request
|
||||
|
@ -89,8 +89,6 @@ std::map<Reason, DownloadErrorCode> RequestEvent::failMap_ = {
|
||||
{UNSUPPORT_RANGE_REQUEST, ERROR_UNKNOWN},
|
||||
};
|
||||
|
||||
std::mutex RequestEvent::taskCacheMutex_;
|
||||
std::map<std::string, std::shared_ptr<TaskInfo>> RequestEvent::taskCache_;
|
||||
napi_value RequestEvent::Pause(napi_env env, napi_callback_info info)
|
||||
{
|
||||
REQUEST_HILOGD("Pause in");
|
||||
@ -151,38 +149,12 @@ napi_value RequestEvent::On(napi_env env, napi_callback_info info)
|
||||
REQUEST_HILOGD("On event %{public}s + %{public}s", jsParam.type.c_str(), jsParam.task->GetTid().c_str());
|
||||
std::string key = jsParam.type + jsParam.task->GetTid();
|
||||
jsParam.task->AddListener(key, listener);
|
||||
std::shared_ptr<TaskInfo> taskInfo;
|
||||
if (GetCache(jsParam.task->GetTid(), taskInfo) && taskInfo != nullptr) {
|
||||
if (!NeedNotify(jsParam.type, taskInfo)) {
|
||||
return nullptr;
|
||||
}
|
||||
listener->RequestCallBack(jsParam.type, jsParam.task->GetTid(), BuildNotifyData(taskInfo));
|
||||
return nullptr;
|
||||
}
|
||||
if (jsParam.task->GetListenerSize(key) == 1) {
|
||||
RequestManager::GetInstance()->On(jsParam.type, jsParam.task->GetTid(), listener);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool RequestEvent::NeedNotify(const std::string &type, std::shared_ptr<TaskInfo> &taskInfo)
|
||||
{
|
||||
if (type == EVENT_FAIL && taskInfo->progress.state != State::FAILED) {
|
||||
return false;
|
||||
}
|
||||
if (type == EVENT_COMPLETE && taskInfo->progress.state != State::COMPLETED) {
|
||||
return false;
|
||||
}
|
||||
if (!taskInfo->progress.sizes.empty()) {
|
||||
uint64_t processed = taskInfo->progress.processed;
|
||||
int64_t totalSize = taskInfo->progress.sizes[0];
|
||||
if (type == EVENT_PROGRESS && processed == 0 && totalSize == -1) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
napi_value RequestEvent::Off(napi_env env, napi_callback_info info)
|
||||
{
|
||||
JsParam jsParam;
|
||||
@ -353,16 +325,17 @@ int32_t RequestEvent::PauseExec(const std::shared_ptr<ExecContext> &context)
|
||||
|
||||
int32_t RequestEvent::QueryExec(const std::shared_ptr<ExecContext> &context)
|
||||
{
|
||||
std::shared_ptr<TaskInfo> infoRes;
|
||||
TaskInfo infoRes;
|
||||
int32_t ret = E_OK;
|
||||
if (!GetCache(context->task->GetTid(), infoRes) || infoRes == nullptr) {
|
||||
infoRes = std::make_shared<TaskInfo>();
|
||||
ret = RequestManager::GetInstance()->Show(context->task->GetTid(), *infoRes);
|
||||
if (!RequestManager::GetInstance()->LoadRequestServer()) {
|
||||
ret = E_SERVICE_ERROR;
|
||||
return ret;
|
||||
}
|
||||
ret = RequestManager::GetInstance()->Show(context->task->GetTid(), infoRes);
|
||||
if (context->version_ != Version::API10 && ret != E_PERMISSION) {
|
||||
ret = E_OK;
|
||||
}
|
||||
GetDownloadInfo(*infoRes, context->infoRes);
|
||||
GetDownloadInfo(infoRes, context->infoRes);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -370,8 +343,8 @@ int32_t RequestEvent::QueryMimeTypeExec(const std::shared_ptr<ExecContext> &cont
|
||||
{
|
||||
std::shared_ptr<TaskInfo> infoRes;
|
||||
int32_t ret = E_OK;
|
||||
if (GetCache(context->task->GetTid(), infoRes) || infoRes != nullptr) {
|
||||
context->strRes = infoRes->mimeType;
|
||||
if (!RequestManager::GetInstance()->LoadRequestServer()) {
|
||||
ret = E_SERVICE_ERROR;
|
||||
return ret;
|
||||
}
|
||||
ret = RequestManager::GetInstance()->QueryMimeType(context->task->GetTid(), context->strRes);
|
||||
@ -441,30 +414,4 @@ int32_t RequestEvent::ResumeExec(const std::shared_ptr<ExecContext> &context)
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void RequestEvent::AddCache(const std::string &taskId, const std::shared_ptr<TaskInfo> &info)
|
||||
{
|
||||
REQUEST_HILOGI("AddCache in, task id is %{public}s", taskId.c_str());
|
||||
std::lock_guard<std::mutex> lock(taskCacheMutex_);
|
||||
taskCache_[taskId] = info;
|
||||
}
|
||||
|
||||
bool RequestEvent::GetCache(const std::string &taskId, std::shared_ptr<TaskInfo> &info)
|
||||
{
|
||||
REQUEST_HILOGI("GetCache in, task id is %{public}s", taskId.c_str());
|
||||
std::lock_guard<std::mutex> lock(taskCacheMutex_);
|
||||
auto it = taskCache_.find(taskId);
|
||||
if (it != taskCache_.end()) {
|
||||
info = it->second;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void RequestEvent::RemoveCache(const std::string &taskId)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(taskCacheMutex_);
|
||||
REQUEST_HILOGI("RemoveCache in, task id is %{public}s", taskId.c_str());
|
||||
taskCache_.erase(taskId);
|
||||
}
|
||||
} // namespace OHOS::Request
|
||||
|
@ -59,6 +59,7 @@ void ParcelHelper::UnMarshalBase(MessageParcel &data, TaskInfo &info)
|
||||
info.mtime = data.ReadUint64();
|
||||
info.data = data.ReadString();
|
||||
info.description = data.ReadString();
|
||||
info.priority = data.ReadUint32();
|
||||
}
|
||||
|
||||
bool ParcelHelper::UnMarshalFormItem(MessageParcel &data, TaskInfo &info)
|
||||
|
@ -54,6 +54,7 @@ int32_t RequestServiceProxy::Create(const Config &config, int32_t &tid, sptr<Not
|
||||
data.WriteInt64(config.ends);
|
||||
data.WriteBool(config.gauge);
|
||||
data.WriteBool(config.precise);
|
||||
data.WriteUint32(config.priority);
|
||||
data.WriteString(config.url);
|
||||
data.WriteString(config.title);
|
||||
data.WriteString(config.method);
|
||||
@ -283,7 +284,13 @@ int32_t RequestServiceProxy::Remove(const std::string &tid, Version version)
|
||||
REQUEST_HILOGE("send request ret code is %{public}d", ret);
|
||||
return E_SERVICE_ERROR;
|
||||
}
|
||||
return reply.ReadInt32();
|
||||
|
||||
// API9 or lower will not return E_TASK_NOT_FOUND.
|
||||
int32_t result = reply.ReadInt32();
|
||||
if (version == Version::API9) {
|
||||
result = E_OK;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int32_t RequestServiceProxy::Resume(const std::string &tid)
|
||||
|
19
rustfmt.toml
Normal file
19
rustfmt.toml
Normal file
@ -0,0 +1,19 @@
|
||||
# Copyright (C) 2023 Huawei Device Co., Ltd.
|
||||
# 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.
|
||||
|
||||
edition = "2021"
|
||||
wrap_comments = true
|
||||
imports_granularity = "Module"
|
||||
group_imports = "StdExternalCrate"
|
||||
format_code_in_doc_comments = true
|
||||
normalize_comments = true
|
51
services/service/download_server/BUILD.gn
Normal file
51
services/service/download_server/BUILD.gn
Normal file
@ -0,0 +1,51 @@
|
||||
# Copyright (C) 2023 Huawei Device Co., Ltd.
|
||||
# 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.
|
||||
|
||||
import("//base/request/request/request_aafwk.gni")
|
||||
import("//build/ohos.gni")
|
||||
|
||||
config("download_service_config") {
|
||||
visibility = [ ":*" ]
|
||||
include_dirs = [ "include" ]
|
||||
|
||||
ldflags = [ "-Wl,--exclude-libs=ALL" ]
|
||||
cflags_cc = [ "-fno-exceptions" ]
|
||||
cflags = [
|
||||
"-fdata-sections",
|
||||
"-ffunction-sections",
|
||||
"-fvisibility=hidden",
|
||||
]
|
||||
}
|
||||
|
||||
ohos_rust_shared_library("download_server") {
|
||||
sources = [ "src/lib.rs" ]
|
||||
|
||||
public_configs = [ ":download_service_config" ]
|
||||
|
||||
deps = [ "../request:request" ]
|
||||
|
||||
external_deps = [
|
||||
"hilog:hilog_rust",
|
||||
"hisysevent:hisysevent_rust",
|
||||
"ipc:ipc_rust",
|
||||
"safwk:system_ability_fwk_rust",
|
||||
]
|
||||
|
||||
rustflags = [
|
||||
"-Copt-level=3",
|
||||
"-Cprefer-dynamic",
|
||||
]
|
||||
crate_name = "download_server"
|
||||
subsystem_name = "request"
|
||||
part_name = "request"
|
||||
}
|
25
services/service/download_server/Cargo.toml
Normal file
25
services/service/download_server/Cargo.toml
Normal file
@ -0,0 +1,25 @@
|
||||
# Copyright (C) 2023 Huawei Device Co., Ltd.
|
||||
# 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.
|
||||
|
||||
[package]
|
||||
name = "download_server"
|
||||
version = "1.0.0"
|
||||
edition = "2021"
|
||||
license = "Apache-2.0"
|
||||
|
||||
[dependencies]
|
||||
request = { path = "../request", features = ["oh"] }
|
||||
hilog_rust = { git = "https://gitee.com/openharmony/hiviewdfx_hilog.git" }
|
||||
ipc_rust = { git = "https://gitee.com/openharmony/communication_ipc" }
|
||||
hisysevent = { git = "https://gitee.com/openharmony/hiviewdfx_hisysevent.git" }
|
||||
system_ability_fwk_rust = { git = "https://gitee.com/openharmony/systemabilitymgr_safwk" }
|
@ -1,36 +1,31 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Huawei Device Co., Ltd.
|
||||
* 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.
|
||||
*/
|
||||
// Copyright (C) 2023 Huawei Device Co., Ltd.
|
||||
// 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.
|
||||
//! This create implement the request server register and publish
|
||||
#![allow(unused_variables)]
|
||||
extern crate ipc_rust;
|
||||
extern crate request;
|
||||
extern crate system_ability_fwk_rust;
|
||||
extern crate hisysevent;
|
||||
|
||||
use hilog_rust::*;
|
||||
use hisysevent::{EventType, write, build_number_param};
|
||||
#![warn(missing_docs, unused_crate_dependencies)]
|
||||
use std::ffi::{c_char, CString};
|
||||
|
||||
use hilog_rust::{error, hilog, info};
|
||||
use hisysevent::{build_number_param, write, EventType};
|
||||
use ipc_rust::{IRemoteBroker, RemoteObj};
|
||||
pub use request::{start, stop, RequestService, RequestServiceStub, LOG_LABEL};
|
||||
use std::ffi::{c_char, CString};
|
||||
use system_ability_fwk_rust::{define_system_ability, IMethod, ISystemAbility, RSystemAbility};
|
||||
|
||||
/// TEST_SERVICE_ID SAID
|
||||
pub const REQUEST_SERVICE_ID: i32 = 3706;
|
||||
|
||||
fn on_start<T: ISystemAbility + IMethod>(ability: &T) {
|
||||
debug!(LOG_LABEL, "on_start");
|
||||
info!(LOG_LABEL, "on_start");
|
||||
let service = match RequestServiceStub::new_remote_stub(RequestService) {
|
||||
Some(service) => service,
|
||||
None => {
|
||||
@ -49,11 +44,13 @@ fn on_start<T: ISystemAbility + IMethod>(ability: &T) {
|
||||
|
||||
ability.publish(&object, REQUEST_SERVICE_ID);
|
||||
start();
|
||||
info!(LOG_LABEL, "on_start succeed");
|
||||
}
|
||||
|
||||
fn on_stop<T: ISystemAbility + IMethod>(ability: &T) {
|
||||
debug!(LOG_LABEL, "on_stop");
|
||||
fn on_stop<T: ISystemAbility + IMethod>(_ability: &T) {
|
||||
info!(LOG_LABEL, "on_stop");
|
||||
stop();
|
||||
info!(LOG_LABEL, "on_stop succeed");
|
||||
}
|
||||
|
||||
fn service_start_fault() {
|
||||
@ -66,7 +63,7 @@ fn service_start_fault() {
|
||||
DOMAIN,
|
||||
SERVICE_START_FAULT,
|
||||
EventType::Fault,
|
||||
&[build_number_param!(ERROR_INFO, DOWNLOAD_PUBLISH_FAIL)]
|
||||
&[build_number_param!(ERROR_INFO, DOWNLOAD_PUBLISH_FAIL)],
|
||||
);
|
||||
}
|
||||
|
||||
@ -76,7 +73,7 @@ define_system_ability!(sa: SystemAbility(on_start, on_stop),);
|
||||
#[link_section = ".init_array"]
|
||||
static A: extern "C" fn() = {
|
||||
extern "C" fn init() {
|
||||
debug!(LOG_LABEL, "request service init");
|
||||
info!(LOG_LABEL, "request service init");
|
||||
let system_ability = SystemAbility::new_system_ability(REQUEST_SERVICE_ID, false)
|
||||
.expect("create service failed");
|
||||
system_ability.register();
|
@ -27,74 +27,26 @@ config("download_service_config") {
|
||||
]
|
||||
}
|
||||
|
||||
ohos_rust_shared_library("download_server") {
|
||||
sources = [ "src/request_service_init.rs" ]
|
||||
|
||||
public_configs = [ ":download_service_config" ]
|
||||
|
||||
deps = [ ":request" ]
|
||||
|
||||
external_deps = [
|
||||
"hilog:hilog_rust",
|
||||
"hisysevent:hisysevent_rust",
|
||||
"ipc:ipc_rust",
|
||||
"safwk:system_ability_fwk_rust",
|
||||
]
|
||||
|
||||
clippy_lints = "none"
|
||||
rustflags = [
|
||||
"-Copt-level=3",
|
||||
"-Cprefer-dynamic",
|
||||
]
|
||||
crate_name = "download_server"
|
||||
crate_type = "dylib"
|
||||
subsystem_name = "request"
|
||||
part_name = "request"
|
||||
}
|
||||
|
||||
ohos_rust_shared_library("request") {
|
||||
sources = [
|
||||
"src/c_string_wrapper.rs",
|
||||
"src/download_server_ipc_interface_code.rs",
|
||||
"src/enumration.rs",
|
||||
"src/filter.rs",
|
||||
"src/form_item.rs",
|
||||
"src/lib.rs",
|
||||
"src/log.rs",
|
||||
"src/progress.rs",
|
||||
"src/request_binding.rs",
|
||||
"src/request_service.rs",
|
||||
"src/request_service_ability.rs",
|
||||
"src/request_task.rs",
|
||||
"src/task_config.rs",
|
||||
"src/task_info.rs",
|
||||
"src/task_manager.rs",
|
||||
"src/utils.rs",
|
||||
]
|
||||
sources = [ "src/lib.rs" ]
|
||||
|
||||
public_configs = [ ":download_service_config" ]
|
||||
|
||||
deps = [ ":request_service_c" ]
|
||||
|
||||
features = [ "oh" ]
|
||||
|
||||
external_deps = [
|
||||
"hilog:hilog_rust",
|
||||
"hisysevent:hisysevent_rust",
|
||||
"hitrace:hitrace_meter_rust",
|
||||
"ipc:ipc_rust",
|
||||
"netstack:ylong_http_client",
|
||||
"safwk:system_ability_fwk_rust",
|
||||
"samgr:rust_samgr",
|
||||
"ylong_runtime:ylong_runtime",
|
||||
]
|
||||
|
||||
clippy_lints = "none"
|
||||
rustflags = [
|
||||
"-Copt-level=3",
|
||||
"-Cprefer-dynamic",
|
||||
"-Zmacro-backtrace",
|
||||
]
|
||||
crate_name = "request"
|
||||
crate_type = "dylib"
|
||||
subsystem_name = "request"
|
||||
part_name = "request"
|
||||
}
|
||||
@ -102,24 +54,24 @@ ohos_rust_shared_library("request") {
|
||||
ohos_shared_library("request_service_c") {
|
||||
include_dirs = [
|
||||
"${request_path}/common/include",
|
||||
"${request_path}/services/service/rust/src/c_wrapper/include",
|
||||
"${request_path}/services/service/request/c_wrapper/include",
|
||||
"${core_service_path}/innerkits/include",
|
||||
"${cellular_data_path}/innerkits/include",
|
||||
"${notification_path}/interfaces/inner_api",
|
||||
]
|
||||
sources = [
|
||||
"${request_path}/services/service/rust/src/c_wrapper/source/application_state_observer.cpp",
|
||||
"${request_path}/services/service/rust/src/c_wrapper/source/background_notification.cpp",
|
||||
"${request_path}/services/service/rust/src/c_wrapper/source/c_check_permission.cpp",
|
||||
"${request_path}/services/service/rust/src/c_wrapper/source/c_event_handler.cpp",
|
||||
"${request_path}/services/service/rust/src/c_wrapper/source/c_request_database.cpp",
|
||||
"${request_path}/services/service/rust/src/c_wrapper/source/c_string_wrapper.cpp",
|
||||
"${request_path}/services/service/rust/src/c_wrapper/source/c_task_config.cpp",
|
||||
"${request_path}/services/service/rust/src/c_wrapper/source/c_task_info.cpp",
|
||||
"${request_path}/services/service/rust/src/c_wrapper/source/common_event_notify.cpp",
|
||||
"${request_path}/services/service/rust/src/c_wrapper/source/get_calling_bundle.cpp",
|
||||
"${request_path}/services/service/rust/src/c_wrapper/source/get_top_bundle.cpp",
|
||||
"${request_path}/services/service/rust/src/c_wrapper/source/network_adapter.cpp",
|
||||
"${request_path}/services/service/request/c_wrapper/source/application_state_observer.cpp",
|
||||
"${request_path}/services/service/request/c_wrapper/source/background_notification.cpp",
|
||||
"${request_path}/services/service/request/c_wrapper/source/c_check_permission.cpp",
|
||||
"${request_path}/services/service/request/c_wrapper/source/c_event_handler.cpp",
|
||||
"${request_path}/services/service/request/c_wrapper/source/c_request_database.cpp",
|
||||
"${request_path}/services/service/request/c_wrapper/source/c_string_wrapper.cpp",
|
||||
"${request_path}/services/service/request/c_wrapper/source/c_task_config.cpp",
|
||||
"${request_path}/services/service/request/c_wrapper/source/c_task_info.cpp",
|
||||
"${request_path}/services/service/request/c_wrapper/source/common_event_notify.cpp",
|
||||
"${request_path}/services/service/request/c_wrapper/source/get_calling_bundle.cpp",
|
||||
"${request_path}/services/service/request/c_wrapper/source/get_top_bundle.cpp",
|
||||
"${request_path}/services/service/request/c_wrapper/source/network_adapter.cpp",
|
||||
]
|
||||
cflags_cc = [ "-O2" ]
|
||||
|
42
services/service/request/Cargo.toml
Normal file
42
services/service/request/Cargo.toml
Normal file
@ -0,0 +1,42 @@
|
||||
# Copyright (C) 2023 Huawei Device Co., Ltd.
|
||||
# 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.
|
||||
|
||||
[package]
|
||||
name = "request"
|
||||
version = "1.0.0"
|
||||
edition = "2021"
|
||||
license = "Apache-2.0"
|
||||
|
||||
[features]
|
||||
default = []
|
||||
|
||||
oh = ["hilog_rust", "hisysevent", "hitrace_meter_rust", "rust_samgr", "ipc_rust"]
|
||||
|
||||
[dependencies]
|
||||
ylong_runtime = { git = "https://gitee.com/openharmony/commonlibrary_rust_ylong_runtime", features = ["full"] }
|
||||
ylong_http_client = { git = "https://gitee.com/openharmony/commonlibrary_rust_ylong_http", features = [
|
||||
"async",
|
||||
"c_openssl_3_0",
|
||||
"http1_1",
|
||||
"ylong_base",
|
||||
] }
|
||||
|
||||
hilog_rust = { git = "https://gitee.com/openharmony/hiviewdfx_hilog.git", optional = true }
|
||||
hisysevent = { git = "https://gitee.com/openharmony/hiviewdfx_hisysevent.git", optional = true }
|
||||
hitrace_meter_rust = { git = "https://gitee.com/openharmony/hiviewdfx_hitrace.git", optional = true }
|
||||
|
||||
rust_samgr = { git = "https://gitee.com/openharmony/systemabilitymgr_samgr.git", optional = true }
|
||||
ipc_rust = { git = "https://gitee.com/openharmony/communication_ipc.git", optional = true }
|
||||
|
||||
log = { version = "0.4.20" }
|
||||
env_logger = { version = "0.10.1" }
|
@ -66,7 +66,8 @@ constexpr const char *CREATE_REQUEST_TABLE1 = "CREATE TABLE IF NOT EXISTS reques
|
||||
"processed TEXT, "
|
||||
"extras TEXT, "
|
||||
"form_items_len INTEGER, "
|
||||
"file_specs_len INTEGER)";
|
||||
"file_specs_len INTEGER, "
|
||||
"priority INTEGER)";
|
||||
|
||||
constexpr const char *CREATE_REQUEST_TABLE2 = "CREATE TABLE IF NOT EXISTS task_info_attachment "
|
||||
"(id INTEGER PRIMARY KEY AUTOINCREMENT, "
|
||||
@ -111,7 +112,8 @@ constexpr const char *CREATE_REQUEST_TABLE3 = "CREATE TABLE IF NOT EXISTS reques
|
||||
"version INTEGER, "
|
||||
"form_items_len INTEGER, "
|
||||
"file_specs_len INTEGER, "
|
||||
"body_file_names_len INTEGER)";
|
||||
"body_file_names_len INTEGER, "
|
||||
"priority INTEGER)";
|
||||
|
||||
constexpr const char *CREATE_REQUEST_TABLE4 = "CREATE TABLE IF NOT EXISTS task_config_attachment "
|
||||
"(id INTEGER PRIMARY KEY AUTOINCREMENT, "
|
||||
@ -166,6 +168,7 @@ struct CVectorWrapper {
|
||||
bool HasRequestTaskRecord(uint32_t taskId);
|
||||
bool RecordRequestTaskInfo(CTaskInfo *taskInfo);
|
||||
bool UpdateRequestTaskInfo(uint32_t taskId, CUpdateInfo *updateInfo);
|
||||
CTaskInfo *Show(uint32_t taskId, uint64_t uid);
|
||||
CTaskInfo *Touch(uint32_t taskId, uint64_t uid, CStringWrapper token);
|
||||
CTaskInfo *Query(uint32_t taskId, Action queryAction);
|
||||
CVectorWrapper Search(CFilter filter);
|
||||
@ -186,6 +189,7 @@ bool RecordRequestTaskConfig(CTaskConfig *taskConfig);
|
||||
void GetCommonTaskConfig(std::shared_ptr<OHOS::NativeRdb::ResultSet> resultSet, TaskConfig &taskConfig);
|
||||
CTaskConfig **QueryAllTaskConfig();
|
||||
int QueryTaskConfigLen();
|
||||
void QuerySingleTaskConfig(std::shared_ptr<OHOS::NativeRdb::ResultSet> resultSet, TaskConfig &taskConfig);
|
||||
int QueryRequestTaskConfig(const OHOS::NativeRdb::RdbPredicates &rdbPredicates, std::vector<TaskConfig> &taskConfigs);
|
||||
int QueryTaskConfigAttachment(const OHOS::NativeRdb::RdbPredicates &rdbPredicates, TaskConfig &taskConfig,
|
||||
int64_t formItemsLen, int64_t fileSpecsLen, int64_t bodyFileNamesLen);
|
@ -41,6 +41,7 @@ struct CommonTaskConfig {
|
||||
int64_t ends;
|
||||
bool gauge;
|
||||
bool precise;
|
||||
uint32_t priority;
|
||||
bool background;
|
||||
};
|
||||
|
@ -37,6 +37,7 @@ struct CommonTaskInfo {
|
||||
bool retry;
|
||||
uint32_t tries;
|
||||
uint8_t version;
|
||||
uint32_t priority;
|
||||
};
|
||||
|
||||
struct CEachFileStatus {
|
@ -197,6 +197,7 @@ bool WriteRequestTaskInfo(CTaskInfo *taskInfo)
|
||||
insertValues.PutInt("retry", taskInfo->commonData.retry);
|
||||
insertValues.PutLong("tries", taskInfo->commonData.tries);
|
||||
insertValues.PutInt("version", taskInfo->commonData.version);
|
||||
insertValues.PutLong("priority", taskInfo->commonData.priority);
|
||||
insertValues.PutString("bundle", std::string(taskInfo->bundle.cStr, taskInfo->bundle.len));
|
||||
insertValues.PutString("url", std::string(taskInfo->url.cStr, taskInfo->url.len));
|
||||
insertValues.PutString("data", std::string(taskInfo->data.cStr, taskInfo->data.len));
|
||||
@ -301,6 +302,26 @@ bool UpdateRequestTaskInfo(uint32_t taskId, CUpdateInfo *updateInfo)
|
||||
return true;
|
||||
}
|
||||
|
||||
CTaskInfo *Show(uint32_t taskId, uint64_t uid)
|
||||
{
|
||||
OHOS::NativeRdb::RdbPredicates rdbPredicates1("request_task_info");
|
||||
rdbPredicates1.EqualTo("task_id", std::to_string(taskId))
|
||||
->And()
|
||||
->EqualTo("uid", std::to_string(uid));
|
||||
int64_t formItemsLen = 0;
|
||||
int64_t fileSpecsLen = 0;
|
||||
TaskInfo taskInfo;
|
||||
if (TouchRequestTaskInfo(rdbPredicates1, taskInfo, formItemsLen, fileSpecsLen) == OHOS::Request::QUERY_ERR) {
|
||||
return nullptr;
|
||||
}
|
||||
OHOS::NativeRdb::RdbPredicates rdbPredicates2("task_info_attachment");
|
||||
rdbPredicates2.EqualTo("task_id", std::to_string(taskId))->And()->EqualTo("uid", std::to_string(uid));
|
||||
if (TouchTaskInfoAttachment(rdbPredicates2, taskInfo, formItemsLen, fileSpecsLen) == OHOS::Request::QUERY_ERR) {
|
||||
return nullptr;
|
||||
}
|
||||
return BuildCTaskInfo(taskInfo);
|
||||
}
|
||||
|
||||
CTaskInfo *Touch(uint32_t taskId, uint64_t uid, CStringWrapper token)
|
||||
{
|
||||
OHOS::NativeRdb::RdbPredicates rdbPredicates1("request_task_info");
|
||||
@ -405,27 +426,27 @@ void GetCommonTaskInfo(std::shared_ptr<OHOS::NativeRdb::ResultSet> resultSet, Ta
|
||||
int64_t tries = 0;
|
||||
int version = 0;
|
||||
|
||||
resultSet->GetLong(0, taskId);
|
||||
resultSet->GetLong(0, taskId); // Line 0 here is 'task_id'
|
||||
taskInfo.commonData.taskId = static_cast<uint32_t>(taskId);
|
||||
resultSet->GetLong(1, uid);
|
||||
resultSet->GetLong(1, uid); // Line 1 here is 'uid'
|
||||
taskInfo.commonData.uid = static_cast<uint64_t>(uid);
|
||||
resultSet->GetInt(2, action);
|
||||
resultSet->GetInt(2, action); // Line 2 here is 'action'
|
||||
taskInfo.commonData.action = static_cast<uint8_t>(action);
|
||||
resultSet->GetInt(3, mode);
|
||||
resultSet->GetInt(3, mode); // Line 3 here is 'mode'
|
||||
taskInfo.commonData.mode = static_cast<uint8_t>(mode);
|
||||
resultSet->GetLong(4, ctime);
|
||||
resultSet->GetLong(4, ctime); // Line 4 here is 'ctime'
|
||||
taskInfo.commonData.ctime = static_cast<uint64_t>(ctime);
|
||||
resultSet->GetLong(5, mtime);
|
||||
resultSet->GetLong(5, mtime); // Line 5 here is 'mtime'
|
||||
taskInfo.commonData.mtime = static_cast<uint64_t>(mtime);
|
||||
resultSet->GetInt(6, reason);
|
||||
resultSet->GetInt(6, reason); // Line 6 here is 'reason'
|
||||
taskInfo.commonData.reason = static_cast<uint8_t>(reason);
|
||||
resultSet->GetInt(7, gauge);
|
||||
resultSet->GetInt(7, gauge); // Line 7 here is 'gauge'
|
||||
taskInfo.commonData.gauge = static_cast<bool>(gauge);
|
||||
resultSet->GetInt(8, retry);
|
||||
resultSet->GetInt(8, retry); // Line 8 here is 'retry'
|
||||
taskInfo.commonData.retry = static_cast<bool>(retry);
|
||||
resultSet->GetLong(9, tries);
|
||||
resultSet->GetLong(9, tries); // Line 9 here is 'tries'
|
||||
taskInfo.commonData.tries = static_cast<uint32_t>(tries);
|
||||
resultSet->GetInt(10, version);
|
||||
resultSet->GetInt(10, version); // Line 10 here is 'version'
|
||||
taskInfo.commonData.version = static_cast<uint8_t>(version);
|
||||
}
|
||||
|
||||
@ -435,7 +456,7 @@ int TouchRequestTaskInfo(const OHOS::NativeRdb::RdbPredicates &rdbPredicates, Ta
|
||||
auto resultSet = OHOS::Request::RequestDataBase::GetInstance().Query(rdbPredicates,
|
||||
{ "task_id", "uid", "action", "mode", "ctime", "mtime", "reason", "gauge", "retry", "tries", "version", "url",
|
||||
"data", "titile", "description", "mime_type", "state", "idx", "total_processed", "sizes", "processed",
|
||||
"extras", "form_items_len", "file_specs_len" });
|
||||
"extras", "form_items_len", "file_specs_len", "priority" });
|
||||
if (resultSet == nullptr || resultSet->GoToFirstRow() != OHOS::NativeRdb::E_OK) {
|
||||
REQUEST_HILOGE("result set is nullptr or go to first row failed");
|
||||
return OHOS::Request::QUERY_ERR;
|
||||
@ -443,23 +464,26 @@ int TouchRequestTaskInfo(const OHOS::NativeRdb::RdbPredicates &rdbPredicates, Ta
|
||||
int state = 0;
|
||||
int64_t idx = 0;
|
||||
int64_t totalProcessed = 0;
|
||||
int64_t priority = 0;
|
||||
GetCommonTaskInfo(resultSet, taskInfo);
|
||||
resultSet->GetString(11, taskInfo.url);
|
||||
resultSet->GetString(12, taskInfo.data);
|
||||
resultSet->GetString(13, taskInfo.title);
|
||||
resultSet->GetString(14, taskInfo.description);
|
||||
resultSet->GetString(15, taskInfo.mimeType);
|
||||
resultSet->GetInt(16, state);
|
||||
resultSet->GetString(11, taskInfo.url); // Line 11 here is 'url'
|
||||
resultSet->GetString(12, taskInfo.data); // Line 12 here is 'data'
|
||||
resultSet->GetString(13, taskInfo.title); // Line 13 here is 'title'
|
||||
resultSet->GetString(14, taskInfo.description); // Line 14 here is 'description'
|
||||
resultSet->GetString(15, taskInfo.mimeType); // Line 15 here is 'mimeType'
|
||||
resultSet->GetInt(16, state); // Line 16 here is 'state'
|
||||
taskInfo.progress.commonData.state = static_cast<uint8_t>(state);
|
||||
resultSet->GetLong(17, idx);
|
||||
resultSet->GetLong(17, idx); // Line 17 here is 'idx'
|
||||
taskInfo.progress.commonData.index = static_cast<uintptr_t>(idx);
|
||||
resultSet->GetLong(18, totalProcessed);
|
||||
resultSet->GetLong(18, totalProcessed); // Line 18 here is 'totalProcessed'
|
||||
taskInfo.progress.commonData.totalProcessed = static_cast<uintptr_t>(totalProcessed);
|
||||
resultSet->GetString(19, taskInfo.progress.sizes);
|
||||
resultSet->GetString(20, taskInfo.progress.processed);
|
||||
resultSet->GetString(21, taskInfo.progress.extras);
|
||||
resultSet->GetLong(22, formItemsLen);
|
||||
resultSet->GetLong(23, fileSpecsLen);
|
||||
resultSet->GetString(19, taskInfo.progress.sizes); // Line 19 here is 'sizes'
|
||||
resultSet->GetString(20, taskInfo.progress.processed); // Line 20 here is 'processed'
|
||||
resultSet->GetString(21, taskInfo.progress.extras); // Line 21 here is 'extras'
|
||||
resultSet->GetLong(22, formItemsLen); // Line 22 here is 'formItemsLen'
|
||||
resultSet->GetLong(23, fileSpecsLen); // Line 23 here is 'fileSpecsLen'
|
||||
resultSet->GetLong(24, priority); // Line 24 here is 'priority'
|
||||
taskInfo.commonData.priority = static_cast<uint32_t>(priority);
|
||||
resultSet->Close();
|
||||
return OHOS::Request::QUERY_OK;
|
||||
}
|
||||
@ -478,22 +502,25 @@ int QueryRequestTaskInfo(const OHOS::NativeRdb::RdbPredicates &rdbPredicates, Ta
|
||||
int state = 0;
|
||||
int64_t idx = 0;
|
||||
int64_t totalProcessed = 0;
|
||||
int64_t priority = 0;
|
||||
GetCommonTaskInfo(resultSet, taskInfo);
|
||||
resultSet->GetString(11, taskInfo.bundle);
|
||||
resultSet->GetString(12, taskInfo.title);
|
||||
resultSet->GetString(13, taskInfo.description);
|
||||
resultSet->GetString(14, taskInfo.mimeType);
|
||||
resultSet->GetInt(15, state);
|
||||
resultSet->GetString(11, taskInfo.bundle); // Line 11 here is 'bundle'
|
||||
resultSet->GetString(12, taskInfo.title); // Line 12 here is 'title'
|
||||
resultSet->GetString(13, taskInfo.description); // Line 13 here is 'description'
|
||||
resultSet->GetString(14, taskInfo.mimeType); // Line 14 here is 'mimeType'
|
||||
resultSet->GetInt(15, state); // Line 15 here is 'state'
|
||||
taskInfo.progress.commonData.state = static_cast<uint8_t>(state);
|
||||
resultSet->GetLong(16, idx);
|
||||
resultSet->GetLong(16, idx); // Line 16 here is 'idx'
|
||||
taskInfo.progress.commonData.index = static_cast<uintptr_t>(idx);
|
||||
resultSet->GetLong(17, totalProcessed);
|
||||
resultSet->GetLong(17, totalProcessed); // Line 17 here is 'totalProcessed'
|
||||
taskInfo.progress.commonData.totalProcessed = static_cast<uintptr_t>(totalProcessed);
|
||||
resultSet->GetString(18, taskInfo.progress.sizes);
|
||||
resultSet->GetString(19, taskInfo.progress.processed);
|
||||
resultSet->GetString(20, taskInfo.progress.extras);
|
||||
resultSet->GetLong(21, formItemsLen);
|
||||
resultSet->GetLong(22, fileSpecsLen);
|
||||
resultSet->GetString(18, taskInfo.progress.sizes); // Line 18 here is 'sizes'
|
||||
resultSet->GetString(19, taskInfo.progress.processed); // Line 19 here is 'processed'
|
||||
resultSet->GetString(20, taskInfo.progress.extras); // Line 20 here is 'extras'
|
||||
resultSet->GetLong(21, formItemsLen); // Line 21 here is 'formItemsLen'
|
||||
resultSet->GetLong(22, fileSpecsLen); // Line 22 here is 'fileSpecsLen'
|
||||
resultSet->GetLong(23, priority); // Line 23 here is 'priority'
|
||||
taskInfo.commonData.priority = static_cast<uint32_t>(priority);
|
||||
resultSet->Close();
|
||||
return OHOS::Request::QUERY_OK;
|
||||
}
|
||||
@ -515,25 +542,25 @@ int TouchTaskInfoAttachment(const OHOS::NativeRdb::RdbPredicates &rdbPredicates,
|
||||
}
|
||||
if (i < formItemsLen) {
|
||||
FormItem formItem;
|
||||
resultSet->GetString(0, formItem.name);
|
||||
resultSet->GetString(1, formItem.value);
|
||||
resultSet->GetString(0, formItem.name); // Line 0 here is 'name'
|
||||
resultSet->GetString(1, formItem.value); // Line 1 here is 'value'
|
||||
taskInfo.formItems.push_back(std::move(formItem));
|
||||
}
|
||||
if (i < fileSpecsLen) {
|
||||
FileSpec fileSpec;
|
||||
std::string path;
|
||||
resultSet->GetString(2, fileSpec.name);
|
||||
resultSet->GetString(3, path);
|
||||
resultSet->GetString(4, fileSpec.fileName);
|
||||
resultSet->GetString(5, fileSpec.mimeType);
|
||||
resultSet->GetString(2, fileSpec.name); // Line 2 here is 'name'
|
||||
resultSet->GetString(3, path); // Line 3 here is 'path'
|
||||
resultSet->GetString(4, fileSpec.fileName); // Line 4 here is 'fileName'
|
||||
resultSet->GetString(5, fileSpec.mimeType); // Line 5 here is 'mimeType'
|
||||
fileSpec.path = path;
|
||||
taskInfo.fileSpecs.push_back(std::move(fileSpec));
|
||||
EachFileStatus eachFileStatus;
|
||||
eachFileStatus.path = std::move(path);
|
||||
int reason = 0;
|
||||
resultSet->GetInt(6, reason);
|
||||
resultSet->GetInt(6, reason); // Line 6 here is 'reason'
|
||||
eachFileStatus.reason = static_cast<uint8_t>(reason);
|
||||
resultSet->GetString(7, eachFileStatus.message);
|
||||
resultSet->GetString(7, eachFileStatus.message); // Line 7 here is 'message'
|
||||
taskInfo.eachFileStatus.push_back(std::move(eachFileStatus));
|
||||
}
|
||||
}
|
||||
@ -560,9 +587,9 @@ int QueryTaskInfoAttachment(const OHOS::NativeRdb::RdbPredicates &rdbPredicates,
|
||||
resultSet->GetString(0, path);
|
||||
eachFileStatus.path = path;
|
||||
int reason = 0;
|
||||
resultSet->GetInt(1, reason);
|
||||
resultSet->GetInt(1, reason); // Line 1 here is 'reason'
|
||||
eachFileStatus.reason = static_cast<uint8_t>(reason);
|
||||
resultSet->GetString(2, eachFileStatus.message);
|
||||
resultSet->GetString(2, eachFileStatus.message); // Line 2 here is 'message'
|
||||
taskInfo.eachFileStatus.push_back(std::move(eachFileStatus));
|
||||
FileSpec fileSpec;
|
||||
fileSpec.path = std::move(path);
|
||||
@ -663,6 +690,7 @@ bool WriteRequestTaskConfig(CTaskConfig *taskConfig)
|
||||
insertValues.PutLong("ends", taskConfig->commonData.ends);
|
||||
insertValues.PutInt("gauge", taskConfig->commonData.gauge);
|
||||
insertValues.PutInt("precise", taskConfig->commonData.precise);
|
||||
insertValues.PutLong("priority", taskConfig->commonData.priority);
|
||||
insertValues.PutInt("background", taskConfig->commonData.background);
|
||||
insertValues.PutString("bundle", std::string(taskConfig->bundle.cStr, taskConfig->bundle.len));
|
||||
insertValues.PutString("url", std::string(taskConfig->url.cStr, taskConfig->url.len));
|
||||
@ -747,37 +775,37 @@ void GetCommonTaskConfig(std::shared_ptr<OHOS::NativeRdb::ResultSet> resultSet,
|
||||
int precise = 0;
|
||||
int background = 0;
|
||||
|
||||
resultSet->GetLong(0, taskId);
|
||||
resultSet->GetLong(0, taskId); // Line 0 here is 'taskId'
|
||||
taskConfig.commonData.taskId = static_cast<uint32_t>(taskId);
|
||||
resultSet->GetLong(1, uid);
|
||||
resultSet->GetLong(1, uid); // Line 1 here is 'uid'
|
||||
taskConfig.commonData.uid = static_cast<uint64_t>(uid);
|
||||
resultSet->GetInt(2, action);
|
||||
resultSet->GetInt(2, action); // Line 2 here is 'action'
|
||||
taskConfig.commonData.action = static_cast<uint8_t>(action);
|
||||
resultSet->GetInt(3, mode);
|
||||
resultSet->GetInt(3, mode); // Line 3 here is 'mode'
|
||||
taskConfig.commonData.mode = static_cast<uint8_t>(mode);
|
||||
resultSet->GetInt(4, cover);
|
||||
resultSet->GetInt(4, cover); // Line 4 here is 'cover'
|
||||
taskConfig.commonData.cover = static_cast<bool>(cover);
|
||||
resultSet->GetInt(5, network);
|
||||
resultSet->GetInt(5, network); // Line 5 here is 'network'
|
||||
taskConfig.commonData.network = static_cast<uint8_t>(network);
|
||||
resultSet->GetInt(6, meterd);
|
||||
resultSet->GetInt(6, meterd); // Line 6 here is 'meterd'
|
||||
taskConfig.commonData.meterd = static_cast<bool>(meterd);
|
||||
resultSet->GetInt(7, roaming);
|
||||
resultSet->GetInt(7, roaming); // Line 7 here is 'roaming'
|
||||
taskConfig.commonData.roaming = static_cast<bool>(roaming);
|
||||
resultSet->GetInt(8, retry);
|
||||
resultSet->GetInt(8, retry); // Line 8 here is 'retry'
|
||||
taskConfig.commonData.retry = static_cast<bool>(retry);
|
||||
resultSet->GetInt(9, redirect);
|
||||
resultSet->GetInt(9, redirect); // Line 9 here is 'redirect'
|
||||
taskConfig.commonData.redirect = static_cast<bool>(redirect);
|
||||
resultSet->GetLong(10, index);
|
||||
resultSet->GetLong(10, index); // Line 10 here is 'index'
|
||||
taskConfig.commonData.index = static_cast<uint32_t>(index);
|
||||
resultSet->GetLong(11, begins);
|
||||
resultSet->GetLong(11, begins); // Line 11 here is 'begins'
|
||||
taskConfig.commonData.begins = static_cast<uint64_t>(begins);
|
||||
resultSet->GetLong(12, ends);
|
||||
resultSet->GetLong(12, ends); // Line 12 here is 'ends'
|
||||
taskConfig.commonData.ends = static_cast<int64_t>(ends);
|
||||
resultSet->GetInt(13, gauge);
|
||||
resultSet->GetInt(13, gauge); // Line 13 here is 'gauge'
|
||||
taskConfig.commonData.gauge = static_cast<bool>(gauge);
|
||||
resultSet->GetInt(14, precise);
|
||||
resultSet->GetInt(14, precise); // Line 14 here is 'precise'
|
||||
taskConfig.commonData.precise = static_cast<bool>(precise);
|
||||
resultSet->GetInt(15, background);
|
||||
resultSet->GetInt(15, background); // Line 15 here is 'background'
|
||||
taskConfig.commonData.background = static_cast<bool>(background);
|
||||
}
|
||||
|
||||
@ -803,13 +831,26 @@ int QueryTaskConfigLen()
|
||||
return len;
|
||||
}
|
||||
|
||||
void QuerySingleTaskConfig(std::shared_ptr<OHOS::NativeRdb::ResultSet> resultSet, TaskConfig &taskConfig)
|
||||
{
|
||||
resultSet->GetString(16, taskConfig.bundle); // Line 16 here is 'background'
|
||||
resultSet->GetString(17, taskConfig.url); // Line 17 here is 'background'
|
||||
resultSet->GetString(18, taskConfig.title); // Line 18 here is 'background'
|
||||
resultSet->GetString(19, taskConfig.description); // Line 19 here is 'background'
|
||||
resultSet->GetString(20, taskConfig.method); // Line 20 here is 'background'
|
||||
resultSet->GetString(21, taskConfig.headers); // Line 21 here is 'background'
|
||||
resultSet->GetString(22, taskConfig.data); // Line 22 here is 'background'
|
||||
resultSet->GetString(23, taskConfig.token); // Line 23 here is 'background'
|
||||
resultSet->GetString(24, taskConfig.extras); // Line 24 here is 'background'
|
||||
}
|
||||
|
||||
int QueryRequestTaskConfig(const OHOS::NativeRdb::RdbPredicates &rdbPredicates, std::vector<TaskConfig> &taskConfigs)
|
||||
{
|
||||
auto resultSet = OHOS::Request::RequestDataBase::GetInstance().Query(rdbPredicates,
|
||||
{ "task_id", "uid", "action", "mode", "cover", "network", "meterd", "roaming", "retry", "redirect", "idx",
|
||||
"begins", "ends", "gauge", "precise", "background", "bundle", "url", "titile", "description", "method",
|
||||
"headers", "data", "token", "extras", "version",
|
||||
"form_items_len", "file_specs_len", "body_file_names_len" });
|
||||
"form_items_len", "file_specs_len", "body_file_names_len", "priority" });
|
||||
int rowCount = 0;
|
||||
if (resultSet == nullptr || resultSet->GetRowCount(rowCount) != OHOS::NativeRdb::E_OK) {
|
||||
REQUEST_HILOGE("TaskConfig result set is nullptr or get row count failed");
|
||||
@ -825,21 +866,16 @@ int QueryRequestTaskConfig(const OHOS::NativeRdb::RdbPredicates &rdbPredicates,
|
||||
int64_t formItemsLen = 0;
|
||||
int64_t fileSpecsLen = 0;
|
||||
int64_t bodyFileNamesLen = 0;
|
||||
int64_t priority = 0;
|
||||
GetCommonTaskConfig(resultSet, taskConfig);
|
||||
resultSet->GetString(16, taskConfig.bundle);
|
||||
resultSet->GetString(17, taskConfig.url);
|
||||
resultSet->GetString(18, taskConfig.title);
|
||||
resultSet->GetString(19, taskConfig.description);
|
||||
resultSet->GetString(20, taskConfig.method);
|
||||
resultSet->GetString(21, taskConfig.headers);
|
||||
resultSet->GetString(22, taskConfig.data);
|
||||
resultSet->GetString(23, taskConfig.token);
|
||||
resultSet->GetString(24, taskConfig.extras);
|
||||
resultSet->GetInt(25, version);
|
||||
QuerySingleTaskConfig(resultSet, taskConfig);
|
||||
resultSet->GetInt(25, version); // Line 25 here is 'background'
|
||||
taskConfig.version = static_cast<uint8_t>(version);
|
||||
resultSet->GetLong(26, formItemsLen);
|
||||
resultSet->GetLong(27, fileSpecsLen);
|
||||
resultSet->GetLong(28, bodyFileNamesLen);
|
||||
resultSet->GetLong(26, formItemsLen); // Line 26 here is 'background'
|
||||
resultSet->GetLong(27, fileSpecsLen); // Line 27 here is 'background'
|
||||
resultSet->GetLong(28, bodyFileNamesLen); // Line 28 here is 'background'
|
||||
resultSet->GetLong(29, priority); // Line 29 here is 'background'
|
||||
taskConfig.commonData.priority = static_cast<uint32_t>(priority);
|
||||
OHOS::NativeRdb::RdbPredicates attachPredicates("task_config_attachment");
|
||||
attachPredicates.EqualTo("task_id", std::to_string(taskConfig.commonData.taskId))
|
||||
->And()->EqualTo("uid", std::to_string(taskConfig.commonData.uid));
|
||||
@ -880,16 +916,16 @@ int QueryTaskConfigAttachment(const OHOS::NativeRdb::RdbPredicates &rdbPredicate
|
||||
}
|
||||
if (i < formItemsLen) {
|
||||
FormItem formItem;
|
||||
resultSet->GetString(0, formItem.name);
|
||||
resultSet->GetString(1, formItem.value);
|
||||
resultSet->GetString(0, formItem.name); // Line 0 here is 'name'
|
||||
resultSet->GetString(1, formItem.value); // Line 1 here is 'value'
|
||||
taskConfig.formItems.push_back(std::move(formItem));
|
||||
}
|
||||
if (i < fileSpecsLen) {
|
||||
FileSpec fileSpec;
|
||||
resultSet->GetString(2, fileSpec.name);
|
||||
resultSet->GetString(3, fileSpec.path);
|
||||
resultSet->GetString(4, fileSpec.fileName);
|
||||
resultSet->GetString(5, fileSpec.mimeType);
|
||||
resultSet->GetString(2, fileSpec.name); // Line 2 here is 'name'
|
||||
resultSet->GetString(3, fileSpec.path); // Line 3 here is 'path'
|
||||
resultSet->GetString(4, fileSpec.fileName); // Line 4 here is 'fileName'
|
||||
resultSet->GetString(5, fileSpec.mimeType); // Line 5 here is 'mimeType'
|
||||
taskConfig.fileSpecs.push_back(std::move(fileSpec));
|
||||
}
|
||||
if (i < bodyFileNamesLen) {
|
28
services/service/request/src/error.rs
Normal file
28
services/service/request/src/error.rs
Normal file
@ -0,0 +1,28 @@
|
||||
// Copyright (C) 2023 Huawei Device Co., Ltd.
|
||||
// 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.
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Debug)]
|
||||
pub(crate) enum ErrorCode {
|
||||
ErrOk = 0,
|
||||
_UnloadingSA = 1,
|
||||
IpcSizeTooLarge = 2,
|
||||
Permission = 201,
|
||||
SystemApi = 202,
|
||||
ParameterCheck = 401,
|
||||
FileOperationErr = 13400001,
|
||||
Other = 13499999,
|
||||
TaskEnqueueErr = 21900004,
|
||||
_TaskModeErr,
|
||||
TaskNotFound,
|
||||
TaskStateErr,
|
||||
}
|
50
services/service/request/src/hilog.rs
Normal file
50
services/service/request/src/hilog.rs
Normal file
@ -0,0 +1,50 @@
|
||||
// Copyright (C) 2023 Huawei Device Co., Ltd.
|
||||
// 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.
|
||||
|
||||
/// hilog label.
|
||||
|
||||
macro_rules! debug {
|
||||
($($args:tt)*) => {{
|
||||
use hilog_rust::hilog;
|
||||
use std::ffi::{c_char, CString};
|
||||
use $crate::LOG_LABEL;
|
||||
|
||||
let log = format!($($args)*);
|
||||
|
||||
hilog_rust::info!(LOG_LABEL,"{}",@public(log));
|
||||
}}
|
||||
}
|
||||
|
||||
macro_rules! info {
|
||||
($($args:tt)*) => {{
|
||||
use hilog_rust::hilog;
|
||||
use std::ffi::{c_char, CString};
|
||||
use $crate::LOG_LABEL;
|
||||
|
||||
let log = format!($($args)*);
|
||||
|
||||
hilog_rust::info!(LOG_LABEL,"{}",@public(log));
|
||||
}}
|
||||
}
|
||||
|
||||
macro_rules! error {
|
||||
($($args:tt)*) => {{
|
||||
use hilog_rust::hilog;
|
||||
use std::ffi::{c_char, CString};
|
||||
use $crate::LOG_LABEL;
|
||||
|
||||
let log = format!($($args)*);
|
||||
|
||||
hilog_rust::error!(LOG_LABEL,"{}",@public(log));
|
||||
}}
|
||||
}
|
67
services/service/request/src/lib.rs
Normal file
67
services/service/request/src/lib.rs
Normal file
@ -0,0 +1,67 @@
|
||||
// Copyright (C) 2023 Huawei Device Co., Ltd.
|
||||
// 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.
|
||||
|
||||
//! This create implement the request proxy and stub
|
||||
|
||||
#![warn(missing_docs, unreachable_pub)]
|
||||
#![warn(clippy::redundant_clone, clippy::redundant_static_lifetimes)]
|
||||
#![cfg_attr(not(feature = "oh"), allow(unused))]
|
||||
|
||||
#[macro_use]
|
||||
mod macros;
|
||||
|
||||
#[cfg(not(feature = "oh"))]
|
||||
#[allow(unused_imports)]
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
|
||||
#[cfg(feature = "oh")]
|
||||
#[macro_use]
|
||||
mod hilog;
|
||||
|
||||
mod error;
|
||||
mod manager;
|
||||
mod task;
|
||||
mod utils;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
cfg_oh! {
|
||||
mod trace;
|
||||
mod sys_event;
|
||||
mod service;
|
||||
pub use service::{RequestService, RequestServiceStub};
|
||||
|
||||
/// hilog label
|
||||
pub const LOG_LABEL: hilog_rust::HiLogLabel = hilog_rust::HiLogLabel {
|
||||
log_type: hilog_rust::LogType::LogCore,
|
||||
domain: 0xD001C00,
|
||||
tag: "RequestService",
|
||||
};
|
||||
|
||||
/// Starts DownloadAbility.
|
||||
pub fn start() {
|
||||
info!("Download Ability prepared to be inited");
|
||||
service::ability::RequestAbility::init();
|
||||
info!("Download Ability inited");
|
||||
}
|
||||
|
||||
/// Starts DownloadAbility.
|
||||
pub fn stop() {
|
||||
info!("Download Ability prepared to be stopped");
|
||||
service::ability::RequestAbility::stop();
|
||||
info!("Download Ability stopped");
|
||||
}
|
||||
|
||||
}
|
21
services/service/request/src/macros.rs
Normal file
21
services/service/request/src/macros.rs
Normal file
@ -0,0 +1,21 @@
|
||||
// Copyright (C) 2023 Huawei Device Co., Ltd.
|
||||
// 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.
|
||||
|
||||
macro_rules! cfg_oh {
|
||||
($($item:item)*) => {
|
||||
$(
|
||||
#[cfg(feature = "oh")]
|
||||
$item
|
||||
)*
|
||||
}
|
||||
}
|
160
services/service/request/src/manager/events/construct.rs
Normal file
160
services/service/request/src/manager/events/construct.rs
Normal file
@ -0,0 +1,160 @@
|
||||
// Copyright (C) 2023 Huawei Device Co., Ltd.
|
||||
// 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.
|
||||
|
||||
use std::collections::HashSet;
|
||||
use std::fs::File;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::error::ErrorCode;
|
||||
use crate::manager::TaskManager;
|
||||
use crate::task::config::{TaskConfig, Version};
|
||||
use crate::task::info::State;
|
||||
use crate::task::reason::Reason;
|
||||
use crate::task::RequestTask;
|
||||
|
||||
const MAX_TASK_COUNT: u32 = 300;
|
||||
const MAX_TASK_COUNT_EACH_APP: u8 = 10;
|
||||
|
||||
impl TaskManager {
|
||||
pub(crate) fn construct_task(
|
||||
&mut self,
|
||||
config: TaskConfig,
|
||||
files: Vec<File>,
|
||||
body_files: Vec<File>,
|
||||
) -> ErrorCode {
|
||||
if files.is_empty() {
|
||||
return ErrorCode::FileOperationErr;
|
||||
}
|
||||
|
||||
let uid = config.common_data.uid;
|
||||
let task_id = config.common_data.task_id;
|
||||
let version = config.version;
|
||||
|
||||
debug!(
|
||||
"TaskManager Construct, uid:{}, task_id:{}, version:{:?}",
|
||||
uid, task_id, version
|
||||
);
|
||||
|
||||
let app_state = self.app_state(uid, &config.bundle);
|
||||
|
||||
let task = RequestTask::constructor(
|
||||
config,
|
||||
files,
|
||||
body_files,
|
||||
self.recording_rdb_num.clone(),
|
||||
AtomicBool::new(false),
|
||||
app_state,
|
||||
);
|
||||
|
||||
match task.conf.version {
|
||||
Version::API10 => {
|
||||
if !self.add_task_api10(Arc::new(task)) {
|
||||
return ErrorCode::TaskEnqueueErr;
|
||||
}
|
||||
self.api10_background_task_count += 1;
|
||||
}
|
||||
Version::API9 => {
|
||||
self.add_task_api9(Arc::new(task));
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(handle) = self.unload_handle.take() {
|
||||
debug!("TaskManager close sa timing abort");
|
||||
handle.cancel();
|
||||
}
|
||||
|
||||
ErrorCode::ErrOk
|
||||
}
|
||||
|
||||
pub(crate) fn add_task_api9(&mut self, task: Arc<RequestTask>) {
|
||||
task.set_status(State::Initialized, Reason::Default);
|
||||
|
||||
let task_id = task.conf.common_data.task_id;
|
||||
let uid = task.conf.common_data.uid;
|
||||
|
||||
self.tasks.insert(task_id, task);
|
||||
|
||||
match self.app_task_map.get_mut(&uid) {
|
||||
Some(set) => {
|
||||
set.insert(task_id);
|
||||
|
||||
debug!(
|
||||
"TaskManager app {} task count:{}, all task count {}",
|
||||
uid,
|
||||
set.len(),
|
||||
self.tasks.len()
|
||||
);
|
||||
}
|
||||
None => {
|
||||
let mut set = HashSet::new();
|
||||
set.insert(task_id);
|
||||
self.app_task_map.insert(uid, set);
|
||||
debug!(
|
||||
"TaskManager app {} task count:{}, all task count {}",
|
||||
uid,
|
||||
1,
|
||||
self.tasks.len()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn add_task_api10(&mut self, task: Arc<RequestTask>) -> bool {
|
||||
let task_id = task.conf.common_data.task_id;
|
||||
let uid = task.conf.common_data.uid;
|
||||
|
||||
if self.api10_background_task_count >= MAX_TASK_COUNT {
|
||||
error!("TaskManager add v10 task failed, the number of tasks has reached the limit in the system");
|
||||
return false;
|
||||
}
|
||||
|
||||
match self.app_task_map.get_mut(&uid) {
|
||||
Some(set) => {
|
||||
if (set.len() as u8) == MAX_TASK_COUNT_EACH_APP {
|
||||
error!(
|
||||
"TaskManager add v10 task failed, the maximum value for each application processing task has been reached");
|
||||
return false;
|
||||
}
|
||||
set.insert(task_id);
|
||||
|
||||
task.set_status(State::Initialized, Reason::Default);
|
||||
self.tasks.insert(task_id, task);
|
||||
|
||||
debug!(
|
||||
"TaskManager app {} task count:{}, all task count {}",
|
||||
uid,
|
||||
set.len(),
|
||||
self.tasks.len()
|
||||
);
|
||||
true
|
||||
}
|
||||
None => {
|
||||
let mut set = HashSet::new();
|
||||
set.insert(task_id);
|
||||
self.app_task_map.insert(uid, set);
|
||||
|
||||
task.set_status(State::Initialized, Reason::Default);
|
||||
self.tasks.insert(task_id, task);
|
||||
|
||||
debug!(
|
||||
"TaskManager app {} task count:{}, all task count {}",
|
||||
uid,
|
||||
1,
|
||||
self.tasks.len()
|
||||
);
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
46
services/service/request/src/manager/events/dump.rs
Normal file
46
services/service/request/src/manager/events/dump.rs
Normal file
@ -0,0 +1,46 @@
|
||||
// Copyright (C) 2023 Huawei Device Co., Ltd.
|
||||
// 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.
|
||||
|
||||
use crate::manager::TaskManager;
|
||||
use crate::task::info::{DumpAllEachInfo, DumpAllInfo, DumpOneInfo};
|
||||
|
||||
impl TaskManager {
|
||||
pub(crate) fn query_one_task(&self, task_id: u32) -> Option<DumpOneInfo> {
|
||||
self.tasks.get(&task_id).map(|task| DumpOneInfo {
|
||||
task_id: task.conf.common_data.task_id,
|
||||
action: task.conf.common_data.action,
|
||||
state: task.status.lock().unwrap().state,
|
||||
reason: task.status.lock().unwrap().reason,
|
||||
total_size: task
|
||||
.file_total_size
|
||||
.load(std::sync::atomic::Ordering::SeqCst),
|
||||
tran_size: task.progress.lock().unwrap().common_data.total_processed,
|
||||
url: task.conf.url.clone(),
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn query_all_task(&self) -> DumpAllInfo {
|
||||
DumpAllInfo {
|
||||
vec: self
|
||||
.tasks
|
||||
.values()
|
||||
.map(|task| DumpAllEachInfo {
|
||||
task_id: task.conf.common_data.task_id,
|
||||
action: task.conf.common_data.action,
|
||||
state: task.status.lock().unwrap().state,
|
||||
reason: task.status.lock().unwrap().reason,
|
||||
})
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
}
|
300
services/service/request/src/manager/events/mod.rs
Normal file
300
services/service/request/src/manager/events/mod.rs
Normal file
@ -0,0 +1,300 @@
|
||||
// Copyright (C) 2023 Huawei Device Co., Ltd.
|
||||
// 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.
|
||||
|
||||
use std::fmt::Debug;
|
||||
use std::fs::File;
|
||||
|
||||
use ylong_runtime::sync::oneshot::{channel, Sender};
|
||||
|
||||
mod construct;
|
||||
mod dump;
|
||||
mod pause;
|
||||
mod query;
|
||||
mod query_mime_type;
|
||||
mod remove;
|
||||
mod resume;
|
||||
mod search;
|
||||
mod show;
|
||||
mod start;
|
||||
mod stop;
|
||||
mod touch;
|
||||
|
||||
use crate::error::ErrorCode;
|
||||
use crate::task::config::{Action, TaskConfig};
|
||||
use crate::task::info::{ApplicationState, DumpAllInfo, DumpOneInfo, TaskInfo};
|
||||
use crate::utils::filter::Filter;
|
||||
use crate::utils::Recv;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) enum EventMessage {
|
||||
Service(ServiceMessage),
|
||||
State(StateMessage),
|
||||
Scheduled(ScheduledMessage),
|
||||
Task(TaskMessage),
|
||||
}
|
||||
|
||||
impl EventMessage {
|
||||
pub(crate) fn construct(
|
||||
config: TaskConfig,
|
||||
files: Vec<File>,
|
||||
body_files: Vec<File>,
|
||||
) -> (Self, Recv<ErrorCode>) {
|
||||
let (tx, rx) = channel::<ErrorCode>();
|
||||
(
|
||||
Self::Service(ServiceMessage::Construct(
|
||||
Box::new(ConstructMessage {
|
||||
config,
|
||||
files,
|
||||
body_files,
|
||||
}),
|
||||
tx,
|
||||
)),
|
||||
Recv::new(rx),
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) fn pause(uid: u64, task_id: u32) -> (Self, Recv<ErrorCode>) {
|
||||
let (tx, rx) = channel::<ErrorCode>();
|
||||
(
|
||||
Self::Service(ServiceMessage::Pause(uid, task_id, tx)),
|
||||
Recv::new(rx),
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) fn query(task_id: u32, action: Action) -> (Self, Recv<Option<TaskInfo>>) {
|
||||
let (tx, rx) = channel::<Option<TaskInfo>>();
|
||||
(
|
||||
Self::Service(ServiceMessage::Query(task_id, action, tx)),
|
||||
Recv::new(rx),
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) fn query_mime_type(uid: u64, task_id: u32) -> (Self, Recv<String>) {
|
||||
let (tx, rx) = channel::<String>();
|
||||
(
|
||||
Self::Service(ServiceMessage::QueryMimeType(uid, task_id, tx)),
|
||||
Recv::new(rx),
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) fn start(uid: u64, task_id: u32) -> (Self, Recv<ErrorCode>) {
|
||||
let (tx, rx) = channel::<ErrorCode>();
|
||||
(
|
||||
Self::Service(ServiceMessage::Start(uid, task_id, tx)),
|
||||
Recv::new(rx),
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) fn stop(uid: u64, task_id: u32) -> (Self, Recv<ErrorCode>) {
|
||||
let (tx, rx) = channel::<ErrorCode>();
|
||||
(
|
||||
Self::Service(ServiceMessage::Stop(uid, task_id, tx)),
|
||||
Recv::new(rx),
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) fn show(uid: u64, task_id: u32) -> (Self, Recv<Option<TaskInfo>>) {
|
||||
let (tx, rx) = channel::<Option<TaskInfo>>();
|
||||
(
|
||||
Self::Service(ServiceMessage::Show(uid, task_id, tx)),
|
||||
Recv::new(rx),
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) fn search(filter: Filter) -> (Self, Recv<Vec<u32>>) {
|
||||
let (tx, rx) = channel::<Vec<u32>>();
|
||||
(
|
||||
Self::Service(ServiceMessage::Search(filter, tx)),
|
||||
Recv::new(rx),
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) fn touch(uid: u64, task_id: u32, token: String) -> (Self, Recv<Option<TaskInfo>>) {
|
||||
let (tx, rx) = channel::<Option<TaskInfo>>();
|
||||
(
|
||||
Self::Service(ServiceMessage::Touch(uid, task_id, token, tx)),
|
||||
Recv::new(rx),
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) fn remove(uid: u64, task_id: u32) -> (Self, Recv<ErrorCode>) {
|
||||
let (tx, rx) = channel::<ErrorCode>();
|
||||
(
|
||||
Self::Service(ServiceMessage::Remove(uid, task_id, tx)),
|
||||
Recv::new(rx),
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) fn resume(uid: u64, task_id: u32) -> (Self, Recv<ErrorCode>) {
|
||||
let (tx, rx) = channel::<ErrorCode>();
|
||||
(
|
||||
Self::Service(ServiceMessage::Resume(uid, task_id, tx)),
|
||||
Recv::new(rx),
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) fn dump_all() -> (Self, Recv<DumpAllInfo>) {
|
||||
let (tx, rx) = channel::<DumpAllInfo>();
|
||||
(Self::Service(ServiceMessage::DumpAll(tx)), Recv::new(rx))
|
||||
}
|
||||
|
||||
pub(crate) fn dump_one(task_id: u32) -> (Self, Recv<Option<DumpOneInfo>>) {
|
||||
let (tx, rx) = channel::<Option<DumpOneInfo>>();
|
||||
(
|
||||
Self::Service(ServiceMessage::DumpOne(task_id, tx)),
|
||||
Recv::new(rx),
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) fn app_state_change(uid: u64, state: ApplicationState) -> Self {
|
||||
Self::State(StateMessage::AppStateChange(uid, state))
|
||||
}
|
||||
|
||||
pub(crate) fn network_change() -> Self {
|
||||
Self::State(StateMessage::NetworkChange)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) enum ServiceMessage {
|
||||
Construct(Box<ConstructMessage>, Sender<ErrorCode>),
|
||||
Pause(u64, u32, Sender<ErrorCode>),
|
||||
QueryMimeType(u64, u32, Sender<String>),
|
||||
Start(u64, u32, Sender<ErrorCode>),
|
||||
Stop(u64, u32, Sender<ErrorCode>),
|
||||
Show(u64, u32, Sender<Option<TaskInfo>>),
|
||||
Remove(u64, u32, Sender<ErrorCode>),
|
||||
Resume(u64, u32, Sender<ErrorCode>),
|
||||
Touch(u64, u32, String, Sender<Option<TaskInfo>>),
|
||||
Query(u32, Action, Sender<Option<TaskInfo>>),
|
||||
DumpOne(u32, Sender<Option<DumpOneInfo>>),
|
||||
Search(Filter, Sender<Vec<u32>>),
|
||||
DumpAll(Sender<DumpAllInfo>),
|
||||
}
|
||||
|
||||
pub(crate) enum TaskMessage {
|
||||
Finished(u32),
|
||||
}
|
||||
|
||||
pub(crate) enum StateMessage {
|
||||
NetworkChange,
|
||||
AppStateChange(u64, ApplicationState),
|
||||
}
|
||||
|
||||
pub(crate) struct ConstructMessage {
|
||||
pub(crate) config: TaskConfig,
|
||||
pub(crate) files: Vec<File>,
|
||||
pub(crate) body_files: Vec<File>,
|
||||
}
|
||||
|
||||
impl Debug for ConstructMessage {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("Construct")
|
||||
.field("uid", &self.config.common_data.uid)
|
||||
.field("task_id", &self.config.common_data.task_id)
|
||||
.field("title", &self.config.title)
|
||||
.field("mode", &self.config.method)
|
||||
.field("version", &self.config.version)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for ServiceMessage {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::Construct(message, _) => message.fmt(f),
|
||||
Self::Pause(uid, task_id, _) => f
|
||||
.debug_struct("Pause")
|
||||
.field("uid", uid)
|
||||
.field("task_id", task_id)
|
||||
.finish(),
|
||||
Self::QueryMimeType(uid, task_id, _) => f
|
||||
.debug_struct("QueryMimeType")
|
||||
.field("uid", uid)
|
||||
.field("task_id", task_id)
|
||||
.finish(),
|
||||
Self::Start(uid, task_id, _) => f
|
||||
.debug_struct("Start")
|
||||
.field("uid", uid)
|
||||
.field("task_id", task_id)
|
||||
.finish(),
|
||||
Self::Stop(uid, task_id, _) => f
|
||||
.debug_struct("Stop")
|
||||
.field("uid", uid)
|
||||
.field("task_id", task_id)
|
||||
.finish(),
|
||||
Self::Show(uid, task_id, _) => f
|
||||
.debug_struct("Show")
|
||||
.field("uid", uid)
|
||||
.field("task_id", task_id)
|
||||
.finish(),
|
||||
Self::Remove(uid, task_id, _) => f
|
||||
.debug_struct("Remove")
|
||||
.field("uid", uid)
|
||||
.field("task_id", task_id)
|
||||
.finish(),
|
||||
Self::Resume(uid, task_id, _) => f
|
||||
.debug_struct("Resume")
|
||||
.field("uid", uid)
|
||||
.field("task_id", task_id)
|
||||
.finish(),
|
||||
Self::Touch(uid, task_id, token, _) => f
|
||||
.debug_struct("Touch")
|
||||
.field("uid", uid)
|
||||
.field("task_id", task_id)
|
||||
.field("token", token)
|
||||
.finish(),
|
||||
Self::Query(task_id, action, _) => f
|
||||
.debug_struct("Query")
|
||||
.field("task_id", task_id)
|
||||
.field("action", action)
|
||||
.finish(),
|
||||
Self::DumpOne(task_id, _) => {
|
||||
f.debug_struct("DumpOne").field("task_id", task_id).finish()
|
||||
}
|
||||
Self::Search(filter, _) => f.debug_struct("Search").field("filter", filter).finish(),
|
||||
Self::DumpAll(_) => f.debug_struct("DumpAll").finish(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for TaskMessage {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::Finished(task_id) => f
|
||||
.debug_struct("Finished")
|
||||
.field("task_id", task_id)
|
||||
.finish(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for StateMessage {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::NetworkChange => f.pad("NetworkChange"),
|
||||
Self::AppStateChange(uid, state) => f
|
||||
.debug_struct("AppStateChange")
|
||||
.field("uid", uid)
|
||||
.field("state", state)
|
||||
.finish(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) enum ScheduledMessage {
|
||||
ClearTimeoutTasks,
|
||||
LogTasks,
|
||||
Unload,
|
||||
UpdateBackgroundApp(u64),
|
||||
}
|
37
services/service/request/src/manager/events/pause.rs
Normal file
37
services/service/request/src/manager/events/pause.rs
Normal file
@ -0,0 +1,37 @@
|
||||
// Copyright (C) 2023 Huawei Device Co., Ltd.
|
||||
// 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.
|
||||
|
||||
use crate::error::ErrorCode;
|
||||
use crate::manager::TaskManager;
|
||||
use crate::task::reason::Reason;
|
||||
|
||||
impl TaskManager {
|
||||
pub(crate) fn pause(&mut self, uid: u64, task_id: u32) -> ErrorCode {
|
||||
debug!("TaskManager pause, uid:{}, task_id:{}", uid, task_id);
|
||||
|
||||
match self.get_task(uid, task_id) {
|
||||
Some(task) => self.pause_task(task, Reason::UserOperation),
|
||||
None => {
|
||||
if self.tasks.contains_key(&task_id) {
|
||||
error!("TaskManager pause a task, task_id:{} exist, but not found in app_task_map, uid:{}", task_id, uid);
|
||||
} else {
|
||||
error!(
|
||||
"TaskManager pause a task, uid:{}, task_id:{} not exist",
|
||||
uid, task_id
|
||||
);
|
||||
}
|
||||
ErrorCode::TaskStateErr
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
53
services/service/request/src/manager/events/query.rs
Normal file
53
services/service/request/src/manager/events/query.rs
Normal file
@ -0,0 +1,53 @@
|
||||
// Copyright (C) 2023 Huawei Device Co., Ltd.
|
||||
// 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.
|
||||
|
||||
use crate::manager::TaskManager;
|
||||
use crate::task::config::Action;
|
||||
use crate::task::ffi::{CTaskInfo, DeleteCTaskInfo};
|
||||
use crate::task::info::TaskInfo;
|
||||
|
||||
impl TaskManager {
|
||||
pub(crate) fn query(&self, task_id: u32, query_action: Action) -> Option<TaskInfo> {
|
||||
debug!(
|
||||
"TaskManager query, task_id:{}, query_action:{:?}",
|
||||
task_id, query_action
|
||||
);
|
||||
|
||||
if let Some(task) = self.tasks.get(&task_id) {
|
||||
if task.conf.common_data.action == query_action || query_action == Action::Any {
|
||||
debug!("query task info by memory");
|
||||
let mut task_info = task.show();
|
||||
task_info.data = "".to_string();
|
||||
task_info.url = "".to_string();
|
||||
debug!("query task info is {:?}", task_info);
|
||||
return Some(task_info);
|
||||
}
|
||||
}
|
||||
|
||||
debug!("query task info by database");
|
||||
let c_task_info = unsafe { Query(task_id, query_action) };
|
||||
if c_task_info.is_null() {
|
||||
return None;
|
||||
}
|
||||
let c_task_info = unsafe { &*c_task_info };
|
||||
let task_info = TaskInfo::from_c_struct(c_task_info);
|
||||
debug!("query task info is {:?}", task_info);
|
||||
unsafe { DeleteCTaskInfo(c_task_info) };
|
||||
Some(task_info)
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
pub(crate) fn Query(taskId: u32, queryAction: Action) -> *const CTaskInfo;
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
// Copyright (C) 2023 Huawei Device Co., Ltd.
|
||||
// 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.
|
||||
|
||||
use super::show::Show;
|
||||
use crate::manager::TaskManager;
|
||||
use crate::task::ffi::DeleteCTaskInfo;
|
||||
use crate::task::info::TaskInfo;
|
||||
|
||||
impl TaskManager {
|
||||
pub(crate) fn query_mime_type(&self, uid: u64, task_id: u32) -> String {
|
||||
debug!(
|
||||
"TaskManager query mime type, uid:{}, task_id:{}",
|
||||
uid, task_id
|
||||
);
|
||||
|
||||
let task = self.get_task(uid, task_id);
|
||||
match task {
|
||||
Some(value) => {
|
||||
debug!("TaskManager query mime type by memory");
|
||||
value.query_mime_type()
|
||||
}
|
||||
None => {
|
||||
debug!("TaskManager query mime type: show mime type from database");
|
||||
let c_task_info = unsafe { Show(task_id, uid) };
|
||||
if c_task_info.is_null() {
|
||||
info!("TaskManger query mime type: no task found in database");
|
||||
return "".into();
|
||||
}
|
||||
let c_task_info = unsafe { &*c_task_info };
|
||||
let task_info = TaskInfo::from_c_struct(c_task_info);
|
||||
let mime_type = task_info.mime_type;
|
||||
debug!("TaskManager query mime type: mime type is {:?}", mime_type);
|
||||
unsafe { DeleteCTaskInfo(c_task_info) };
|
||||
mime_type
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
41
services/service/request/src/manager/events/remove.rs
Normal file
41
services/service/request/src/manager/events/remove.rs
Normal file
@ -0,0 +1,41 @@
|
||||
// Copyright (C) 2023 Huawei Device Co., Ltd.
|
||||
// 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.
|
||||
|
||||
use crate::error::ErrorCode;
|
||||
use crate::manager::TaskManager;
|
||||
use crate::task::info::State;
|
||||
use crate::task::reason::Reason;
|
||||
|
||||
impl TaskManager {
|
||||
pub(crate) fn remove(&mut self, uid: u64, task_id: u32) -> ErrorCode {
|
||||
if let Some(task) = self.get_task(uid, task_id) {
|
||||
task.set_status(State::Removed, Reason::UserOperation);
|
||||
self.after_task_processed(&task);
|
||||
debug!(
|
||||
"TaskManager remove a task, uid:{}, task_id:{} success",
|
||||
uid, task_id
|
||||
);
|
||||
ErrorCode::ErrOk
|
||||
} else {
|
||||
if self.tasks.contains_key(&task_id) {
|
||||
error!("TaskManager remove a task, task_id:{} exist, but not found in app_task_map, uid:{}", task_id, uid);
|
||||
} else {
|
||||
error!(
|
||||
"TaskManager remove a task, uid:{}, task_id:{} not exist",
|
||||
uid, task_id
|
||||
);
|
||||
}
|
||||
ErrorCode::TaskNotFound
|
||||
}
|
||||
}
|
||||
}
|
59
services/service/request/src/manager/events/resume.rs
Normal file
59
services/service/request/src/manager/events/resume.rs
Normal file
@ -0,0 +1,59 @@
|
||||
// Copyright (C) 2023 Huawei Device Co., Ltd.
|
||||
// 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.
|
||||
|
||||
use std::sync::atomic::Ordering;
|
||||
|
||||
use crate::error::ErrorCode;
|
||||
use crate::manager::TaskManager;
|
||||
use crate::task::info::State;
|
||||
|
||||
cfg_oh! {
|
||||
use crate::manager::Notifier;
|
||||
}
|
||||
|
||||
impl TaskManager {
|
||||
pub(crate) fn resume(&mut self, uid: u64, task_id: u32) -> ErrorCode {
|
||||
debug!("TaskManager resume, uid:{}, task_id:{}", uid, task_id);
|
||||
|
||||
if let Some(task) = self.get_task(uid, task_id) {
|
||||
let state = task.status.lock().unwrap().state;
|
||||
if state != State::Paused {
|
||||
error!("can not resume a task which state is not paused");
|
||||
return ErrorCode::TaskStateErr;
|
||||
}
|
||||
error!("resume the task success");
|
||||
task.resume.store(true, Ordering::SeqCst);
|
||||
let notify_data = task.build_notify_data();
|
||||
|
||||
#[cfg(feature = "oh")]
|
||||
Notifier::service_front_notify(
|
||||
"resume".into(),
|
||||
notify_data,
|
||||
&self.app_state(task.conf.common_data.uid, &task.conf.bundle),
|
||||
);
|
||||
self.start_inner(task);
|
||||
ErrorCode::ErrOk
|
||||
} else {
|
||||
if self.tasks.contains_key(&task_id) {
|
||||
error!("TaskManager resume a task, task_id:{} exist, but not found in app_task_map, uid:{}", task_id, uid);
|
||||
} else {
|
||||
error!(
|
||||
"TaskManager resume a task, uid:{}, task_id:{} not exist",
|
||||
uid, task_id
|
||||
);
|
||||
}
|
||||
|
||||
ErrorCode::TaskStateErr
|
||||
}
|
||||
}
|
||||
}
|
43
services/service/request/src/manager/events/search.rs
Normal file
43
services/service/request/src/manager/events/search.rs
Normal file
@ -0,0 +1,43 @@
|
||||
// Copyright (C) 2023 Huawei Device Co., Ltd.
|
||||
// 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.
|
||||
|
||||
use crate::manager::TaskManager;
|
||||
use crate::utils::c_wrapper::{CFilter, CVectorWrapper, DeleteCVectorWrapper};
|
||||
use crate::utils::filter::Filter;
|
||||
|
||||
impl TaskManager {
|
||||
pub(crate) fn search(&self, filter: Filter) -> Vec<u32> {
|
||||
debug!("TaskManager search a task, filter:{:?}", filter);
|
||||
|
||||
let mut vec = Vec::<u32>::new();
|
||||
let c_vector_wrapper = unsafe { Search(filter.to_c_struct()) };
|
||||
if c_vector_wrapper.ptr.is_null() || c_vector_wrapper.len == 0 {
|
||||
error!("c_vector_wrapper is null");
|
||||
return vec;
|
||||
}
|
||||
let slice = unsafe {
|
||||
std::slice::from_raw_parts(c_vector_wrapper.ptr, c_vector_wrapper.len as usize)
|
||||
};
|
||||
for item in slice.iter() {
|
||||
vec.push(*item);
|
||||
}
|
||||
debug!("c_vector_wrapper is not null");
|
||||
unsafe { DeleteCVectorWrapper(c_vector_wrapper.ptr) };
|
||||
vec
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
pub(crate) fn Search(filter: CFilter) -> CVectorWrapper;
|
||||
}
|
45
services/service/request/src/manager/events/show.rs
Normal file
45
services/service/request/src/manager/events/show.rs
Normal file
@ -0,0 +1,45 @@
|
||||
// Copyright (C) 2023 Huawei Device Co., Ltd.
|
||||
// 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.
|
||||
|
||||
use crate::manager::TaskManager;
|
||||
use crate::task::ffi::{CTaskInfo, DeleteCTaskInfo};
|
||||
use crate::task::info::TaskInfo;
|
||||
|
||||
impl TaskManager {
|
||||
pub(crate) fn show(&self, uid: u64, task_id: u32) -> Option<TaskInfo> {
|
||||
match self.get_task(uid, task_id) {
|
||||
Some(value) => {
|
||||
debug!("TaskManager show, uid:{}, task_id:{} success", uid, task_id);
|
||||
let task_info = value.show();
|
||||
Some(task_info)
|
||||
}
|
||||
None => {
|
||||
debug!("TaskManager show: show task info from database");
|
||||
let c_task_info = unsafe { Show(task_id, uid) };
|
||||
if c_task_info.is_null() {
|
||||
info!("TaskManger show: no task found in database");
|
||||
return None;
|
||||
}
|
||||
let c_task_info = unsafe { &*c_task_info };
|
||||
let task_info = TaskInfo::from_c_struct(c_task_info);
|
||||
debug!("TaskManager show: task info is {:?}", task_info);
|
||||
unsafe { DeleteCTaskInfo(c_task_info) };
|
||||
Some(task_info)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
pub(crate) fn Show(task_id: u32, uid: u64) -> *const CTaskInfo;
|
||||
}
|
153
services/service/request/src/manager/events/start.rs
Normal file
153
services/service/request/src/manager/events/start.rs
Normal file
@ -0,0 +1,153 @@
|
||||
// Copyright (C) 2023 Huawei Device Co., Ltd.
|
||||
// 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.
|
||||
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::error::ErrorCode;
|
||||
use crate::manager::events::{EventMessage, TaskMessage};
|
||||
use crate::manager::TaskManager;
|
||||
use crate::task::config::Version;
|
||||
use crate::task::info::{ApplicationState, State};
|
||||
use crate::task::reason::Reason;
|
||||
use crate::task::request_task::run;
|
||||
use crate::task::RequestTask;
|
||||
const MAX_RUNNING_TASK_COUNT_EACH_APP: u32 = 5; // api10
|
||||
const MAX_RUNNING_TASK_COUNT_API9: u32 = 4;
|
||||
|
||||
impl TaskManager {
|
||||
pub(crate) fn start(&mut self, uid: u64, task_id: u32) -> ErrorCode {
|
||||
info!("start a task, which task id is {}", task_id);
|
||||
|
||||
if let Some(task) = self.get_task(uid, task_id) {
|
||||
let task_state = task.status.lock().unwrap().state;
|
||||
if task_state != State::Initialized {
|
||||
error!("can not start a task which state is {}", task_state as u32);
|
||||
return ErrorCode::TaskStateErr;
|
||||
}
|
||||
self.start_inner(task);
|
||||
ErrorCode::ErrOk
|
||||
} else {
|
||||
if self.tasks.contains_key(&task_id) {
|
||||
error!("TaskManager start a task, task_id:{} exist, but not found in app_task_map, uid:{}", task_id, uid);
|
||||
} else {
|
||||
error!(
|
||||
"TaskManager start a task, uid:{}, task_id:{} not exist",
|
||||
uid, task_id
|
||||
);
|
||||
}
|
||||
ErrorCode::TaskStateErr
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn start_inner(&mut self, task: Arc<RequestTask>) {
|
||||
if !task.net_work_online() || !task.check_net_work_status() {
|
||||
error!("check net work failed");
|
||||
self.after_task_processed(&task);
|
||||
return;
|
||||
}
|
||||
let state = task.status.lock().unwrap().state;
|
||||
if state != State::Initialized && state != State::Waiting && state != State::Paused {
|
||||
self.after_task_processed(&task);
|
||||
return;
|
||||
}
|
||||
|
||||
if self.reach_maximum_running_limit(task.conf.common_data.uid, task.conf.version) {
|
||||
info!("too many task in running state");
|
||||
task.set_status(State::Waiting, Reason::RunningTaskMeetLimits);
|
||||
self.after_task_processed(&task);
|
||||
return;
|
||||
}
|
||||
|
||||
let (state, reason) = {
|
||||
let status = task.status.lock().unwrap();
|
||||
(status.state, status.reason)
|
||||
};
|
||||
if state == State::Waiting
|
||||
&& (reason == Reason::NetWorkOffline || reason == Reason::UnSupportedNetWorkType)
|
||||
{
|
||||
task.retry.store(true, Ordering::SeqCst);
|
||||
task.tries.fetch_add(1, Ordering::SeqCst);
|
||||
task.set_status(State::Retrying, Reason::Default);
|
||||
} else {
|
||||
task.set_status(State::Running, Reason::Default);
|
||||
}
|
||||
|
||||
let task_id = task.conf.common_data.task_id;
|
||||
|
||||
let tx = self.tx.clone();
|
||||
|
||||
let state = ApplicationState::from(
|
||||
self.app_state(task.conf.common_data.uid, &task.conf.bundle)
|
||||
.load(Ordering::Relaxed),
|
||||
);
|
||||
|
||||
let qos_changes = self.qos.insert(&task, state);
|
||||
|
||||
self.change_qos(qos_changes);
|
||||
|
||||
ylong_runtime::spawn(async move {
|
||||
run(task.clone()).await;
|
||||
tx.send(EventMessage::Task(TaskMessage::Finished(
|
||||
task.conf.common_data.task_id,
|
||||
)))
|
||||
});
|
||||
|
||||
info!("task {} start success", task_id);
|
||||
}
|
||||
|
||||
fn reach_maximum_running_limit(&self, uid: u64, version: Version) -> bool {
|
||||
match version {
|
||||
Version::API10 => {
|
||||
let mut count = 0;
|
||||
let tasks = match self.app_task_map.get(&uid) {
|
||||
Some(v) => v,
|
||||
None => return false,
|
||||
};
|
||||
for task in tasks {
|
||||
let request_task = match self.tasks.get(task) {
|
||||
Some(task) => task,
|
||||
None => {
|
||||
error!("TaskManager reach_maximum_running_limit task_id:{} not found in uid:{}", task, uid);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
if request_task.conf.version == Version::API10 {
|
||||
let state = request_task.status.lock().unwrap().state;
|
||||
if state == State::Retrying || state == State::Running {
|
||||
count += 1;
|
||||
}
|
||||
if count >= MAX_RUNNING_TASK_COUNT_EACH_APP {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Version::API9 => {
|
||||
let mut count = 0;
|
||||
for request_task in self.tasks.values() {
|
||||
if request_task.conf.version == Version::API9 {
|
||||
let state = request_task.status.lock().unwrap().state;
|
||||
if state == State::Retrying || state == State::Running {
|
||||
count += 1;
|
||||
}
|
||||
if count >= MAX_RUNNING_TASK_COUNT_API9 {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
51
services/service/request/src/manager/events/stop.rs
Normal file
51
services/service/request/src/manager/events/stop.rs
Normal file
@ -0,0 +1,51 @@
|
||||
// Copyright (C) 2023 Huawei Device Co., Ltd.
|
||||
// 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.
|
||||
|
||||
use std::sync::atomic::Ordering;
|
||||
|
||||
use crate::error::ErrorCode;
|
||||
use crate::manager::TaskManager;
|
||||
use crate::task::info::State;
|
||||
use crate::task::reason::Reason;
|
||||
|
||||
impl TaskManager {
|
||||
pub(crate) fn stop(&mut self, uid: u64, task_id: u32) -> ErrorCode {
|
||||
if let Some(task) = self.get_task(uid, task_id) {
|
||||
if !task.set_status(State::Stopped, Reason::UserOperation) {
|
||||
let state = task.status.lock().unwrap().state;
|
||||
error!(
|
||||
"TaskManager can not stop task_id: {} that state is {:?}",
|
||||
task_id, state
|
||||
);
|
||||
return ErrorCode::TaskStateErr;
|
||||
}
|
||||
self.after_task_processed(&task);
|
||||
debug!(
|
||||
"TaskManager stop a task, uid: {}, task_id:{} success",
|
||||
uid, task_id
|
||||
);
|
||||
task.resume.store(false, Ordering::SeqCst);
|
||||
ErrorCode::ErrOk
|
||||
} else {
|
||||
if self.tasks.contains_key(&task_id) {
|
||||
error!("TaskManager stop a task, task_id:{} exist, but not found in app_task_map, uid:{}", task_id, uid);
|
||||
} else {
|
||||
error!(
|
||||
"TaskManager stop a task, uid:{}, task_id:{} not exist",
|
||||
uid, task_id
|
||||
);
|
||||
}
|
||||
ErrorCode::TaskStateErr
|
||||
}
|
||||
}
|
||||
}
|
52
services/service/request/src/manager/events/touch.rs
Normal file
52
services/service/request/src/manager/events/touch.rs
Normal file
@ -0,0 +1,52 @@
|
||||
// Copyright (C) 2023 Huawei Device Co., Ltd.
|
||||
// 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.
|
||||
|
||||
use crate::manager::TaskManager;
|
||||
use crate::task::ffi::{CTaskInfo, DeleteCTaskInfo};
|
||||
use crate::task::info::TaskInfo;
|
||||
use crate::utils::c_wrapper::CStringWrapper;
|
||||
|
||||
impl TaskManager {
|
||||
pub(crate) fn touch(&self, uid: u64, task_id: u32, token: String) -> Option<TaskInfo> {
|
||||
debug!("TaskManager touch a task, uid:{}, task_id:{}", uid, task_id);
|
||||
|
||||
match self.get_task(uid, task_id) {
|
||||
Some(value) => {
|
||||
debug!("touch task info by memory");
|
||||
if value.conf.token.eq(token.as_str()) {
|
||||
let mut task_info = value.show();
|
||||
task_info.bundle = "".to_string();
|
||||
return Some(task_info);
|
||||
}
|
||||
None
|
||||
}
|
||||
None => {
|
||||
debug!("TaskManger touch: touch task_info from database");
|
||||
let c_task_info = unsafe { Touch(task_id, uid, CStringWrapper::from(&token)) };
|
||||
if c_task_info.is_null() {
|
||||
info!("TaskManger touch: no task found in database");
|
||||
return None;
|
||||
}
|
||||
let c_task_info = unsafe { &*c_task_info };
|
||||
let task_info = TaskInfo::from_c_struct(c_task_info);
|
||||
debug!("TaskManger touch: task info is {:?}", task_info);
|
||||
unsafe { DeleteCTaskInfo(c_task_info) };
|
||||
Some(task_info)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
pub(crate) fn Touch(taskId: u32, uid: u64, token: CStringWrapper) -> *const CTaskInfo;
|
||||
}
|
28
services/service/request/src/manager/mod.rs
Normal file
28
services/service/request/src/manager/mod.rs
Normal file
@ -0,0 +1,28 @@
|
||||
// Copyright (C) 2023 Huawei Device Co., Ltd.
|
||||
// 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.
|
||||
|
||||
pub(crate) mod task_manager;
|
||||
pub(crate) use task_manager::TaskManager;
|
||||
|
||||
pub(crate) mod monitor;
|
||||
mod unload;
|
||||
|
||||
pub(crate) mod events;
|
||||
pub(crate) mod qos;
|
||||
pub(crate) mod scheduled;
|
||||
|
||||
cfg_oh! {
|
||||
mod notifier;
|
||||
|
||||
pub(crate) use notifier::Notifier;
|
||||
}
|
226
services/service/request/src/manager/monitor.rs
Normal file
226
services/service/request/src/manager/monitor.rs
Normal file
@ -0,0 +1,226 @@
|
||||
// Copyright (C) 2023 Huawei Device Co., Ltd.
|
||||
// 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.
|
||||
|
||||
use std::sync::atomic::{AtomicU8, Ordering};
|
||||
use std::sync::Arc;
|
||||
|
||||
use super::TaskManager;
|
||||
use crate::manager::scheduled;
|
||||
use crate::task::config::Action;
|
||||
use crate::task::info::{ApplicationState, Mode, State};
|
||||
use crate::task::reason::Reason;
|
||||
|
||||
cfg_oh! {
|
||||
use crate::manager::Notifier;
|
||||
}
|
||||
|
||||
impl TaskManager {
|
||||
pub(crate) fn update_app_state(&mut self, uid: u64, state: ApplicationState) {
|
||||
if self.app_task_map.get(&uid).is_none() {
|
||||
return;
|
||||
}
|
||||
|
||||
match state {
|
||||
ApplicationState::Foreground => {
|
||||
match self.app_state_map.get(&uid) {
|
||||
Some(state) => {
|
||||
state.store(ApplicationState::Foreground as u8, Ordering::SeqCst)
|
||||
}
|
||||
None => {
|
||||
self.app_state_map.insert(
|
||||
uid,
|
||||
Arc::new(AtomicU8::new(ApplicationState::Foreground as u8)),
|
||||
);
|
||||
}
|
||||
}
|
||||
let qos_changes = self.qos.change_state(uid, state);
|
||||
self.change_qos(qos_changes);
|
||||
|
||||
self.update_foreground_app(uid);
|
||||
}
|
||||
|
||||
ApplicationState::Background => {
|
||||
match self.app_state_map.get(&uid) {
|
||||
Some(state) => {
|
||||
state.store(ApplicationState::Background as u8, Ordering::SeqCst)
|
||||
}
|
||||
None => {
|
||||
self.app_state_map.insert(
|
||||
uid,
|
||||
Arc::new(AtomicU8::new(ApplicationState::Background as u8)),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let tx = self.tx.clone();
|
||||
ylong_runtime::spawn(scheduled::update_background_app(uid, tx));
|
||||
|
||||
let qos_changes = self.qos.change_state(uid, state);
|
||||
self.change_qos(qos_changes);
|
||||
}
|
||||
|
||||
ApplicationState::Terminated => {
|
||||
match self.app_state_map.get(&uid) {
|
||||
Some(state) => {
|
||||
state.store(ApplicationState::Terminated as u8, Ordering::SeqCst)
|
||||
}
|
||||
None => {
|
||||
self.app_state_map.insert(
|
||||
uid,
|
||||
Arc::new(AtomicU8::new(ApplicationState::Terminated as u8)),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let qos_changes = self.qos.change_state(uid, state);
|
||||
self.change_qos(qos_changes);
|
||||
|
||||
self.update_terminated_app(uid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn update_foreground_app(&mut self, uid: u64) {
|
||||
debug!("TaskManager begin update_foreground_app uid:{}", uid);
|
||||
|
||||
let tasks = match self.app_task_map.get(&uid) {
|
||||
Some(set) => {
|
||||
let mut v = vec![];
|
||||
for task_id in set {
|
||||
match self.tasks.get(task_id) {
|
||||
Some(task) => {
|
||||
if task.conf.common_data.mode == Mode::FrontEnd {
|
||||
v.push(task.clone())
|
||||
}
|
||||
}
|
||||
None => {
|
||||
error!("TaskManager update_foreground_app uid:{}, task_id:{} not found int tasks", uid, task_id);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
v
|
||||
}
|
||||
None => {
|
||||
error!("TaskManager update_foreground_app uid:{} not found", uid);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
tasks.into_iter().for_each(|task| {
|
||||
let state = task.status.lock().unwrap().state;
|
||||
let reason = task.status.lock().unwrap().reason;
|
||||
if state == State::Paused && reason == Reason::AppBackgroundOrTerminate {
|
||||
info!("Begin try resume task as app switch to background");
|
||||
task.resume.store(true, Ordering::SeqCst);
|
||||
|
||||
let notify_data = task.build_notify_data();
|
||||
|
||||
#[cfg(feature = "oh")]
|
||||
Notifier::service_front_notify(
|
||||
"resume".into(),
|
||||
notify_data,
|
||||
&self.app_state(uid, &task.conf.bundle),
|
||||
);
|
||||
self.start_inner(task);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
pub(crate) fn update_background_app(&mut self, uid: u64) {
|
||||
debug!("TaskManager begin update_background_app uid:{}", uid);
|
||||
|
||||
if self.app_task_map.get(&uid).is_none() {
|
||||
return;
|
||||
}
|
||||
|
||||
let tasks = match self.app_task_map.get(&uid) {
|
||||
Some(set) => {
|
||||
let mut v = vec![];
|
||||
for task_id in set {
|
||||
match self.tasks.get(task_id) {
|
||||
Some(task) => {
|
||||
if task.conf.common_data.mode == Mode::FrontEnd {
|
||||
v.push(task.clone())
|
||||
}
|
||||
}
|
||||
None => {
|
||||
error!("TaskManager update_foreground_app uid:{}, task_id:{} not found int tasks", uid, task_id);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
v
|
||||
}
|
||||
None => {
|
||||
error!("TaskManager update_foreground_app uid:{} not found", uid);
|
||||
return;
|
||||
}
|
||||
};
|
||||
tasks.into_iter().for_each(|task| {
|
||||
if task.conf.common_data.action == Action::UpLoad {
|
||||
task.set_status(State::Failed, Reason::AppBackgroundOrTerminate);
|
||||
self.after_task_processed(&task);
|
||||
} else if task.conf.common_data.action == Action::DownLoad {
|
||||
self.pause_task(task, Reason::AppBackgroundOrTerminate);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn update_terminated_app(&mut self, uid: u64) {
|
||||
debug!("TaskManager begin update_terminated_app uid:{}", uid);
|
||||
|
||||
let tasks = match self.app_task_map.get(&uid) {
|
||||
Some(set) => {
|
||||
let mut v = vec![];
|
||||
for task_id in set {
|
||||
match self.tasks.get(task_id) {
|
||||
Some(task) => {
|
||||
if task.conf.common_data.mode == Mode::FrontEnd {
|
||||
v.push(task.clone())
|
||||
}
|
||||
}
|
||||
None => {
|
||||
error!("TaskManager update_foreground_app uid:{}, task_id:{} not found int tasks", uid, task_id);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
v
|
||||
}
|
||||
None => {
|
||||
error!("TaskManager update_foreground_app uid:{} not found", uid);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
tasks.into_iter().for_each(|task| {
|
||||
task.set_status(State::Failed, Reason::AppBackgroundOrTerminate);
|
||||
self.after_task_processed(&task);
|
||||
});
|
||||
}
|
||||
|
||||
pub(crate) fn update_network(&mut self) {
|
||||
let tasks = self.tasks.values().cloned().collect::<Vec<_>>();
|
||||
|
||||
for task in tasks {
|
||||
if unsafe { IsOnline() } {
|
||||
self.resume_waiting_task(task.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
pub(crate) fn IsOnline() -> bool;
|
||||
}
|
64
services/service/request/src/manager/notifier.rs
Normal file
64
services/service/request/src/manager/notifier.rs
Normal file
@ -0,0 +1,64 @@
|
||||
// Copyright (C) 2023 Huawei Device Co., Ltd.
|
||||
// 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.
|
||||
|
||||
use std::sync::atomic::{AtomicU8, Ordering};
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::service::ability::RequestAbility;
|
||||
use crate::service::notify::{Event, NotifyEvent};
|
||||
use crate::task::config::Version;
|
||||
use crate::task::info::ApplicationState;
|
||||
use crate::task::notify::NotifyData;
|
||||
use crate::task::RequestTask;
|
||||
pub(crate) struct Notifier;
|
||||
|
||||
impl Notifier {
|
||||
pub(crate) fn service_front_notify(
|
||||
event: String,
|
||||
notify_data: NotifyData,
|
||||
app_state: &Arc<AtomicU8>,
|
||||
) {
|
||||
let total_processed = notify_data.progress.common_data.total_processed;
|
||||
let file_total_size: i64 = notify_data.progress.sizes.iter().sum();
|
||||
if total_processed == 0 && file_total_size < 0 && event.eq("progress") {
|
||||
return;
|
||||
}
|
||||
|
||||
if ApplicationState::from(app_state.load(Ordering::SeqCst)) != ApplicationState::Foreground
|
||||
&& (notify_data.version == Version::API10 || event.eq("progress"))
|
||||
{
|
||||
return;
|
||||
}
|
||||
let event = match event.try_into() {
|
||||
Ok(event) => event,
|
||||
Err(e) => {
|
||||
error!("TaskManager notify try_into failed {:?}", e);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
let event = NotifyEvent::notify(event, notify_data);
|
||||
RequestAbility::notify().send_event(event);
|
||||
}
|
||||
|
||||
pub(crate) fn remove_notify(task: &Arc<RequestTask>) {
|
||||
let data = task.build_notify_data();
|
||||
let event = NotifyEvent::notify(Event::Remove, data);
|
||||
RequestAbility::notify().send_event(event);
|
||||
}
|
||||
|
||||
pub(crate) fn clear_notify(task: &Arc<RequestTask>) {
|
||||
let event = NotifyEvent::clear(task.conf.common_data.task_id);
|
||||
RequestAbility::notify().send_event(event);
|
||||
}
|
||||
}
|
562
services/service/request/src/manager/qos.rs
Normal file
562
services/service/request/src/manager/qos.rs
Normal file
@ -0,0 +1,562 @@
|
||||
// Copyright (C) 2023 Huawei Device Co., Ltd.
|
||||
// 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.
|
||||
|
||||
use std::cmp::Ordering;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::mem;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::task::info::ApplicationState;
|
||||
use crate::task::RequestTask;
|
||||
|
||||
const HIGH_QOS_MAX: usize = 10;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Hash, Clone)]
|
||||
pub(crate) struct QosCase {
|
||||
uid: u64,
|
||||
task_id: u32,
|
||||
qos_index: u32,
|
||||
}
|
||||
|
||||
impl PartialOrd for QosCase {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for QosCase {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
if self.uid != other.uid {
|
||||
return Ordering::Equal;
|
||||
}
|
||||
self.qos_index.cmp(&other.qos_index)
|
||||
}
|
||||
}
|
||||
|
||||
impl QosCase {
|
||||
fn new(uid: u64, task_id: u32, qos_index: u32) -> Self {
|
||||
Self {
|
||||
uid,
|
||||
task_id,
|
||||
qos_index,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct QosQueue {
|
||||
foreground_high_qos_cases: Vec<QosCase>,
|
||||
foreground_low_qos_cases: HashMap<u64, Vec<QosCase>>,
|
||||
|
||||
background_high_qos_cases: Vec<QosCase>,
|
||||
background_low_qos_cases: HashMap<u64, Vec<QosCase>>,
|
||||
|
||||
tasks: HashSet<u32>,
|
||||
|
||||
app_state_map: HashMap<u64, ApplicationState>,
|
||||
app_task_count: HashMap<u64, usize>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) enum Qos {
|
||||
High,
|
||||
Low,
|
||||
}
|
||||
|
||||
impl QosQueue {
|
||||
pub(crate) fn new() -> Self {
|
||||
Self {
|
||||
foreground_high_qos_cases: Vec::with_capacity(HIGH_QOS_MAX),
|
||||
|
||||
foreground_low_qos_cases: HashMap::new(),
|
||||
|
||||
background_high_qos_cases: Vec::with_capacity(HIGH_QOS_MAX),
|
||||
|
||||
background_low_qos_cases: HashMap::new(),
|
||||
|
||||
tasks: HashSet::new(),
|
||||
|
||||
app_state_map: HashMap::new(),
|
||||
app_task_count: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn insert(
|
||||
&mut self,
|
||||
task: &Arc<RequestTask>,
|
||||
app_state: ApplicationState,
|
||||
) -> Vec<(u32, Qos)> {
|
||||
let task_id = task.conf.common_data.task_id;
|
||||
let uid = task.conf.common_data.uid;
|
||||
let priority = task.conf.common_data.priority;
|
||||
|
||||
if self.tasks.contains(&task_id) {
|
||||
error!(
|
||||
"Qos insert a task twice, uid:{} task_id:{} priority:{}",
|
||||
uid, task_id, priority
|
||||
);
|
||||
return vec![];
|
||||
}
|
||||
|
||||
if app_state == ApplicationState::Terminated {
|
||||
error!(
|
||||
"Qos insert a terminated task, uid:{} task_id:{} priority:{}",
|
||||
uid, task_id, priority
|
||||
);
|
||||
return vec![];
|
||||
}
|
||||
|
||||
debug!(
|
||||
"Qos insert a task, uid:{} task_id:{} priority:{}",
|
||||
uid, task_id, priority
|
||||
);
|
||||
|
||||
self.tasks.insert(task_id);
|
||||
|
||||
match self.app_task_count.get_mut(&uid) {
|
||||
Some(count) => *count += 1,
|
||||
None => {
|
||||
self.app_task_count.insert(uid, 1);
|
||||
}
|
||||
}
|
||||
|
||||
let case = QosCase::new(uid, task_id, priority);
|
||||
|
||||
match self.app_state_map.get(&uid) {
|
||||
Some(state) => {
|
||||
if *state != app_state {
|
||||
error!(
|
||||
"Qos app_state_map state:{:?} not eq to inserted app_state:{:?}",
|
||||
state, app_state
|
||||
);
|
||||
|
||||
let mut qos_changes = self.change_state(uid, app_state);
|
||||
qos_changes.extend(self.insert_inner(case, app_state));
|
||||
qos_changes
|
||||
} else {
|
||||
self.insert_inner(case, app_state)
|
||||
}
|
||||
}
|
||||
None => {
|
||||
self.app_state_map.insert(uid, app_state);
|
||||
self.insert_inner(case, app_state)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn insert_inner(&mut self, case: QosCase, state: ApplicationState) -> Vec<(u32, Qos)> {
|
||||
match state {
|
||||
ApplicationState::Foreground => self.frontground_insert(case, state),
|
||||
|
||||
ApplicationState::Background => self.background_insert(case, state),
|
||||
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
fn frontground_insert(&mut self, case: QosCase, state: ApplicationState) -> Vec<(u32, Qos)> {
|
||||
if self.foreground_high_qos_cases.len() < HIGH_QOS_MAX {
|
||||
let mut qos_changes = Vec::new();
|
||||
qos_changes.push((case.task_id, Qos::High));
|
||||
|
||||
self.foreground_high_qos_cases.push(case);
|
||||
|
||||
if self.background_high_qos_cases.len() + self.foreground_high_qos_cases.len()
|
||||
> HIGH_QOS_MAX
|
||||
{
|
||||
self.background_high_qos_cases.sort();
|
||||
let down_grade_case = self.background_high_qos_cases.pop().unwrap();
|
||||
|
||||
qos_changes.push((down_grade_case.task_id, Qos::Low));
|
||||
|
||||
match self.background_low_qos_cases.get_mut(&down_grade_case.uid) {
|
||||
Some(low_qos_cases) => {
|
||||
low_qos_cases.push(down_grade_case);
|
||||
}
|
||||
None => {
|
||||
let mut low_qos_cases = Vec::new();
|
||||
let uid = down_grade_case.uid;
|
||||
low_qos_cases.push(down_grade_case);
|
||||
self.background_low_qos_cases.insert(uid, low_qos_cases);
|
||||
}
|
||||
}
|
||||
}
|
||||
qos_changes
|
||||
} else {
|
||||
self.contest_insert(case, state)
|
||||
}
|
||||
}
|
||||
|
||||
fn background_insert(&mut self, case: QosCase, state: ApplicationState) -> Vec<(u32, Qos)> {
|
||||
if self.background_high_qos_cases.len() + self.foreground_high_qos_cases.len()
|
||||
< HIGH_QOS_MAX
|
||||
{
|
||||
let task_id = case.task_id;
|
||||
self.background_high_qos_cases.push(case);
|
||||
vec![(task_id, Qos::High)]
|
||||
} else {
|
||||
self.contest_insert(case, state)
|
||||
}
|
||||
}
|
||||
|
||||
fn contest_insert(&mut self, mut case: QosCase, state: ApplicationState) -> Vec<(u32, Qos)> {
|
||||
let high_qos_cases = match state {
|
||||
ApplicationState::Foreground => &mut self.foreground_high_qos_cases,
|
||||
ApplicationState::Background => &mut self.background_high_qos_cases,
|
||||
ApplicationState::Terminated => unreachable!(),
|
||||
};
|
||||
|
||||
let low_qos_cases = match state {
|
||||
ApplicationState::Foreground => &mut self.foreground_low_qos_cases,
|
||||
ApplicationState::Background => &mut self.background_low_qos_cases,
|
||||
ApplicationState::Terminated => unreachable!(),
|
||||
};
|
||||
|
||||
let mut qos_changes = Vec::new();
|
||||
|
||||
let mut down_grade_case = &case;
|
||||
let mut swap_case_index_opt = None;
|
||||
for (i, swap_case) in high_qos_cases
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter(|(_, swap)| swap.uid == case.uid)
|
||||
{
|
||||
if down_grade_case.qos_index < swap_case.qos_index {
|
||||
down_grade_case = swap_case;
|
||||
swap_case_index_opt = Some(i)
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(i) = swap_case_index_opt {
|
||||
qos_changes.push((case.task_id, Qos::High));
|
||||
mem::swap(&mut case, high_qos_cases.get_mut(i).unwrap());
|
||||
}
|
||||
|
||||
qos_changes.push((case.task_id, Qos::Low));
|
||||
match low_qos_cases.get_mut(&case.uid) {
|
||||
Some(cases) => {
|
||||
cases.push(case);
|
||||
}
|
||||
None => {
|
||||
let mut cases = Vec::new();
|
||||
let uid = case.uid;
|
||||
cases.push(case);
|
||||
low_qos_cases.insert(uid, cases);
|
||||
}
|
||||
}
|
||||
|
||||
qos_changes
|
||||
}
|
||||
|
||||
pub(crate) fn remove(&mut self, uid: u64, task_id: u32) -> Vec<(u32, Qos)> {
|
||||
let state = match self.app_state_map.get(&uid) {
|
||||
None => {
|
||||
error!("Qos can not find app_state, uid:{}", uid);
|
||||
return vec![];
|
||||
}
|
||||
Some(state) => state,
|
||||
};
|
||||
|
||||
if !self.tasks.remove(&task_id) {
|
||||
debug!("Qos remove task_id:{} that not exist", task_id);
|
||||
return vec![];
|
||||
}
|
||||
|
||||
debug!("Qos remove uid:{} task_id:{}", uid, task_id);
|
||||
|
||||
match self.app_task_count.get_mut(&uid) {
|
||||
Some(count) => {
|
||||
*count -= 1;
|
||||
if *count == 0 {
|
||||
self.app_task_count.remove(&uid);
|
||||
}
|
||||
}
|
||||
None => {
|
||||
error!(
|
||||
"Qos remove task_id:{}, but uid:{} count task 0",
|
||||
task_id, uid
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
match state {
|
||||
ApplicationState::Foreground => self.foreground_remove(uid, task_id),
|
||||
ApplicationState::Background => self.background_remove(uid, task_id),
|
||||
ApplicationState::Terminated => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
fn foreground_remove(&mut self, uid: u64, task_id: u32) -> Vec<(u32, Qos)> {
|
||||
let mut qos_changes = vec![];
|
||||
|
||||
for i in 0..self.foreground_high_qos_cases.len() {
|
||||
if self.foreground_high_qos_cases[i].task_id == task_id {
|
||||
self.foreground_high_qos_cases.remove(i);
|
||||
for low_qos_cases in self.foreground_low_qos_cases.values_mut() {
|
||||
low_qos_cases.sort_by(|a, b| b.qos_index.cmp(&a.qos_index));
|
||||
if let Some(case) = low_qos_cases.pop() {
|
||||
qos_changes.push((case.task_id, Qos::High));
|
||||
self.foreground_high_qos_cases.push(case);
|
||||
return qos_changes;
|
||||
}
|
||||
}
|
||||
|
||||
for low_qos_cases in self.background_low_qos_cases.values_mut() {
|
||||
low_qos_cases.sort_by(|a, b| b.qos_index.cmp(&a.qos_index));
|
||||
if let Some(case) = low_qos_cases.pop() {
|
||||
qos_changes.push((case.task_id, Qos::High));
|
||||
self.background_high_qos_cases.push(case);
|
||||
return qos_changes;
|
||||
}
|
||||
}
|
||||
return qos_changes;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(set) = self.foreground_low_qos_cases.get_mut(&uid) {
|
||||
for i in 0..set.len() {
|
||||
if set[i].task_id == task_id {
|
||||
set.remove(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
qos_changes
|
||||
}
|
||||
fn background_remove(&mut self, uid: u64, task_id: u32) -> Vec<(u32, Qos)> {
|
||||
let mut qos_changes = vec![];
|
||||
|
||||
for i in 0..self.background_high_qos_cases.len() {
|
||||
if self.background_high_qos_cases[i].task_id == task_id {
|
||||
self.background_high_qos_cases.remove(i);
|
||||
|
||||
for low_qos_cases in self.background_low_qos_cases.values_mut() {
|
||||
low_qos_cases.sort_by(|a, b| b.qos_index.cmp(&a.qos_index));
|
||||
if let Some(case) = low_qos_cases.pop() {
|
||||
qos_changes.push((case.task_id, Qos::High));
|
||||
self.background_high_qos_cases.push(case);
|
||||
return qos_changes;
|
||||
}
|
||||
}
|
||||
return qos_changes;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(set) = self.background_low_qos_cases.get_mut(&uid) {
|
||||
for i in 0..set.len() {
|
||||
if set[i].task_id == task_id {
|
||||
set.remove(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
qos_changes
|
||||
}
|
||||
|
||||
pub(crate) fn change_state(
|
||||
&mut self,
|
||||
uid: u64,
|
||||
new_state: ApplicationState,
|
||||
) -> Vec<(u32, Qos)> {
|
||||
let state = match self.app_state_map.get(&uid) {
|
||||
None => return vec![],
|
||||
Some(state) => {
|
||||
if *state == new_state {
|
||||
error!("Qos change state with the same state");
|
||||
return vec![];
|
||||
} else {
|
||||
*state
|
||||
}
|
||||
}
|
||||
};
|
||||
debug!(
|
||||
"Qos change state uid:{}, state:{:?}, new_state:{:?}",
|
||||
uid, state, new_state
|
||||
);
|
||||
|
||||
self.app_state_map.insert(uid, new_state);
|
||||
|
||||
match new_state {
|
||||
ApplicationState::Foreground => self.state_turn_to_foreground(uid),
|
||||
ApplicationState::Background => self.state_turn_to_background(uid),
|
||||
ApplicationState::Terminated => self.state_turn_to_terminated(uid, state),
|
||||
}
|
||||
}
|
||||
|
||||
fn state_turn_to_foreground(&mut self, uid: u64) -> Vec<(u32, Qos)> {
|
||||
let mut qos_changes = vec![];
|
||||
let high_qos_cases = self
|
||||
.background_high_qos_cases
|
||||
.iter()
|
||||
.cloned()
|
||||
.filter(|case| case.uid == uid);
|
||||
|
||||
self.foreground_high_qos_cases.extend(high_qos_cases);
|
||||
|
||||
self.background_high_qos_cases
|
||||
.retain(|case| case.uid != uid);
|
||||
|
||||
if let Some(mut low_qos_cases) = self.background_low_qos_cases.remove(&uid) {
|
||||
low_qos_cases.sort_by(|a, b| b.qos_index.cmp(&a.qos_index));
|
||||
while self.foreground_high_qos_cases.len() < HIGH_QOS_MAX {
|
||||
if let Some(case) = low_qos_cases.pop() {
|
||||
qos_changes.extend(self.frontground_insert(case, ApplicationState::Foreground));
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if !low_qos_cases.is_empty() {
|
||||
self.foreground_low_qos_cases.insert(uid, low_qos_cases);
|
||||
}
|
||||
}
|
||||
qos_changes
|
||||
}
|
||||
|
||||
fn state_turn_to_background(&mut self, uid: u64) -> Vec<(u32, Qos)> {
|
||||
let mut qos_changes = vec![];
|
||||
|
||||
if let Some(low_qos_cases) = self.foreground_low_qos_cases.remove(&uid) {
|
||||
self.background_low_qos_cases.insert(uid, low_qos_cases);
|
||||
}
|
||||
|
||||
let mut high_qos_cases = self
|
||||
.foreground_high_qos_cases
|
||||
.iter()
|
||||
.cloned()
|
||||
.filter(|case| case.uid == uid)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
self.foreground_high_qos_cases
|
||||
.retain(|case| case.uid != uid);
|
||||
|
||||
'a: for low_qos_cases in self.foreground_low_qos_cases.values_mut() {
|
||||
low_qos_cases.sort_by(|a, b| b.qos_index.cmp(&a.qos_index));
|
||||
while self.foreground_high_qos_cases.len() < HIGH_QOS_MAX {
|
||||
if let Some(case) = low_qos_cases.pop() {
|
||||
qos_changes.push((case.task_id, Qos::High));
|
||||
self.foreground_high_qos_cases.push(case);
|
||||
} else {
|
||||
break 'a;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.foreground_low_qos_cases
|
||||
.retain(|_, cases| !cases.is_empty());
|
||||
|
||||
if self.foreground_high_qos_cases.len() < 10 {
|
||||
high_qos_cases.sort_by(|a, b| b.qos_index.cmp(&a.qos_index));
|
||||
|
||||
while self.background_high_qos_cases.len() + self.foreground_high_qos_cases.len()
|
||||
< HIGH_QOS_MAX
|
||||
{
|
||||
if let Some(case) = high_qos_cases.pop() {
|
||||
self.background_high_qos_cases.push(case);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
qos_changes.extend(high_qos_cases.iter().map(|case| (case.task_id, Qos::Low)));
|
||||
|
||||
if !high_qos_cases.is_empty() {
|
||||
match self.background_low_qos_cases.get_mut(&uid) {
|
||||
Some(low_qos_cases) => {
|
||||
low_qos_cases.extend(high_qos_cases);
|
||||
}
|
||||
None => {
|
||||
let low_qos_cases = high_qos_cases.into_iter().collect();
|
||||
self.background_low_qos_cases.insert(uid, low_qos_cases);
|
||||
}
|
||||
}
|
||||
}
|
||||
qos_changes
|
||||
}
|
||||
fn state_turn_to_terminated(
|
||||
&mut self,
|
||||
uid: u64,
|
||||
old_state: ApplicationState,
|
||||
) -> Vec<(u32, Qos)> {
|
||||
let mut qos_changes = vec![];
|
||||
|
||||
self.app_state_map.remove(&uid);
|
||||
self.app_task_count.remove(&uid);
|
||||
|
||||
match old_state {
|
||||
ApplicationState::Background => {
|
||||
self.background_high_qos_cases
|
||||
.iter()
|
||||
.filter(|case| case.uid == uid)
|
||||
.for_each(|case| {
|
||||
self.tasks.remove(&case.task_id);
|
||||
});
|
||||
|
||||
self.background_high_qos_cases
|
||||
.retain(|case| case.uid != uid);
|
||||
|
||||
'a: for low_qos_cases in self.background_low_qos_cases.values_mut() {
|
||||
low_qos_cases.sort_by(|a, b| b.qos_index.cmp(&a.qos_index));
|
||||
while self.background_high_qos_cases.len()
|
||||
+ self.foreground_high_qos_cases.len()
|
||||
< HIGH_QOS_MAX
|
||||
{
|
||||
if let Some(case) = low_qos_cases.pop() {
|
||||
qos_changes.push((case.task_id, Qos::High));
|
||||
self.background_high_qos_cases.push(case);
|
||||
} else {
|
||||
break 'a;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(remove_tasks) = self.background_low_qos_cases.remove(&uid) {
|
||||
remove_tasks.into_iter().for_each(|case| {
|
||||
self.tasks.remove(&case.task_id);
|
||||
})
|
||||
}
|
||||
}
|
||||
ApplicationState::Foreground => {
|
||||
self.foreground_high_qos_cases
|
||||
.iter()
|
||||
.filter(|case| case.uid == uid)
|
||||
.for_each(|case| {
|
||||
self.tasks.remove(&case.task_id);
|
||||
});
|
||||
|
||||
self.foreground_high_qos_cases
|
||||
.retain(|case| case.uid != uid);
|
||||
|
||||
'a: for low_qos_cases in self.foreground_low_qos_cases.values_mut() {
|
||||
low_qos_cases.sort_by(|a, b| b.qos_index.cmp(&a.qos_index));
|
||||
while self.foreground_high_qos_cases.len() < HIGH_QOS_MAX {
|
||||
if let Some(case) = low_qos_cases.pop() {
|
||||
qos_changes.push((case.task_id, Qos::High));
|
||||
self.foreground_high_qos_cases.push(case);
|
||||
} else {
|
||||
break 'a;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(remove_tasks) = self.foreground_low_qos_cases.remove(&uid) {
|
||||
remove_tasks.into_iter().for_each(|case| {
|
||||
self.tasks.remove(&case.task_id);
|
||||
})
|
||||
}
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
||||
qos_changes
|
||||
}
|
||||
}
|
122
services/service/request/src/manager/scheduled.rs
Normal file
122
services/service/request/src/manager/scheduled.rs
Normal file
@ -0,0 +1,122 @@
|
||||
// Copyright (C) 2023 Huawei Device Co., Ltd.
|
||||
// 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.
|
||||
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
use ylong_runtime::sync::mpsc::UnboundedSender;
|
||||
|
||||
use super::events::{EventMessage, ScheduledMessage};
|
||||
use super::TaskManager;
|
||||
use crate::task::config::Version;
|
||||
use crate::task::info::State;
|
||||
use crate::task::reason::Reason;
|
||||
use crate::task::RequestTask;
|
||||
use crate::utils::get_current_timestamp;
|
||||
|
||||
const MILLISECONDS_IN_ONE_DAY: u64 = 24 * 60 * 60 * 1000;
|
||||
const MILLISECONDS_IN_ONE_MONTH: u64 = 30 * 24 * 60 * 60 * 1000;
|
||||
const CLEAR_INTERVAL: u64 = 30 * 60;
|
||||
const LOG_INTERVAL: u64 = 5 * 60;
|
||||
const UNLOAD_WAITING: u64 = 60;
|
||||
const BACKGROUND_TASK_STOP_INTERVAL: u64 = 60;
|
||||
// monitor tasks, tasks in waiting state turn to stop after one day, tasks in
|
||||
// other state turn to stop after one month.
|
||||
pub(crate) async fn clear_timeout_tasks(tx: UnboundedSender<EventMessage>) {
|
||||
loop {
|
||||
ylong_runtime::time::sleep(Duration::from_secs(CLEAR_INTERVAL)).await;
|
||||
let _ = tx.send(EventMessage::Scheduled(ScheduledMessage::ClearTimeoutTasks));
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn log_all_task_info(tx: UnboundedSender<EventMessage>) {
|
||||
loop {
|
||||
ylong_runtime::time::sleep(Duration::from_secs(LOG_INTERVAL)).await;
|
||||
let _ = tx.send(EventMessage::Scheduled(ScheduledMessage::LogTasks));
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn unload_sa(tx: UnboundedSender<EventMessage>) {
|
||||
ylong_runtime::time::sleep(Duration::from_secs(UNLOAD_WAITING)).await;
|
||||
let _ = tx.send(EventMessage::Scheduled(ScheduledMessage::Unload));
|
||||
}
|
||||
|
||||
pub(crate) async fn update_background_app(uid: u64, tx: UnboundedSender<EventMessage>) {
|
||||
ylong_runtime::time::sleep(Duration::from_secs(BACKGROUND_TASK_STOP_INTERVAL)).await;
|
||||
let _ = tx.send(EventMessage::Scheduled(
|
||||
ScheduledMessage::UpdateBackgroundApp(uid),
|
||||
));
|
||||
}
|
||||
|
||||
impl TaskManager {
|
||||
pub(crate) fn clear_timeout_tasks(&mut self) {
|
||||
let mut remove_tasks = Vec::<Arc<RequestTask>>::new();
|
||||
|
||||
for task in self.tasks.values() {
|
||||
let current_time = get_current_timestamp();
|
||||
let (state, time) = {
|
||||
let guard = task.status.lock().unwrap();
|
||||
(guard.state, guard.waitting_network_time)
|
||||
};
|
||||
if state == State::Waiting {
|
||||
if let Some(t) = time {
|
||||
if current_time - t > MILLISECONDS_IN_ONE_DAY {
|
||||
task.set_status(State::Stopped, Reason::WaittingNetWorkOneday);
|
||||
remove_tasks.push(task.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
if task.conf.version == Version::API9 {
|
||||
continue;
|
||||
}
|
||||
if current_time - task.ctime > MILLISECONDS_IN_ONE_MONTH {
|
||||
task.set_status(State::Stopped, Reason::TaskSurvivalOneMonth);
|
||||
remove_tasks.push(task.clone());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
for task in remove_tasks {
|
||||
self.after_task_processed(&task);
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn log_all_task_info(&self) {
|
||||
let api10_background_task_count = self.api10_background_task_count;
|
||||
let recording_rdb_num = self.recording_rdb_num.load(Ordering::SeqCst);
|
||||
info!(
|
||||
"dump all task info, api10_background_task_count:{}, recording_rdb_num:{}",
|
||||
api10_background_task_count, recording_rdb_num
|
||||
);
|
||||
for (task_id, task) in self.tasks.iter() {
|
||||
let task_status = task.status.lock().unwrap();
|
||||
info!("dump task message, task_id:{}, action:{}, mode:{}, bundle name:{}, task_status:{:?}",
|
||||
task_id, task.conf.common_data.action as u8, task.conf.common_data.mode as u8, task.conf.bundle, *task_status);
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn schedule_unload_sa(&mut self) {
|
||||
debug!("TaskManage clock 60s to close sa");
|
||||
let tx = self.tx.clone();
|
||||
match self.unload_handle.take() {
|
||||
Some(handle) => {
|
||||
handle.cancel();
|
||||
self.unload_handle = Some(ylong_runtime::spawn(unload_sa(tx)));
|
||||
}
|
||||
None => {
|
||||
self.unload_handle = Some(ylong_runtime::spawn(unload_sa(tx)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
456
services/service/request/src/manager/task_manager.rs
Normal file
456
services/service/request/src/manager/task_manager.rs
Normal file
@ -0,0 +1,456 @@
|
||||
// Copyright (C) 2023 Huawei Device Co., Ltd.
|
||||
// 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.
|
||||
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::sync::atomic::{AtomicU32, AtomicU8, Ordering};
|
||||
use std::sync::Arc;
|
||||
|
||||
use ylong_runtime::sync::mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender};
|
||||
use ylong_runtime::task::JoinHandle;
|
||||
|
||||
use super::events::{
|
||||
ConstructMessage, EventMessage, ScheduledMessage, ServiceMessage, StateMessage, TaskMessage,
|
||||
};
|
||||
use super::qos::{Qos, QosQueue};
|
||||
use super::scheduled;
|
||||
use crate::error::ErrorCode;
|
||||
use crate::task::config::Version;
|
||||
use crate::task::info::{ApplicationState, State};
|
||||
use crate::task::reason::Reason;
|
||||
use crate::task::request_task::RequestTask;
|
||||
use crate::utils::c_wrapper::CStringWrapper;
|
||||
|
||||
cfg_oh! {
|
||||
use crate::manager::Notifier;
|
||||
}
|
||||
|
||||
pub(crate) struct TaskManager {
|
||||
pub(crate) tasks: HashMap<u32, Arc<RequestTask>>,
|
||||
pub(crate) qos: QosQueue,
|
||||
|
||||
pub(crate) app_task_map: HashMap<u64, HashSet<u32>>,
|
||||
|
||||
pub(crate) app_state_map: HashMap<u64, Arc<AtomicU8>>,
|
||||
|
||||
pub(crate) restoring: bool,
|
||||
pub(crate) api10_background_task_count: u32,
|
||||
|
||||
pub(crate) unload_handle: Option<JoinHandle<()>>,
|
||||
|
||||
pub(crate) recording_rdb_num: Arc<AtomicU32>,
|
||||
pub(crate) tx: UnboundedSender<EventMessage>,
|
||||
pub(crate) rx: UnboundedReceiver<EventMessage>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct TaskManagerEntry {
|
||||
tx: UnboundedSender<EventMessage>,
|
||||
}
|
||||
|
||||
impl TaskManagerEntry {
|
||||
fn new(tx: UnboundedSender<EventMessage>) -> Self {
|
||||
Self { tx }
|
||||
}
|
||||
|
||||
pub(crate) fn send_event(&self, event: EventMessage) -> bool {
|
||||
if self.tx.send(event).is_err() {
|
||||
error!("Sends TaskManager event failed, or TaskManager is unloading");
|
||||
return false;
|
||||
}
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
impl TaskManager {
|
||||
pub(crate) fn init() -> TaskManagerEntry {
|
||||
debug!("TaskManager init");
|
||||
|
||||
ylong_runtime::builder::RuntimeBuilder::new_multi_thread()
|
||||
.worker_num(4)
|
||||
.build_global()
|
||||
.unwrap();
|
||||
|
||||
let (tx, rx) = unbounded_channel();
|
||||
|
||||
let mut task_manager = Self::new(tx.clone(), rx);
|
||||
|
||||
// Considers update invalid task in database to FAILED state here?.
|
||||
|
||||
task_manager.restore_all_tasks(task_manager.recording_rdb_num.clone());
|
||||
|
||||
ylong_runtime::spawn(scheduled::clear_timeout_tasks(task_manager.tx.clone()));
|
||||
|
||||
ylong_runtime::spawn(scheduled::log_all_task_info(task_manager.tx.clone()));
|
||||
|
||||
ylong_runtime::spawn(task_manager.run());
|
||||
|
||||
TaskManagerEntry::new(tx)
|
||||
}
|
||||
|
||||
fn new(tx: UnboundedSender<EventMessage>, rx: UnboundedReceiver<EventMessage>) -> Self {
|
||||
TaskManager {
|
||||
qos: QosQueue::new(),
|
||||
tasks: HashMap::new(),
|
||||
app_task_map: HashMap::new(),
|
||||
app_state_map: HashMap::new(),
|
||||
|
||||
unload_handle: None,
|
||||
restoring: false,
|
||||
api10_background_task_count: 0,
|
||||
recording_rdb_num: Arc::new(AtomicU32::new(0)),
|
||||
rx,
|
||||
tx,
|
||||
}
|
||||
}
|
||||
|
||||
async fn run(mut self) {
|
||||
loop {
|
||||
let recv = match self.rx.recv().await {
|
||||
Ok(message) => message,
|
||||
Err(e) => {
|
||||
error!("TaskManager recv error {:?}", e);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
match recv {
|
||||
EventMessage::Service(message) => self.handle_service_command(message),
|
||||
EventMessage::State(message) => self.handle_state_change(message),
|
||||
EventMessage::Task(message) => self.handle_request_task(message),
|
||||
EventMessage::Scheduled(message) => {
|
||||
if self.handle_scheduled_task(message) {
|
||||
info!("TaskManager unload succeed");
|
||||
// If unload_sa success, breaks this loop.
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
debug!("TaskManager handle message done");
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_request_task(&mut self, message: TaskMessage) {
|
||||
debug!("TaskManager handle task_message {:?}", message);
|
||||
|
||||
match message {
|
||||
TaskMessage::Finished(task_id) => {
|
||||
let task = match self.tasks.get(&task_id) {
|
||||
Some(task) => task.clone(),
|
||||
None => return,
|
||||
};
|
||||
self.after_task_processed(&task);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_scheduled_task(&mut self, message: ScheduledMessage) -> bool {
|
||||
debug!("TaskManager handle scheduled_message {:?}", message);
|
||||
|
||||
match message {
|
||||
ScheduledMessage::ClearTimeoutTasks => self.clear_timeout_tasks(),
|
||||
ScheduledMessage::LogTasks => self.log_all_task_info(),
|
||||
ScheduledMessage::Unload => return self.unload_sa(),
|
||||
ScheduledMessage::UpdateBackgroundApp(uid) => self.update_background_app(uid),
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
fn handle_state_change(&mut self, message: StateMessage) {
|
||||
debug!("TaskManager handle state_message {:?}", message);
|
||||
|
||||
match message {
|
||||
StateMessage::NetworkChange => {
|
||||
self.update_network();
|
||||
}
|
||||
StateMessage::AppStateChange(uid, state) => {
|
||||
self.update_app_state(uid, state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_service_command(&mut self, message: ServiceMessage) {
|
||||
debug!("TaskManager handle service_message {:?}", message);
|
||||
|
||||
match message {
|
||||
ServiceMessage::Construct(construct_message, tx) => {
|
||||
let ConstructMessage {
|
||||
config,
|
||||
files,
|
||||
body_files,
|
||||
} = *construct_message;
|
||||
let error_code = self.construct_task(config, files, body_files);
|
||||
let _ = tx.send(error_code);
|
||||
}
|
||||
ServiceMessage::Pause(uid, task_id, tx) => {
|
||||
let error_code = self.pause(uid, task_id);
|
||||
let _ = tx.send(error_code);
|
||||
}
|
||||
ServiceMessage::Resume(uid, task_id, tx) => {
|
||||
let error_code = self.resume(uid, task_id);
|
||||
let _ = tx.send(error_code);
|
||||
}
|
||||
ServiceMessage::Start(uid, task_id, tx) => {
|
||||
let error_code = self.start(uid, task_id);
|
||||
let _ = tx.send(error_code);
|
||||
}
|
||||
ServiceMessage::Stop(uid, task_id, tx) => {
|
||||
let error_code = self.stop(uid, task_id);
|
||||
let _ = tx.send(error_code);
|
||||
}
|
||||
|
||||
ServiceMessage::Show(uid, task_id, tx) => {
|
||||
let task_info = self.show(uid, task_id);
|
||||
let _ = tx.send(task_info);
|
||||
}
|
||||
|
||||
ServiceMessage::Query(task_id, query_action, tx) => {
|
||||
let task_info = self.query(task_id, query_action);
|
||||
let _ = tx.send(task_info);
|
||||
}
|
||||
ServiceMessage::Search(filter, tx) => {
|
||||
let v = self.search(filter);
|
||||
let _ = tx.send(v);
|
||||
}
|
||||
ServiceMessage::Touch(uid, task_id, token, tx) => {
|
||||
let task_info = self.touch(uid, task_id, token);
|
||||
let _ = tx.send(task_info);
|
||||
}
|
||||
ServiceMessage::Remove(uid, task_id, tx) => {
|
||||
let error_code = self.remove(uid, task_id);
|
||||
let _ = tx.send(error_code);
|
||||
}
|
||||
ServiceMessage::DumpAll(tx) => {
|
||||
let dump_all_info = self.query_all_task();
|
||||
let _ = tx.send(dump_all_info);
|
||||
}
|
||||
ServiceMessage::DumpOne(task_id, tx) => {
|
||||
let dump_one_info = self.query_one_task(task_id);
|
||||
let _ = tx.send(dump_one_info);
|
||||
}
|
||||
ServiceMessage::QueryMimeType(uid, task_id, tx) => {
|
||||
let s = self.query_mime_type(uid, task_id);
|
||||
let _ = tx.send(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn app_state(&mut self, uid: u64, bundle: &str) -> Arc<AtomicU8> {
|
||||
match self.app_state_map.get(&uid) {
|
||||
Some(state) => state.clone(),
|
||||
None => {
|
||||
let top_bundle = unsafe { GetTopBundleName() };
|
||||
let top_bundle = top_bundle.to_string();
|
||||
debug!(
|
||||
"TaskManager try get app_state uid:{} from top_bundle {}",
|
||||
uid, top_bundle
|
||||
);
|
||||
if top_bundle == bundle {
|
||||
let state = Arc::new(AtomicU8::new(ApplicationState::Foreground as u8));
|
||||
self.app_state_map.insert(uid, state.clone());
|
||||
state
|
||||
} else {
|
||||
let state = Arc::new(AtomicU8::new(ApplicationState::Background as u8));
|
||||
self.app_state_map.insert(uid, state.clone());
|
||||
state
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn get_task(&self, uid: u64, task_id: u32) -> Option<Arc<RequestTask>> {
|
||||
self.app_task_map
|
||||
.get(&uid)
|
||||
.and_then(|set| set.get(&task_id))
|
||||
.and_then(|task_id| self.tasks.get(task_id).cloned())
|
||||
}
|
||||
|
||||
fn process_waiting_task(&mut self, uid: u64, version: Version) {
|
||||
match version {
|
||||
Version::API10 => {
|
||||
let tasks = match self.app_task_map.get(&uid) {
|
||||
Some(v) => v.iter().copied().collect::<Vec<_>>(),
|
||||
None => return,
|
||||
};
|
||||
for task in tasks {
|
||||
let request_task = match self.tasks.get(&task) {
|
||||
Some(task) => task,
|
||||
None => {
|
||||
error!(
|
||||
"TaskManager process waiting task, task_id:{} not found",
|
||||
task
|
||||
);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
if request_task.conf.version == Version::API10 {
|
||||
let state = request_task.status.lock().unwrap().state;
|
||||
if state == State::Waiting {
|
||||
debug!(
|
||||
"TaskManager begin process v10 task_id:{} which in waitting state",
|
||||
task
|
||||
);
|
||||
self.start_inner(request_task.clone());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Version::API9 => {
|
||||
for task in self.tasks.values() {
|
||||
if task.conf.version == Version::API9 {
|
||||
let state = task.status.lock().unwrap().state;
|
||||
if state == State::Waiting {
|
||||
debug!(
|
||||
"TaskManager begin process v9 task_id:{} which in waitting state",
|
||||
task.conf.common_data.task_id
|
||||
);
|
||||
let task = task.clone();
|
||||
self.start_inner(task);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn after_task_processed(&mut self, task: &Arc<RequestTask>) {
|
||||
let state = task.status.lock().unwrap().state;
|
||||
if state != State::Completed
|
||||
&& state != State::Failed
|
||||
&& state != State::Removed
|
||||
&& state != State::Stopped
|
||||
{
|
||||
return;
|
||||
}
|
||||
debug!(
|
||||
"TaskManager remove task_id:{} from map",
|
||||
task.conf.common_data.task_id
|
||||
);
|
||||
|
||||
let remove_task = self.tasks.remove(&task.conf.common_data.task_id).unwrap();
|
||||
|
||||
let uid = &task.conf.common_data.uid;
|
||||
match self.app_task_map.get_mut(uid) {
|
||||
Some(map) => {
|
||||
map.remove(&task.conf.common_data.task_id);
|
||||
}
|
||||
None => {
|
||||
error!("TaskManager after_task_processed get uid:{} failed", uid);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
match self.app_task_map.get(&task.conf.common_data.uid) {
|
||||
Some(map) => {
|
||||
if map.is_empty() {
|
||||
self.app_task_map.remove(&task.conf.common_data.uid);
|
||||
self.app_state_map.remove(&remove_task.conf.common_data.uid);
|
||||
}
|
||||
}
|
||||
None => {
|
||||
error!("TaskManger where is my map");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if remove_task.conf.version == Version::API10 {
|
||||
self.api10_background_task_count -= 1;
|
||||
}
|
||||
|
||||
let app_state = ApplicationState::from(remove_task.app_state.load(Ordering::SeqCst));
|
||||
if !(app_state == ApplicationState::Background
|
||||
&& remove_task.conf.version == Version::API10)
|
||||
{
|
||||
#[cfg(feature = "oh")]
|
||||
Notifier::remove_notify(&remove_task);
|
||||
}
|
||||
|
||||
// Notifies NotifyManager to remove RemoteObj when task has been removed.
|
||||
|
||||
#[cfg(feature = "oh")]
|
||||
Notifier::clear_notify(&remove_task);
|
||||
|
||||
let map = self
|
||||
.qos
|
||||
.remove(task.conf.common_data.uid, task.conf.common_data.task_id);
|
||||
|
||||
self.change_qos(map);
|
||||
|
||||
if self.check_unload_sa() {
|
||||
self.schedule_unload_sa();
|
||||
} else {
|
||||
self.process_waiting_task(remove_task.conf.common_data.uid, remove_task.conf.version);
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn pause_task(&self, task: Arc<RequestTask>, reason: Reason) -> ErrorCode {
|
||||
let uid = task.conf.common_data.uid;
|
||||
let task_id = task.conf.common_data.task_id;
|
||||
|
||||
if !task.set_status(State::Paused, reason) {
|
||||
let state = task.status.lock().unwrap();
|
||||
error!(
|
||||
"TaskManager pause a task, uid:{}, task_id:{} failed which state is {:?}",
|
||||
uid, task_id, state
|
||||
);
|
||||
ErrorCode::TaskStateErr
|
||||
} else {
|
||||
task.resume.store(false, Ordering::SeqCst);
|
||||
debug!(
|
||||
"TaskManager pause a task, uid:{}, task_id:{} success",
|
||||
uid, task_id
|
||||
);
|
||||
ErrorCode::ErrOk
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn resume_waiting_task(&mut self, task: Arc<RequestTask>) {
|
||||
let state = task.status.lock().unwrap().state;
|
||||
if state == State::Waiting && task.is_satisfied_configuration() {
|
||||
info!("Begin try resume task as network condition resume");
|
||||
task.resume.store(true, Ordering::SeqCst);
|
||||
let notify_data = task.build_notify_data();
|
||||
|
||||
#[cfg(feature = "oh")]
|
||||
Notifier::service_front_notify(
|
||||
"resume".into(),
|
||||
notify_data,
|
||||
&self.app_state(task.conf.common_data.uid, &task.conf.bundle),
|
||||
);
|
||||
self.start_inner(task.clone());
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn change_qos(&mut self, new_qos: Vec<(u32, Qos)>) {
|
||||
for (task_id, qos) in new_qos.iter() {
|
||||
if let Some(task) = self.tasks.get(task_id) {
|
||||
match qos {
|
||||
Qos::High => {
|
||||
info!("Qos task_id:{} set to High Qos", task_id);
|
||||
task.rate_limiting.store(false, Ordering::SeqCst);
|
||||
}
|
||||
Qos::Low => {
|
||||
info!("Qos task_id:{} set to Low Qos", task_id);
|
||||
task.rate_limiting.store(true, Ordering::SeqCst);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
pub(crate) fn GetTopBundleName() -> CStringWrapper;
|
||||
}
|
217
services/service/request/src/manager/unload.rs
Normal file
217
services/service/request/src/manager/unload.rs
Normal file
@ -0,0 +1,217 @@
|
||||
// Copyright (C) 2023 Huawei Device Co., Ltd.
|
||||
// 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.
|
||||
|
||||
use std::collections::HashSet;
|
||||
use std::sync::atomic::{AtomicBool, AtomicU32, Ordering};
|
||||
use std::sync::Arc;
|
||||
|
||||
use super::TaskManager;
|
||||
use crate::manager::monitor::IsOnline;
|
||||
use crate::task::config::{TaskConfig, Version};
|
||||
use crate::task::ffi::CTaskConfig;
|
||||
use crate::task::info::State;
|
||||
use crate::task::RequestTask;
|
||||
|
||||
impl TaskManager {
|
||||
pub(crate) fn check_unload_sa(&self) -> bool {
|
||||
if !self.rx.is_empty() {
|
||||
return false;
|
||||
}
|
||||
|
||||
if !self.tasks.is_empty() && self.network_check_unload_sa() {
|
||||
return false;
|
||||
}
|
||||
|
||||
if self.recording_rdb_num.load(Ordering::SeqCst) != 0 {
|
||||
return false;
|
||||
}
|
||||
|
||||
if !self.rx.is_empty() {
|
||||
return false;
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
pub(crate) fn unload_sa(&mut self) -> bool {
|
||||
#[cfg(feature = "oh")]
|
||||
const REQUEST_SERVICE_ID: i32 = 3706;
|
||||
|
||||
if !self.check_unload_sa() {
|
||||
debug!("Triggers unload sa, but cannot unload now");
|
||||
return false;
|
||||
}
|
||||
|
||||
self.rx.close();
|
||||
|
||||
info!("unload SA");
|
||||
|
||||
if !self.tasks.is_empty() {
|
||||
self.record_all_task_config();
|
||||
}
|
||||
|
||||
#[cfg(feature = "oh")]
|
||||
let samgr_proxy = rust_samgr::get_systemability_manager();
|
||||
|
||||
// failed logic?
|
||||
#[cfg(feature = "oh")]
|
||||
let _ = samgr_proxy
|
||||
.unload_systemability(REQUEST_SERVICE_ID)
|
||||
.map_err(|e| error!("unload SA failed, err is {:?}", e));
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
pub(crate) fn restore_all_tasks(&mut self, recording_rdb_num: Arc<AtomicU32>) {
|
||||
if self.restoring {
|
||||
return;
|
||||
}
|
||||
|
||||
self.restoring = true;
|
||||
|
||||
if let Some(config_list) = self.query_all_task_config() {
|
||||
info!(
|
||||
"RSA query task config list len: {} in database",
|
||||
config_list.len()
|
||||
);
|
||||
for config in config_list.into_iter() {
|
||||
debug!("RSA query task config is {:?}", config);
|
||||
let uid = config.common_data.uid;
|
||||
let task_id = config.common_data.task_id;
|
||||
let token = config.token.clone();
|
||||
if let Some(task_info) = self.touch(uid, task_id, token) {
|
||||
let state = State::from(task_info.progress.common_data.state);
|
||||
if state != State::Waiting && state != State::Paused {
|
||||
continue;
|
||||
}
|
||||
let app_state = self.app_state(uid, &config.bundle);
|
||||
let request_task = RequestTask::restore_task(
|
||||
config,
|
||||
task_info,
|
||||
recording_rdb_num.clone(),
|
||||
AtomicBool::new(false),
|
||||
app_state,
|
||||
);
|
||||
let task = Arc::new(request_task);
|
||||
self.restore_task(task.clone());
|
||||
if unsafe { IsOnline() } {
|
||||
self.resume_waiting_task(task.clone());
|
||||
}
|
||||
}
|
||||
unsafe { CleanTaskConfigTable(task_id, uid) };
|
||||
}
|
||||
} else {
|
||||
self.schedule_unload_sa();
|
||||
}
|
||||
self.restoring = false;
|
||||
}
|
||||
|
||||
fn record_all_task_config(&mut self) {
|
||||
debug!("record all task config into database");
|
||||
self.recording_rdb_num.fetch_add(1, Ordering::SeqCst);
|
||||
for task in self.tasks.values() {
|
||||
if unsafe { HasTaskConfigRecord(task.conf.common_data.task_id) } {
|
||||
continue;
|
||||
}
|
||||
let state = task.status.lock().unwrap().state;
|
||||
|
||||
if state != State::Waiting && state != State::Paused {
|
||||
continue;
|
||||
}
|
||||
|
||||
let task_config = &task.conf;
|
||||
|
||||
let c_task_config =
|
||||
task_config.to_c_struct(task.conf.common_data.task_id, task.conf.common_data.uid);
|
||||
let ret = unsafe { RecordRequestTaskConfig(&c_task_config) };
|
||||
info!("insert taskConfig DB ret is {}", ret);
|
||||
}
|
||||
self.recording_rdb_num.fetch_sub(1, Ordering::SeqCst);
|
||||
}
|
||||
|
||||
fn restore_task(&mut self, task: Arc<RequestTask>) {
|
||||
if task.conf.version == Version::API10 {
|
||||
self.api10_background_task_count += 1;
|
||||
}
|
||||
let uid = task.conf.common_data.uid;
|
||||
let task_id = task.conf.common_data.task_id;
|
||||
if self.get_task(uid, task_id).is_some() {
|
||||
return;
|
||||
}
|
||||
|
||||
self.tasks.insert(task_id, task);
|
||||
|
||||
match self.app_task_map.get_mut(&uid) {
|
||||
Some(set) => {
|
||||
set.insert(task_id);
|
||||
}
|
||||
None => {
|
||||
let mut set = HashSet::new();
|
||||
set.insert(task_id);
|
||||
self.app_task_map.insert(uid, set);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn network_check_unload_sa(&self) -> bool {
|
||||
let mut need_unload = false;
|
||||
for task in self.tasks.values() {
|
||||
let state = task.status.lock().unwrap().state;
|
||||
if state == State::Completed
|
||||
|| state == State::Failed
|
||||
|| state == State::Removed
|
||||
|| state == State::Stopped
|
||||
|| ((state == State::Waiting || state == State::Paused)
|
||||
&& (!task.is_satisfied_configuration() || unsafe { !IsOnline() }))
|
||||
{
|
||||
need_unload = true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
need_unload
|
||||
}
|
||||
|
||||
pub(crate) fn query_all_task_config(&self) -> Option<Vec<TaskConfig>> {
|
||||
debug!("query all task config in database");
|
||||
let mut task_config_list: Vec<TaskConfig> = Vec::new();
|
||||
let c_config_list_len = unsafe { QueryTaskConfigLen() };
|
||||
if c_config_list_len <= 0 {
|
||||
debug!("no task config in database");
|
||||
return None;
|
||||
}
|
||||
let c_task_config_list = unsafe { QueryAllTaskConfig() };
|
||||
if c_task_config_list.is_null() {
|
||||
return None;
|
||||
}
|
||||
let c_task_config_ptrs =
|
||||
unsafe { std::slice::from_raw_parts(c_task_config_list, c_config_list_len as usize) };
|
||||
for c_task_config in c_task_config_ptrs.iter() {
|
||||
let task_config = TaskConfig::from_c_struct(unsafe { &**c_task_config });
|
||||
task_config_list.push(task_config);
|
||||
unsafe { DeleteCTaskConfig(*c_task_config) };
|
||||
}
|
||||
unsafe { DeleteCTaskConfigs(c_task_config_list) };
|
||||
Some(task_config_list)
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
pub(crate) fn DeleteCTaskConfigs(ptr: *const *const CTaskConfig);
|
||||
pub(crate) fn QueryAllTaskConfig() -> *const *const CTaskConfig;
|
||||
pub(crate) fn QueryTaskConfigLen() -> i32;
|
||||
|
||||
pub(crate) fn DeleteCTaskConfig(ptr: *const CTaskConfig);
|
||||
pub(crate) fn RecordRequestTaskConfig(taskConfig: *const CTaskConfig) -> bool;
|
||||
pub(crate) fn CleanTaskConfigTable(taskId: u32, uid: u64) -> bool;
|
||||
pub(crate) fn HasTaskConfigRecord(taskId: u32) -> bool;
|
||||
}
|
120
services/service/request/src/service/ability.rs
Normal file
120
services/service/request/src/service/ability.rs
Normal file
@ -0,0 +1,120 @@
|
||||
// Copyright (C) 2023 Huawei Device Co., Ltd.
|
||||
// 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.
|
||||
|
||||
// Copyright (C) 2023 Huawei Device Co., Ltd.
|
||||
// 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,
|
||||
// See the License for the specific language governing permissions and
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// limitations under the License.
|
||||
|
||||
//! Request ability services implementations.
|
||||
|
||||
use std::hint;
|
||||
use std::mem::MaybeUninit;
|
||||
use std::sync::atomic::{AtomicU8, Ordering};
|
||||
|
||||
use crate::manager::task_manager::TaskManagerEntry;
|
||||
use crate::manager::TaskManager;
|
||||
use crate::service::listener::{AppStateListener, NetworkChangeListener};
|
||||
use crate::service::notify::{NotifyEntry, NotifyManager};
|
||||
|
||||
static mut REQUEST_ABILITY: MaybeUninit<RequestAbility> = MaybeUninit::uninit();
|
||||
static STATE: AtomicU8 = AtomicU8::new(RequestAbility::NOT_INITED);
|
||||
|
||||
pub(crate) struct RequestAbility {
|
||||
manager: TaskManagerEntry,
|
||||
notify: NotifyEntry,
|
||||
app: AppStateListener,
|
||||
network: NetworkChangeListener,
|
||||
}
|
||||
|
||||
impl RequestAbility {
|
||||
const NOT_INITED: u8 = 0;
|
||||
const INITIALIZING: u8 = 1;
|
||||
const RUNNING: u8 = 2;
|
||||
const STOPPING: u8 = 3;
|
||||
const STOPPED: u8 = 4;
|
||||
|
||||
// `init` must have been called before calling `get_instance`.
|
||||
pub(crate) fn get_instance() -> &'static Self {
|
||||
loop {
|
||||
match STATE.load(Ordering::SeqCst) {
|
||||
Self::RUNNING | Self::STOPPED => return unsafe { &*REQUEST_ABILITY.as_ptr() },
|
||||
_ => hint::spin_loop(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn init() {
|
||||
if STATE
|
||||
.compare_exchange(
|
||||
Self::NOT_INITED,
|
||||
Self::INITIALIZING,
|
||||
Ordering::SeqCst,
|
||||
Ordering::SeqCst,
|
||||
)
|
||||
.is_ok()
|
||||
{
|
||||
unsafe {
|
||||
REQUEST_ABILITY.write(Self {
|
||||
manager: TaskManager::init(),
|
||||
notify: NotifyManager::init(),
|
||||
app: AppStateListener::init(),
|
||||
network: NetworkChangeListener::init(),
|
||||
});
|
||||
RequestInitServiceHandler();
|
||||
};
|
||||
STATE.store(Self::RUNNING, Ordering::SeqCst);
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn stop() {
|
||||
if STATE
|
||||
.compare_exchange(
|
||||
Self::RUNNING,
|
||||
Self::STOPPING,
|
||||
Ordering::SeqCst,
|
||||
Ordering::SeqCst,
|
||||
)
|
||||
.is_ok()
|
||||
{
|
||||
unsafe {
|
||||
let ability = REQUEST_ABILITY.assume_init_ref();
|
||||
// After entries shutdown, the `rx`s of these channels will be dropped.
|
||||
ability.notify.shutdown();
|
||||
ability.app.shutdown();
|
||||
ability.network.shutdown();
|
||||
};
|
||||
STATE.store(Self::STOPPED, Ordering::SeqCst);
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn notify() -> NotifyEntry {
|
||||
Self::get_instance().notify.clone()
|
||||
}
|
||||
|
||||
pub(crate) fn task_manager() -> TaskManagerEntry {
|
||||
Self::get_instance().manager.clone()
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
pub(crate) fn RequestInitServiceHandler();
|
||||
}
|
250
services/service/request/src/service/command/construct.rs
Normal file
250
services/service/request/src/service/command/construct.rs
Normal file
@ -0,0 +1,250 @@
|
||||
// Copyright (C) 2023 Huawei Device Co., Ltd.
|
||||
// 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.
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::fs::File;
|
||||
|
||||
use ipc_rust::{get_calling_uid, BorrowedMsgParcel, IMsgParcel, IpcResult, IpcStatusCode};
|
||||
|
||||
use crate::error::ErrorCode;
|
||||
use crate::manager::events::EventMessage;
|
||||
use crate::service::ability::RequestAbility;
|
||||
use crate::service::permission::PermissionChecker;
|
||||
use crate::service::{get_calling_bundle, open_file_readonly, open_file_readwrite};
|
||||
use crate::task::config::{Action, CommonTaskConfig, Network, TaskConfig, Version};
|
||||
use crate::task::info::Mode;
|
||||
use crate::utils::form_item::{FileSpec, FormItem};
|
||||
use crate::utils::generate_task_id;
|
||||
|
||||
pub(crate) struct Construct;
|
||||
|
||||
impl Construct {
|
||||
pub(crate) fn execute(
|
||||
data: &BorrowedMsgParcel,
|
||||
reply: &mut BorrowedMsgParcel,
|
||||
) -> IpcResult<()> {
|
||||
info!("Service construct");
|
||||
|
||||
if !PermissionChecker::check_internet() {
|
||||
error!("Service construct: no INTERNET permission");
|
||||
reply.write(&(ErrorCode::Permission as i32))?;
|
||||
return Err(IpcStatusCode::Failed);
|
||||
}
|
||||
|
||||
let action: u32 = data.read()?;
|
||||
let action: Action = Action::from(action as u8);
|
||||
|
||||
let version: u32 = data.read()?;
|
||||
let version: Version = Version::from(version as u8);
|
||||
|
||||
let mode: u32 = data.read()?;
|
||||
let mode: Mode = Mode::from(mode as u8);
|
||||
|
||||
let cover: bool = data.read()?;
|
||||
|
||||
let network: u32 = data.read()?;
|
||||
let network: Network = Network::from(network as u8);
|
||||
|
||||
let metered: bool = data.read()?;
|
||||
|
||||
let roaming: bool = data.read()?;
|
||||
|
||||
let retry: bool = data.read()?;
|
||||
|
||||
let redirect: bool = data.read()?;
|
||||
|
||||
let background: bool = data.read()?;
|
||||
|
||||
let index: u32 = data.read()?;
|
||||
|
||||
let begins: i64 = data.read()?;
|
||||
|
||||
let ends: i64 = data.read()?;
|
||||
|
||||
let gauge: bool = data.read()?;
|
||||
|
||||
let precise: bool = data.read()?;
|
||||
|
||||
let priority: u32 = data.read()?;
|
||||
|
||||
let url: String = data.read()?;
|
||||
|
||||
let title: String = data.read()?;
|
||||
|
||||
let method: String = data.read()?;
|
||||
|
||||
let token: String = data.read()?;
|
||||
|
||||
let description: String = data.read()?;
|
||||
|
||||
let data_base: String = data.read()?;
|
||||
|
||||
let bundle = get_calling_bundle();
|
||||
// Creates task_id here, move it to task_manager later?
|
||||
let task_id = generate_task_id();
|
||||
let uid = get_calling_uid();
|
||||
|
||||
let mut form_items = Vec::new();
|
||||
let form_size: u32 = data.read()?;
|
||||
if form_size > data.get_readable_bytes() {
|
||||
error!("Service construct: form_size too large");
|
||||
reply.write(&(ErrorCode::IpcSizeTooLarge as i32))?;
|
||||
return Err(IpcStatusCode::Failed);
|
||||
}
|
||||
for _ in 0..form_size {
|
||||
let name: String = data.read()?;
|
||||
let value: String = data.read()?;
|
||||
form_items.push(FormItem { name, value });
|
||||
}
|
||||
|
||||
let mut files = Vec::<File>::new();
|
||||
let mut file_specs: Vec<FileSpec> = Vec::new();
|
||||
let file_size: u32 = data.read()?;
|
||||
if file_size > data.get_readable_bytes() {
|
||||
error!("Service construct: file_specs size too large");
|
||||
reply.write(&(ErrorCode::IpcSizeTooLarge as i32))?;
|
||||
return Err(IpcStatusCode::Failed);
|
||||
}
|
||||
for _ in 0..file_size {
|
||||
let name: String = data.read()?;
|
||||
let path: String = data.read()?;
|
||||
let file_name: String = data.read()?;
|
||||
let mime_type: String = data.read()?;
|
||||
if action == Action::UpLoad {
|
||||
let file = open_file_readonly(uid, &bundle, &path)?;
|
||||
files.push(file);
|
||||
} else {
|
||||
let file = open_file_readwrite(uid, &bundle, &path)?;
|
||||
files.push(file);
|
||||
}
|
||||
let _fd_error: i32 = data.read()?;
|
||||
file_specs.push(FileSpec {
|
||||
name,
|
||||
path,
|
||||
file_name,
|
||||
mime_type,
|
||||
});
|
||||
}
|
||||
|
||||
// Response bodies fd.
|
||||
let body_file_size: u32 = data.read()?;
|
||||
if body_file_size > data.get_readable_bytes() {
|
||||
error!("Service construct: body_file size too large");
|
||||
reply.write(&(ErrorCode::IpcSizeTooLarge as i32))?;
|
||||
return Err(IpcStatusCode::Failed);
|
||||
}
|
||||
let mut body_files = Vec::new();
|
||||
let mut body_file_names: Vec<String> = Vec::new();
|
||||
for _ in 0..body_file_size {
|
||||
let file_name: String = data.read()?;
|
||||
let body_file = open_file_readwrite(uid, &bundle, &file_name)?;
|
||||
body_file_names.push(file_name);
|
||||
body_files.push(body_file);
|
||||
}
|
||||
|
||||
let header_size: u32 = data.read()?;
|
||||
if header_size > data.get_readable_bytes() {
|
||||
error!("Service construct: header size too large");
|
||||
reply.write(&(ErrorCode::IpcSizeTooLarge as i32))?;
|
||||
return Err(IpcStatusCode::Failed);
|
||||
}
|
||||
let mut headers: HashMap<String, String> = HashMap::new();
|
||||
for _ in 0..header_size {
|
||||
let key: String = data.read()?;
|
||||
let value: String = data.read()?;
|
||||
headers.insert(key, value);
|
||||
}
|
||||
|
||||
let extras_size: u32 = data.read()?;
|
||||
if extras_size > data.get_readable_bytes() {
|
||||
error!("Service construct: extras size too large");
|
||||
reply.write(&(ErrorCode::IpcSizeTooLarge as i32))?;
|
||||
return Err(IpcStatusCode::Failed);
|
||||
}
|
||||
let mut extras: HashMap<String, String> = HashMap::new();
|
||||
for _ in 0..extras_size {
|
||||
let key: String = data.read()?;
|
||||
let value: String = data.read()?;
|
||||
extras.insert(key, value);
|
||||
}
|
||||
|
||||
let task_config = TaskConfig {
|
||||
bundle,
|
||||
url,
|
||||
title,
|
||||
description,
|
||||
method,
|
||||
headers,
|
||||
data: data_base,
|
||||
token,
|
||||
extras,
|
||||
version,
|
||||
form_items,
|
||||
file_specs,
|
||||
body_file_names,
|
||||
common_data: CommonTaskConfig {
|
||||
task_id,
|
||||
uid,
|
||||
action,
|
||||
mode,
|
||||
cover,
|
||||
network,
|
||||
metered,
|
||||
roaming,
|
||||
retry,
|
||||
redirect,
|
||||
index,
|
||||
begins: begins as u64,
|
||||
ends,
|
||||
gauge,
|
||||
precise,
|
||||
priority,
|
||||
background,
|
||||
},
|
||||
};
|
||||
|
||||
debug!("Service construct: task_config constructed");
|
||||
debug!("Service construct: target files {:?}", files);
|
||||
|
||||
let (event, rx) = EventMessage::construct(task_config, files, body_files);
|
||||
if !RequestAbility::task_manager().send_event(event) {
|
||||
return Err(IpcStatusCode::Failed);
|
||||
}
|
||||
let ret = match rx.get() {
|
||||
Some(ret) => ret,
|
||||
None => {
|
||||
error!("Service construct: receives ret failed");
|
||||
return Err(IpcStatusCode::Failed);
|
||||
}
|
||||
};
|
||||
|
||||
debug!("Service construct: construct event sent to manager");
|
||||
|
||||
if version != Version::API10 {
|
||||
let (event, _) = EventMessage::start(uid, task_id);
|
||||
if !RequestAbility::task_manager().send_event(event) {
|
||||
return Err(IpcStatusCode::Failed);
|
||||
}
|
||||
debug!("Service construct: start event sent to manager");
|
||||
}
|
||||
|
||||
reply.write(&(ret as i32))?;
|
||||
if ret != ErrorCode::ErrOk {
|
||||
error!("Service construct: construct task failed");
|
||||
return Err(IpcStatusCode::Failed);
|
||||
}
|
||||
debug!("Service construct: task id {}", task_id);
|
||||
reply.write(&(task_id as i32))?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
143
services/service/request/src/service/command/dump.rs
Normal file
143
services/service/request/src/service/command/dump.rs
Normal file
@ -0,0 +1,143 @@
|
||||
// Copyright (C) 2023 Huawei Device Co., Ltd.
|
||||
// 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.
|
||||
|
||||
use std::io::Write;
|
||||
|
||||
use ipc_rust::{FileDesc, IpcStatusCode, String16};
|
||||
|
||||
use crate::manager::events::EventMessage;
|
||||
use crate::service::ability::RequestAbility;
|
||||
|
||||
const HELP_MSG: &str = "usage:\n\
|
||||
-h help text for the tool\n\
|
||||
-t [taskid] without taskid: display all task summary info; \
|
||||
taskid: display one task detail info\n";
|
||||
|
||||
pub(crate) struct Dump;
|
||||
|
||||
impl Dump {
|
||||
// Ignores all the file error.
|
||||
pub(crate) fn execute(file: &FileDesc, args: &mut Vec<String16>) -> i32 {
|
||||
info!("Service dump");
|
||||
|
||||
let len = args.len();
|
||||
if len == 0 || args[0].get_string().eq("-h") {
|
||||
let _ = file.as_ref().write(HELP_MSG.as_bytes());
|
||||
return IpcStatusCode::Ok as i32;
|
||||
}
|
||||
|
||||
if !args[0].get_string().eq("-t") {
|
||||
let _ = file.as_ref().write("invalid args".as_bytes());
|
||||
return IpcStatusCode::Ok as i32;
|
||||
}
|
||||
|
||||
match len {
|
||||
1 => dump_all_task_info(file),
|
||||
2 => {
|
||||
let task_id = args[1].get_string().parse::<u32>();
|
||||
match task_id {
|
||||
Ok(id) => dump_one_task_info(file, id),
|
||||
Err(_) => {
|
||||
let _ = file.as_ref().write("-t accept a number".as_bytes());
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
let _ = file
|
||||
.as_ref()
|
||||
.write("too many args, -t accept no arg or one arg".as_bytes());
|
||||
}
|
||||
}
|
||||
IpcStatusCode::Ok as i32
|
||||
}
|
||||
}
|
||||
|
||||
fn dump_all_task_info(file: &FileDesc) {
|
||||
info!("Service dump: dump all task info");
|
||||
|
||||
let (event, rx) = EventMessage::dump_all();
|
||||
if !RequestAbility::task_manager().send_event(event) {
|
||||
return;
|
||||
}
|
||||
|
||||
let infos = match rx.get() {
|
||||
Some(infos) => infos,
|
||||
None => {
|
||||
error!("Service dump: receives infos failed");
|
||||
return;
|
||||
}
|
||||
};
|
||||
let len = infos.vec.len();
|
||||
let mut file = file.as_ref();
|
||||
let _ = file.write(format!("task num: {}\n", len).as_bytes());
|
||||
if len > 0 {
|
||||
let _ = file.write(
|
||||
format!(
|
||||
"{:<20}{:<12}{:<12}{:<12}\n",
|
||||
"id", "action", "state", "reason"
|
||||
)
|
||||
.as_bytes(),
|
||||
);
|
||||
for info in infos.vec.iter() {
|
||||
let _ = file.write(
|
||||
format!(
|
||||
"{:<20}{:<12}{:<12}{:<12}\n",
|
||||
info.task_id, info.action as u8, info.state as u8, info.reason as u8
|
||||
)
|
||||
.as_bytes(),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn dump_one_task_info(file: &FileDesc, task_id: u32) {
|
||||
info!("Service dump: dump one task info");
|
||||
|
||||
let (event, rx) = EventMessage::dump_one(task_id);
|
||||
if !RequestAbility::task_manager().send_event(event) {
|
||||
return;
|
||||
}
|
||||
let task = match rx.get() {
|
||||
Some(task) => task,
|
||||
None => {
|
||||
error!("Service dump: receives task failed");
|
||||
return;
|
||||
}
|
||||
};
|
||||
let mut file = file.as_ref();
|
||||
|
||||
if let Some(task) = task {
|
||||
let _ = file.write(
|
||||
format!(
|
||||
"{:<20}{:<12}{:<12}{:<12}{:<12}{:<12}{}\n",
|
||||
"id", "action", "state", "reason", "total_size", "tran_size", "url"
|
||||
)
|
||||
.as_bytes(),
|
||||
);
|
||||
let _ = file.write(
|
||||
format!(
|
||||
"{:<20}{:<12}{:<12}{:<12}{:<12}{:<12}{}\n",
|
||||
task.task_id,
|
||||
task.action as u8,
|
||||
task.state as u8,
|
||||
task.reason as u8,
|
||||
task.total_size,
|
||||
task.tran_size,
|
||||
task.url
|
||||
)
|
||||
.as_bytes(),
|
||||
);
|
||||
} else {
|
||||
let _ = file.write(format!("invalid task id {}", task_id).as_bytes());
|
||||
}
|
||||
}
|
42
services/service/request/src/service/command/mod.rs
Normal file
42
services/service/request/src/service/command/mod.rs
Normal file
@ -0,0 +1,42 @@
|
||||
// Copyright (C) 2023 Huawei Device Co., Ltd.
|
||||
// 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.
|
||||
|
||||
mod construct;
|
||||
mod dump;
|
||||
mod off;
|
||||
mod on;
|
||||
mod pause;
|
||||
mod query;
|
||||
mod query_mime_type;
|
||||
mod remove;
|
||||
mod resume;
|
||||
mod search;
|
||||
mod show;
|
||||
mod start;
|
||||
mod stop;
|
||||
mod touch;
|
||||
|
||||
pub(crate) use construct::Construct;
|
||||
pub(crate) use dump::Dump;
|
||||
pub(crate) use off::Off;
|
||||
pub(crate) use on::On;
|
||||
pub(crate) use pause::Pause;
|
||||
pub(crate) use query::Query;
|
||||
pub(crate) use query_mime_type::QueryMimeType;
|
||||
pub(crate) use remove::Remove;
|
||||
pub(crate) use resume::Resume;
|
||||
pub(crate) use search::Search;
|
||||
pub(crate) use show::Show;
|
||||
pub(crate) use start::Start;
|
||||
pub(crate) use stop::Stop;
|
||||
pub(crate) use touch::Touch;
|
68
services/service/request/src/service/command/off.rs
Normal file
68
services/service/request/src/service/command/off.rs
Normal file
@ -0,0 +1,68 @@
|
||||
// Copyright (C) 2023 Huawei Device Co., Ltd.
|
||||
// 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.
|
||||
|
||||
use ipc_rust::{BorrowedMsgParcel, IpcResult, IpcStatusCode};
|
||||
|
||||
use crate::error::ErrorCode;
|
||||
use crate::service::ability::RequestAbility;
|
||||
use crate::service::notify::{Event, NotifyEvent};
|
||||
|
||||
pub(crate) struct Off;
|
||||
|
||||
impl Off {
|
||||
pub(crate) fn execute(
|
||||
data: &BorrowedMsgParcel,
|
||||
reply: &mut BorrowedMsgParcel,
|
||||
) -> IpcResult<()> {
|
||||
info!("Service off");
|
||||
let off_type: String = data.read()?;
|
||||
debug!("Service off: off_type {:?}", off_type);
|
||||
|
||||
let event = match Event::try_from(off_type) {
|
||||
Ok(event) => event,
|
||||
Err(_) => {
|
||||
error!("Service off: off_type not valid");
|
||||
reply.write(&(ErrorCode::ParameterCheck as i32))?;
|
||||
return Err(IpcStatusCode::Failed);
|
||||
}
|
||||
};
|
||||
let id: String = data.read()?;
|
||||
debug!("Service off: task_id {}", id);
|
||||
match id.parse::<u32>() {
|
||||
Ok(id) => {
|
||||
debug!("Service off: u32 task_id is {:?}", id);
|
||||
let (event, rx) = NotifyEvent::off(event, id);
|
||||
RequestAbility::notify().send_event(event);
|
||||
|
||||
let ret = match rx.get() {
|
||||
Some(ret) => ret,
|
||||
None => {
|
||||
error!("Service off: receives ret failed");
|
||||
return Err(IpcStatusCode::Failed);
|
||||
}
|
||||
};
|
||||
reply.write(&(ret as i32))?;
|
||||
if ret != ErrorCode::ErrOk {
|
||||
error!("Service off: off failed for ret is {}", ret as i32);
|
||||
return Err(IpcStatusCode::Failed);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
_ => {
|
||||
error!("Service off: task_id not valid");
|
||||
reply.write(&(ErrorCode::TaskNotFound as i32))?;
|
||||
Err(IpcStatusCode::Failed)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
69
services/service/request/src/service/command/on.rs
Normal file
69
services/service/request/src/service/command/on.rs
Normal file
@ -0,0 +1,69 @@
|
||||
// Copyright (C) 2023 Huawei Device Co., Ltd.
|
||||
// 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.
|
||||
|
||||
use ipc_rust::{BorrowedMsgParcel, IpcResult, IpcStatusCode, RemoteObj};
|
||||
|
||||
use crate::error::ErrorCode;
|
||||
use crate::service::ability::RequestAbility;
|
||||
use crate::service::notify::{Event, NotifyEvent};
|
||||
|
||||
pub(crate) struct On;
|
||||
|
||||
impl On {
|
||||
pub(crate) fn execute(
|
||||
data: &BorrowedMsgParcel,
|
||||
reply: &mut BorrowedMsgParcel,
|
||||
) -> IpcResult<()> {
|
||||
info!("Service on");
|
||||
let on_type: String = data.read()?;
|
||||
debug!("Service on: on_type is {:?}", on_type);
|
||||
|
||||
let event = match Event::try_from(on_type) {
|
||||
Ok(event) => event,
|
||||
Err(_) => {
|
||||
error!("Service on: on_type not valid");
|
||||
reply.write(&(ErrorCode::ParameterCheck as i32))?;
|
||||
return Err(IpcStatusCode::Failed);
|
||||
}
|
||||
};
|
||||
let id: String = data.read()?;
|
||||
debug!("Service on: task_id is {}", id);
|
||||
match id.parse::<u32>() {
|
||||
Ok(id) => {
|
||||
debug!("Service on: u32 task_id is {}", id);
|
||||
let obj: RemoteObj = data.read::<RemoteObj>()?;
|
||||
let (event, rx) = NotifyEvent::on(event, id, obj);
|
||||
RequestAbility::notify().send_event(event);
|
||||
|
||||
let ret = match rx.get() {
|
||||
Some(ret) => ret,
|
||||
None => {
|
||||
error!("Service on: receives ret failed");
|
||||
return Err(IpcStatusCode::Failed);
|
||||
}
|
||||
};
|
||||
reply.write(&(ret as i32))?;
|
||||
if ret != ErrorCode::ErrOk {
|
||||
error!("Service on: on failed for ret is {}", ret as i32);
|
||||
return Err(IpcStatusCode::Failed);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
_ => {
|
||||
error!("Service on: task_id not valid");
|
||||
reply.write(&(ErrorCode::TaskNotFound as i32))?;
|
||||
Err(IpcStatusCode::Failed)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
72
services/service/request/src/service/command/pause.rs
Normal file
72
services/service/request/src/service/command/pause.rs
Normal file
@ -0,0 +1,72 @@
|
||||
// Copyright (C) 2023 Huawei Device Co., Ltd.
|
||||
// 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.
|
||||
|
||||
use ipc_rust::{get_calling_uid, BorrowedMsgParcel, IpcResult, IpcStatusCode};
|
||||
|
||||
use crate::error::ErrorCode;
|
||||
use crate::manager::events::EventMessage;
|
||||
use crate::service::ability::RequestAbility;
|
||||
use crate::service::permission::PermissionChecker;
|
||||
use crate::task::config::Version;
|
||||
|
||||
pub(crate) struct Pause;
|
||||
|
||||
impl Pause {
|
||||
pub(crate) fn execute(
|
||||
data: &BorrowedMsgParcel,
|
||||
reply: &mut BorrowedMsgParcel,
|
||||
) -> IpcResult<()> {
|
||||
info!("Service pause");
|
||||
let version: u32 = data.read()?;
|
||||
debug!("Service pause: version {}", version);
|
||||
if Version::from(version as u8) == Version::API9 && !PermissionChecker::check_internet() {
|
||||
error!("Service pause: no INTERNET permission");
|
||||
reply.write(&(ErrorCode::Permission as i32))?;
|
||||
return Err(IpcStatusCode::Failed);
|
||||
}
|
||||
|
||||
let id: String = data.read()?;
|
||||
debug!("Service pause: task_id is {}", id);
|
||||
match id.parse::<u32>() {
|
||||
Ok(id) => {
|
||||
debug!("Service pause: u32 task_id is {}", id);
|
||||
|
||||
let uid = get_calling_uid();
|
||||
debug!("Service pause: uid is {}", uid);
|
||||
|
||||
let (event, rx) = EventMessage::pause(uid, id);
|
||||
if !RequestAbility::task_manager().send_event(event) {
|
||||
return Err(IpcStatusCode::Failed);
|
||||
}
|
||||
let ret = match rx.get() {
|
||||
Some(ret) => ret,
|
||||
None => {
|
||||
error!("Service pause: receives ret failed");
|
||||
return Err(IpcStatusCode::Failed);
|
||||
}
|
||||
};
|
||||
reply.write(&(ret as i32))?;
|
||||
if ret != ErrorCode::ErrOk {
|
||||
error!("Service pause: pause fail for ret is {}", ret as u32);
|
||||
return Err(IpcStatusCode::Failed);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
_ => {
|
||||
error!("Service pause: task_id not valid");
|
||||
reply.write(&(ErrorCode::TaskNotFound as i32))?;
|
||||
Err(IpcStatusCode::Failed)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
82
services/service/request/src/service/command/query.rs
Normal file
82
services/service/request/src/service/command/query.rs
Normal file
@ -0,0 +1,82 @@
|
||||
// Copyright (C) 2023 Huawei Device Co., Ltd.
|
||||
// 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.
|
||||
|
||||
use ipc_rust::{BorrowedMsgParcel, IpcResult, IpcStatusCode};
|
||||
|
||||
use crate::error::ErrorCode;
|
||||
use crate::manager::events::EventMessage;
|
||||
use crate::service::ability::RequestAbility;
|
||||
use crate::service::permission::{PermissionChecker, QueryPermission};
|
||||
use crate::service::{is_system_api, serialize_task_info};
|
||||
use crate::task::config::Action;
|
||||
|
||||
pub(crate) struct Query;
|
||||
|
||||
impl Query {
|
||||
pub(crate) fn execute(
|
||||
data: &BorrowedMsgParcel,
|
||||
reply: &mut BorrowedMsgParcel,
|
||||
) -> IpcResult<()> {
|
||||
info!("Service query");
|
||||
if !is_system_api() {
|
||||
error!("Service query: not system api");
|
||||
reply.write(&(ErrorCode::SystemApi as i32))?;
|
||||
return Err(IpcStatusCode::Failed);
|
||||
}
|
||||
let permission = PermissionChecker::check_query();
|
||||
let action = match permission {
|
||||
QueryPermission::NoPermission => {
|
||||
error!("Service query: no QUERY permission");
|
||||
reply.write(&(ErrorCode::Permission as i32))?;
|
||||
return Err(IpcStatusCode::Failed);
|
||||
}
|
||||
QueryPermission::QueryDownLoad => Action::DownLoad,
|
||||
QueryPermission::QueryUpload => Action::UpLoad,
|
||||
QueryPermission::QueryAll => Action::Any,
|
||||
};
|
||||
|
||||
let id: String = data.read()?;
|
||||
debug!("Service query: task_id is {}", id);
|
||||
match id.parse::<u32>() {
|
||||
Ok(id) => {
|
||||
debug!("Service query: u32 task_id is {}", id);
|
||||
let (event, rx) = EventMessage::query(id, action);
|
||||
if !RequestAbility::task_manager().send_event(event) {
|
||||
return Err(IpcStatusCode::Failed);
|
||||
}
|
||||
match rx.get() {
|
||||
Some(Some(info)) => {
|
||||
reply.write(&(ErrorCode::ErrOk as i32))?;
|
||||
debug!("Service query: task_info - {:?}", info);
|
||||
serialize_task_info(info, reply)?;
|
||||
Ok(())
|
||||
}
|
||||
Some(None) => {
|
||||
error!("Service query: task_id not found");
|
||||
reply.write(&(ErrorCode::TaskNotFound as i32))?;
|
||||
Err(IpcStatusCode::Failed)
|
||||
}
|
||||
None => {
|
||||
error!("Service query: receives task_info failed");
|
||||
Err(IpcStatusCode::Failed)
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
error!("Service query: task_id not valid");
|
||||
reply.write(&(ErrorCode::TaskNotFound as i32))?;
|
||||
Err(IpcStatusCode::Failed)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
// Copyright (C) 2023 Huawei Device Co., Ltd.
|
||||
// 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.
|
||||
|
||||
use ipc_rust::{get_calling_uid, BorrowedMsgParcel, IpcResult, IpcStatusCode};
|
||||
|
||||
use crate::error::ErrorCode;
|
||||
use crate::manager::events::EventMessage;
|
||||
use crate::service::ability::RequestAbility;
|
||||
use crate::service::permission::PermissionChecker;
|
||||
|
||||
pub(crate) struct QueryMimeType;
|
||||
|
||||
impl QueryMimeType {
|
||||
pub(crate) fn execute(
|
||||
data: &BorrowedMsgParcel,
|
||||
reply: &mut BorrowedMsgParcel,
|
||||
) -> IpcResult<()> {
|
||||
info!("Service query mime type");
|
||||
if !PermissionChecker::check_internet() {
|
||||
error!("Service query mime type: no INTERNET permission");
|
||||
reply.write(&(ErrorCode::Permission as i32))?;
|
||||
return Err(IpcStatusCode::Failed);
|
||||
}
|
||||
let id: String = data.read()?;
|
||||
debug!("Service query mime type: task_id is {}", id);
|
||||
match id.parse::<u32>() {
|
||||
Ok(id) => {
|
||||
debug!("Service query mime type: u32 task_id is {}", id);
|
||||
|
||||
let uid = get_calling_uid();
|
||||
debug!("Service query mime type: uid is {}", uid);
|
||||
|
||||
let (event, rx) = EventMessage::query_mime_type(uid, id);
|
||||
if !RequestAbility::task_manager().send_event(event) {
|
||||
return Err(IpcStatusCode::Failed);
|
||||
}
|
||||
let mime = match rx.get() {
|
||||
Some(mime) => mime,
|
||||
None => {
|
||||
error!("Service query mime type: receives mime failed");
|
||||
return Err(IpcStatusCode::Failed);
|
||||
}
|
||||
};
|
||||
debug!("Service query mime type: {}", mime);
|
||||
reply.write(&(ErrorCode::ErrOk as i32))?;
|
||||
reply.write(&mime)?;
|
||||
Ok(())
|
||||
}
|
||||
_ => {
|
||||
error!("Service query mime type: task_id not valid");
|
||||
reply.write(&(ErrorCode::TaskNotFound as i32))?;
|
||||
Err(IpcStatusCode::Failed)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
69
services/service/request/src/service/command/remove.rs
Normal file
69
services/service/request/src/service/command/remove.rs
Normal file
@ -0,0 +1,69 @@
|
||||
// Copyright (C) 2023 Huawei Device Co., Ltd.
|
||||
// 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.
|
||||
|
||||
use ipc_rust::{get_calling_uid, BorrowedMsgParcel, IpcResult, IpcStatusCode};
|
||||
|
||||
use crate::error::ErrorCode;
|
||||
use crate::manager::events::EventMessage;
|
||||
use crate::service::ability::RequestAbility;
|
||||
use crate::service::permission::PermissionChecker;
|
||||
use crate::task::config::Version;
|
||||
|
||||
pub(crate) struct Remove;
|
||||
|
||||
impl Remove {
|
||||
pub(crate) fn execute(
|
||||
data: &BorrowedMsgParcel,
|
||||
reply: &mut BorrowedMsgParcel,
|
||||
) -> IpcResult<()> {
|
||||
info!("Service remove");
|
||||
let version: u32 = data.read()?;
|
||||
if Version::from(version as u8) == Version::API9 && !PermissionChecker::check_internet() {
|
||||
error!("Service remove: no INTERNET permission");
|
||||
reply.write(&(ErrorCode::Permission as i32))?;
|
||||
return Err(IpcStatusCode::Failed);
|
||||
}
|
||||
|
||||
let id: String = data.read()?;
|
||||
debug!("Service remove: task_id is {}", id);
|
||||
match id.parse::<u32>() {
|
||||
Ok(id) => {
|
||||
debug!("Service remove: u32 task_id is {}", id);
|
||||
let uid = get_calling_uid();
|
||||
debug!("Service remove: uid is {}", uid);
|
||||
let (event, rx) = EventMessage::remove(uid, id);
|
||||
if !RequestAbility::task_manager().send_event(event) {
|
||||
return Err(IpcStatusCode::Failed);
|
||||
}
|
||||
let ret = match rx.get() {
|
||||
Some(ret) => ret,
|
||||
None => {
|
||||
error!("Service remove: receives ret failed");
|
||||
return Err(IpcStatusCode::Failed);
|
||||
}
|
||||
};
|
||||
reply.write(&(ret as i32))?;
|
||||
if ret != ErrorCode::ErrOk {
|
||||
error!("Service remove: remove failed for ret is {}", ret as i32);
|
||||
return Err(IpcStatusCode::Failed);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
_ => {
|
||||
error!("Service remove: task_id not valid");
|
||||
reply.write(&(ErrorCode::TaskNotFound as i32))?;
|
||||
Err(IpcStatusCode::Failed)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
67
services/service/request/src/service/command/resume.rs
Normal file
67
services/service/request/src/service/command/resume.rs
Normal file
@ -0,0 +1,67 @@
|
||||
// Copyright (C) 2023 Huawei Device Co., Ltd.
|
||||
// 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.
|
||||
|
||||
use ipc_rust::{get_calling_uid, BorrowedMsgParcel, IpcResult, IpcStatusCode};
|
||||
|
||||
use crate::error::ErrorCode;
|
||||
use crate::manager::events::EventMessage;
|
||||
use crate::service::ability::RequestAbility;
|
||||
use crate::service::permission::PermissionChecker;
|
||||
|
||||
pub(crate) struct Resume;
|
||||
|
||||
impl Resume {
|
||||
pub(crate) fn execute(
|
||||
data: &BorrowedMsgParcel,
|
||||
reply: &mut BorrowedMsgParcel,
|
||||
) -> IpcResult<()> {
|
||||
info!("Service resume");
|
||||
if !PermissionChecker::check_internet() {
|
||||
error!("Service resume: no INTERNET permission");
|
||||
reply.write(&(ErrorCode::Permission as i32))?;
|
||||
return Err(IpcStatusCode::Failed);
|
||||
}
|
||||
|
||||
let id: String = data.read()?;
|
||||
debug!("Service resume: task_id is {}", id);
|
||||
match id.parse::<u32>() {
|
||||
Ok(id) => {
|
||||
debug!("Service resume: u32 task_id is {}", id);
|
||||
let uid = get_calling_uid();
|
||||
debug!("Service resume: uid is {}", uid);
|
||||
let (event, rx) = EventMessage::resume(uid, id);
|
||||
if !RequestAbility::task_manager().send_event(event) {
|
||||
return Err(IpcStatusCode::Failed);
|
||||
}
|
||||
let ret = match rx.get() {
|
||||
Some(ret) => ret,
|
||||
None => {
|
||||
error!("Service resume: receives ret failed");
|
||||
return Err(IpcStatusCode::Failed);
|
||||
}
|
||||
};
|
||||
reply.write(&(ret as i32))?;
|
||||
if ret != ErrorCode::ErrOk {
|
||||
error!("Service resume: resume failed for ret is {}", ret as i32);
|
||||
return Err(IpcStatusCode::Failed);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
_ => {
|
||||
error!("Service resume: task_id not valid");
|
||||
reply.write(&(ErrorCode::TaskNotFound as i32))?;
|
||||
Err(IpcStatusCode::Failed)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
75
services/service/request/src/service/command/search.rs
Normal file
75
services/service/request/src/service/command/search.rs
Normal file
@ -0,0 +1,75 @@
|
||||
// Copyright (C) 2023 Huawei Device Co., Ltd.
|
||||
// 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.
|
||||
|
||||
use ipc_rust::{BorrowedMsgParcel, IpcResult, IpcStatusCode};
|
||||
|
||||
use crate::manager::events::EventMessage;
|
||||
use crate::service::ability::RequestAbility;
|
||||
use crate::service::{get_calling_bundle, is_system_api};
|
||||
use crate::utils::filter::{CommonFilter, Filter};
|
||||
|
||||
pub(crate) struct Search;
|
||||
|
||||
impl Search {
|
||||
pub(crate) fn execute(
|
||||
data: &BorrowedMsgParcel,
|
||||
reply: &mut BorrowedMsgParcel,
|
||||
) -> IpcResult<()> {
|
||||
info!("Service search");
|
||||
let mut bundle: String = data.read()?;
|
||||
if !is_system_api() {
|
||||
debug!("Service search: not system api");
|
||||
bundle = get_calling_bundle();
|
||||
debug!("Service search: bundle change: {}", bundle);
|
||||
}
|
||||
debug!("Service search: bundle is {}", bundle);
|
||||
let before: i64 = data.read()?;
|
||||
debug!("Service search: before is {}", before);
|
||||
let after: i64 = data.read()?;
|
||||
debug!("Service search: after is {}", after);
|
||||
let state: u32 = data.read()?;
|
||||
debug!("Service search: state is {}", state);
|
||||
let action: u32 = data.read()?;
|
||||
debug!("Service search: action is {}", action);
|
||||
let mode: u32 = data.read()?;
|
||||
debug!("Service search: mode is {}", mode);
|
||||
let common_data = CommonFilter {
|
||||
before,
|
||||
after,
|
||||
state: state as u8,
|
||||
action: action as u8,
|
||||
mode: mode as u8,
|
||||
};
|
||||
let filter = Filter {
|
||||
bundle,
|
||||
common_data,
|
||||
};
|
||||
let (event, rx) = EventMessage::search(filter);
|
||||
if !RequestAbility::task_manager().send_event(event) {
|
||||
return Err(IpcStatusCode::Failed);
|
||||
}
|
||||
let ids = match rx.get() {
|
||||
Some(ids) => ids,
|
||||
None => {
|
||||
error!("Service search: receives ids failed");
|
||||
return Err(IpcStatusCode::Failed);
|
||||
}
|
||||
};
|
||||
debug!("Service search: search task ids is {:?}", ids);
|
||||
reply.write(&(ids.len() as u32))?;
|
||||
for it in ids.iter() {
|
||||
reply.write(&(it.to_string()))?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
72
services/service/request/src/service/command/show.rs
Normal file
72
services/service/request/src/service/command/show.rs
Normal file
@ -0,0 +1,72 @@
|
||||
// Copyright (C) 2023 Huawei Device Co., Ltd.
|
||||
// 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.
|
||||
|
||||
use ipc_rust::{get_calling_uid, BorrowedMsgParcel, IpcResult, IpcStatusCode};
|
||||
|
||||
use crate::error::ErrorCode;
|
||||
use crate::manager::events::EventMessage;
|
||||
use crate::service::ability::RequestAbility;
|
||||
use crate::service::permission::PermissionChecker;
|
||||
use crate::service::serialize_task_info;
|
||||
|
||||
pub(crate) struct Show;
|
||||
|
||||
impl Show {
|
||||
pub(crate) fn execute(
|
||||
data: &BorrowedMsgParcel,
|
||||
reply: &mut BorrowedMsgParcel,
|
||||
) -> IpcResult<()> {
|
||||
info!("Service show");
|
||||
if !PermissionChecker::check_internet() {
|
||||
error!("Service show: no INTERNET permission");
|
||||
reply.write(&(ErrorCode::Permission as i32))?;
|
||||
return Err(IpcStatusCode::Failed);
|
||||
}
|
||||
let id: String = data.read()?;
|
||||
debug!("Service show: task_id is {}", id);
|
||||
match id.parse::<u32>() {
|
||||
Ok(id) => {
|
||||
debug!("Service show: u32 task_id is {}", id);
|
||||
let uid = get_calling_uid();
|
||||
debug!("Service show: uid is {}", uid);
|
||||
|
||||
let (event, rx) = EventMessage::show(uid, id);
|
||||
if !RequestAbility::task_manager().send_event(event) {
|
||||
return Err(IpcStatusCode::Failed);
|
||||
}
|
||||
match rx.get() {
|
||||
Some(Some(info)) => {
|
||||
reply.write(&(ErrorCode::ErrOk as i32))?;
|
||||
debug!("Service show: task_info {:?}", info);
|
||||
serialize_task_info(info, reply)?;
|
||||
Ok(())
|
||||
}
|
||||
Some(None) => {
|
||||
error!("Service show: task_id not found");
|
||||
reply.write(&(ErrorCode::TaskNotFound as i32))?;
|
||||
Err(IpcStatusCode::Failed)
|
||||
}
|
||||
None => {
|
||||
error!("Service show: receives task_info failed");
|
||||
Err(IpcStatusCode::Failed)
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
error!("Service show: task_id not valid");
|
||||
reply.write(&(ErrorCode::TaskNotFound as i32))?;
|
||||
Err(IpcStatusCode::Failed)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
68
services/service/request/src/service/command/start.rs
Normal file
68
services/service/request/src/service/command/start.rs
Normal file
@ -0,0 +1,68 @@
|
||||
// Copyright (C) 2023 Huawei Device Co., Ltd.
|
||||
// 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.
|
||||
|
||||
use ipc_rust::{get_calling_uid, BorrowedMsgParcel, IpcResult, IpcStatusCode};
|
||||
|
||||
use crate::error::ErrorCode;
|
||||
use crate::manager::events::EventMessage;
|
||||
use crate::service::ability::RequestAbility;
|
||||
use crate::service::permission::PermissionChecker;
|
||||
|
||||
pub(crate) struct Start;
|
||||
|
||||
impl Start {
|
||||
pub(crate) fn execute(
|
||||
data: &BorrowedMsgParcel,
|
||||
reply: &mut BorrowedMsgParcel,
|
||||
) -> IpcResult<()> {
|
||||
info!("Service start");
|
||||
if !PermissionChecker::check_internet() {
|
||||
error!("Service start: no INTERNET permission.");
|
||||
reply.write(&(ErrorCode::Permission as i32))?;
|
||||
return Err(IpcStatusCode::Failed);
|
||||
}
|
||||
|
||||
let id: String = data.read()?;
|
||||
debug!("Service start: task_id is {}", id);
|
||||
match id.parse::<u32>() {
|
||||
Ok(id) => {
|
||||
debug!("Service start: u32 task_id is {}", id);
|
||||
let uid = get_calling_uid();
|
||||
debug!("Service start: uid is {}", uid);
|
||||
|
||||
let (event, rx) = EventMessage::start(uid, id);
|
||||
if !RequestAbility::task_manager().send_event(event) {
|
||||
return Err(IpcStatusCode::Failed);
|
||||
}
|
||||
let ret = match rx.get() {
|
||||
Some(ret) => ret,
|
||||
None => {
|
||||
error!("Service start: receives ret failed");
|
||||
return Err(IpcStatusCode::Failed);
|
||||
}
|
||||
};
|
||||
reply.write(&(ret as i32))?;
|
||||
if ret != ErrorCode::ErrOk {
|
||||
error!("Service start: start failed for ret is {}", ret as i32);
|
||||
return Err(IpcStatusCode::Failed);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
_ => {
|
||||
error!("Service start: task_id not valid");
|
||||
reply.write(&(ErrorCode::TaskNotFound as i32))?;
|
||||
Err(IpcStatusCode::Failed)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
60
services/service/request/src/service/command/stop.rs
Normal file
60
services/service/request/src/service/command/stop.rs
Normal file
@ -0,0 +1,60 @@
|
||||
// Copyright (C) 2023 Huawei Device Co., Ltd.
|
||||
// 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.
|
||||
|
||||
use ipc_rust::{get_calling_uid, BorrowedMsgParcel, IpcResult, IpcStatusCode};
|
||||
|
||||
use crate::error::ErrorCode;
|
||||
use crate::manager::events::EventMessage;
|
||||
use crate::service::ability::RequestAbility;
|
||||
|
||||
pub(crate) struct Stop;
|
||||
|
||||
impl Stop {
|
||||
pub(crate) fn execute(
|
||||
data: &BorrowedMsgParcel,
|
||||
reply: &mut BorrowedMsgParcel,
|
||||
) -> IpcResult<()> {
|
||||
debug!("Service stop");
|
||||
let id: String = data.read()?;
|
||||
debug!("Service stop: task_id is {}", id);
|
||||
match id.parse::<u32>() {
|
||||
Ok(id) => {
|
||||
debug!("Service stop: u32 task_id is {}", id);
|
||||
let uid = get_calling_uid();
|
||||
debug!("Service stop: uid is {}", uid);
|
||||
let (event, rx) = EventMessage::stop(uid, id);
|
||||
if !RequestAbility::task_manager().send_event(event) {
|
||||
return Err(IpcStatusCode::Failed);
|
||||
}
|
||||
let ret = match rx.get() {
|
||||
Some(ret) => ret,
|
||||
None => {
|
||||
error!("Service stop: receives ret failed");
|
||||
return Err(IpcStatusCode::Failed);
|
||||
}
|
||||
};
|
||||
reply.write(&(ret as i32))?;
|
||||
if ret != ErrorCode::ErrOk {
|
||||
error!("Service stop: stop failed for ret is {}", ret as i32);
|
||||
return Err(IpcStatusCode::Failed);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
_ => {
|
||||
error!("Service stop: task_id not valid");
|
||||
reply.write(&(ErrorCode::TaskNotFound as i32))?;
|
||||
Err(IpcStatusCode::Failed)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
67
services/service/request/src/service/command/touch.rs
Normal file
67
services/service/request/src/service/command/touch.rs
Normal file
@ -0,0 +1,67 @@
|
||||
// Copyright (C) 2023 Huawei Device Co., Ltd.
|
||||
// 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.
|
||||
|
||||
use ipc_rust::{get_calling_uid, BorrowedMsgParcel, IpcResult, IpcStatusCode};
|
||||
|
||||
use crate::error::ErrorCode;
|
||||
use crate::manager::events::EventMessage;
|
||||
use crate::service::ability::RequestAbility;
|
||||
use crate::service::serialize_task_info;
|
||||
|
||||
pub(crate) struct Touch;
|
||||
|
||||
impl Touch {
|
||||
pub(crate) fn execute(
|
||||
data: &BorrowedMsgParcel,
|
||||
reply: &mut BorrowedMsgParcel,
|
||||
) -> IpcResult<()> {
|
||||
debug!("Service touch");
|
||||
let id: String = data.read()?;
|
||||
debug!("Service touch: task_id is {}", id);
|
||||
match id.parse::<u32>() {
|
||||
Ok(id) => {
|
||||
debug!("Service touch: u32 task_id is {}", id);
|
||||
let token: String = data.read()?;
|
||||
debug!("Service touch: token is {}", token);
|
||||
let uid = get_calling_uid();
|
||||
debug!("Service touch: uid is {}", uid);
|
||||
let (event, rx) = EventMessage::touch(uid, id, token);
|
||||
if !RequestAbility::task_manager().send_event(event) {
|
||||
return Err(IpcStatusCode::Failed);
|
||||
}
|
||||
match rx.get() {
|
||||
Some(Some(info)) => {
|
||||
reply.write(&(ErrorCode::ErrOk as i32))?;
|
||||
debug!("Service touch: task_info get");
|
||||
serialize_task_info(info, reply)?;
|
||||
Ok(())
|
||||
}
|
||||
Some(None) => {
|
||||
error!("Service touch: task_id or token not found");
|
||||
reply.write(&(ErrorCode::TaskNotFound as i32))?;
|
||||
Err(IpcStatusCode::Failed)
|
||||
}
|
||||
None => {
|
||||
error!("Service touch: receives task_info failed");
|
||||
Err(IpcStatusCode::Failed)
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
error!("Service touch: task_id or token not valid");
|
||||
reply.write(&(ErrorCode::TaskNotFound as i32))?;
|
||||
Err(IpcStatusCode::Failed)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,55 +1,53 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Huawei Device Co., Ltd.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* SAID: 3706*/
|
||||
/// Function code of RequestInterfaceCode
|
||||
pub enum RequestInterfaceCode {
|
||||
/// request construct & api10 create task
|
||||
Construct = 0,
|
||||
/// pause task
|
||||
Pause,
|
||||
/// query task || system api Queries specified task details
|
||||
Query,
|
||||
/// query mime type
|
||||
QueryMimeType,
|
||||
/// remove task || removes specifed task belongs to the caller
|
||||
Remove,
|
||||
/// resume task
|
||||
Resume,
|
||||
/// on task
|
||||
On,
|
||||
/// off task
|
||||
Off,
|
||||
/// ap10 start task
|
||||
Start,
|
||||
/// stop task
|
||||
Stop,
|
||||
/// Shows specified task details belongs to the caller
|
||||
Show,
|
||||
/// Touches specified task with token
|
||||
Touch,
|
||||
/// Searches tasks, for system
|
||||
Search,
|
||||
/// system api deletes specifed tasks
|
||||
Clear,
|
||||
}
|
||||
|
||||
/// Function code of RequestNotifyInterfaceCode
|
||||
pub enum RequestNotifyInterfaceCode {
|
||||
/// callback notification
|
||||
Notify = 0,
|
||||
/// Cache callback notification
|
||||
DoneNotify,
|
||||
}
|
||||
// Copyright (C) 2023 Huawei Device Co., Ltd.
|
||||
// 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.
|
||||
|
||||
// SAID: 3706
|
||||
/// Function code of RequestInterfaceCode
|
||||
pub(crate) enum RequestInterfaceCode {
|
||||
/// request construct & api10 create task
|
||||
Construct = 0,
|
||||
/// pause task
|
||||
Pause,
|
||||
/// query task || system api Queries specified task details
|
||||
Query,
|
||||
/// query mime type
|
||||
QueryMimeType,
|
||||
/// remove task || removes specifed task belongs to the caller
|
||||
Remove,
|
||||
/// resume task
|
||||
Resume,
|
||||
/// on task
|
||||
On,
|
||||
/// off task
|
||||
Off,
|
||||
/// ap10 start task
|
||||
Start,
|
||||
/// stop task
|
||||
Stop,
|
||||
/// Shows specified task details belongs to the caller
|
||||
Show,
|
||||
/// Touches specified task with token
|
||||
Touch,
|
||||
/// Searches tasks, for system
|
||||
Search,
|
||||
/// system api deletes specifed tasks
|
||||
Clear,
|
||||
}
|
||||
|
||||
/// Function code of RequestNotifyInterfaceCode
|
||||
pub(crate) enum RequestNotifyInterfaceCode {
|
||||
/// callback notification
|
||||
Notify = 0,
|
||||
/// Cache callback notification
|
||||
DoneNotify,
|
||||
}
|
51
services/service/request/src/service/listener/app.rs
Normal file
51
services/service/request/src/service/listener/app.rs
Normal file
@ -0,0 +1,51 @@
|
||||
// Copyright (C) 2023 Huawei Device Co., Ltd.
|
||||
// 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.
|
||||
|
||||
use crate::manager::events::EventMessage;
|
||||
use crate::service::ability::RequestAbility;
|
||||
use crate::task::info::ApplicationState;
|
||||
|
||||
pub(crate) struct AppStateListener;
|
||||
|
||||
impl AppStateListener {
|
||||
pub(crate) fn init() -> Self {
|
||||
info!("AppStateListener prepares to be inited");
|
||||
unsafe {
|
||||
RegisterAPPStateCallback(app_state_change_callback);
|
||||
}
|
||||
info!("AppStateListener is inited");
|
||||
Self
|
||||
}
|
||||
|
||||
pub(crate) fn shutdown(&self) {
|
||||
// Considers remove the callback.
|
||||
info!("AppStateListener is stopped");
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" fn app_state_change_callback(uid: i32, state: i32) {
|
||||
info!("Receives app state change callback");
|
||||
|
||||
let state = match state {
|
||||
2 => ApplicationState::Foreground,
|
||||
4 => ApplicationState::Background,
|
||||
5 => ApplicationState::Terminated,
|
||||
_ => return,
|
||||
};
|
||||
|
||||
RequestAbility::task_manager().send_event(EventMessage::app_state_change(uid as u64, state));
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
fn RegisterAPPStateCallback(f: extern "C" fn(i32, i32));
|
||||
}
|
18
services/service/request/src/service/listener/mod.rs
Normal file
18
services/service/request/src/service/listener/mod.rs
Normal file
@ -0,0 +1,18 @@
|
||||
// Copyright (C) 2023 Huawei Device Co., Ltd.
|
||||
// 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.
|
||||
|
||||
mod app;
|
||||
mod network;
|
||||
|
||||
pub(crate) use app::AppStateListener;
|
||||
pub(crate) use network::NetworkChangeListener;
|
42
services/service/request/src/service/listener/network.rs
Normal file
42
services/service/request/src/service/listener/network.rs
Normal file
@ -0,0 +1,42 @@
|
||||
// Copyright (C) 2023 Huawei Device Co., Ltd.
|
||||
// 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.
|
||||
|
||||
use crate::manager::events::EventMessage;
|
||||
use crate::service::ability::RequestAbility;
|
||||
|
||||
pub(crate) struct NetworkChangeListener;
|
||||
|
||||
impl NetworkChangeListener {
|
||||
pub(crate) fn init() -> Self {
|
||||
info!("NetworkChangeListener prepares to be inited");
|
||||
unsafe {
|
||||
RegisterNetworkCallback(network_change_callback);
|
||||
}
|
||||
info!("NetworkChangeListener is inited");
|
||||
Self
|
||||
}
|
||||
|
||||
pub(crate) fn shutdown(&self) {
|
||||
// Considers remove the callback.
|
||||
info!("NetworkChangeListener is stopped");
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" fn network_change_callback() {
|
||||
info!("Receives network change callback");
|
||||
RequestAbility::task_manager().send_event(EventMessage::network_change());
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
fn RegisterNetworkCallback(f: extern "C" fn());
|
||||
}
|
362
services/service/request/src/service/mod.rs
Normal file
362
services/service/request/src/service/mod.rs
Normal file
@ -0,0 +1,362 @@
|
||||
// Copyright (C) 2023 Huawei Device Co., Ltd.
|
||||
// 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.
|
||||
|
||||
//! This crate implement the request server service.
|
||||
|
||||
pub(crate) mod ability;
|
||||
pub(crate) mod command;
|
||||
#[allow(unused)]
|
||||
pub(crate) mod interface;
|
||||
pub(crate) mod listener;
|
||||
pub(crate) mod notify;
|
||||
pub(crate) mod permission;
|
||||
|
||||
use std::fs::{File, OpenOptions};
|
||||
|
||||
pub(crate) use interface::{RequestInterfaceCode, RequestNotifyInterfaceCode};
|
||||
use ipc_rust::{
|
||||
define_remote_object, get_calling_token_id, BorrowedMsgParcel, FileDesc, IRemoteBroker,
|
||||
InterfaceToken, IpcResult, IpcStatusCode, RemoteObj, RemoteStub, String16,
|
||||
};
|
||||
|
||||
use crate::task::info::TaskInfo;
|
||||
use crate::utils::c_wrapper::CStringWrapper;
|
||||
|
||||
define_remote_object!(
|
||||
RequestServiceInterface["ohos.request.service"] {
|
||||
stub: RequestServiceStub(on_remote_request),
|
||||
proxy: RequestServiceProxy,
|
||||
}
|
||||
);
|
||||
|
||||
fn on_remote_request(
|
||||
stub: &dyn RequestServiceInterface,
|
||||
code: u32,
|
||||
data: &BorrowedMsgParcel,
|
||||
reply: &mut BorrowedMsgParcel,
|
||||
) -> IpcResult<()> {
|
||||
const SERVICE_TOKEN: &str = "OHOS.Download.RequestServiceInterface";
|
||||
|
||||
info!("Processes on_remote_request, code: {}", code);
|
||||
match data.read::<InterfaceToken>().map(|token| token.get_token()) {
|
||||
Ok(token) if token == SERVICE_TOKEN => {}
|
||||
_ => {
|
||||
error!("Gets invalid token");
|
||||
return Err(IpcStatusCode::Failed);
|
||||
}
|
||||
};
|
||||
match code.try_into()? {
|
||||
RequestInterfaceCode::Construct => stub.construct(data, reply),
|
||||
RequestInterfaceCode::Pause => stub.pause(data, reply),
|
||||
RequestInterfaceCode::Query => stub.query(data, reply),
|
||||
RequestInterfaceCode::QueryMimeType => stub.query_mime_type(data, reply),
|
||||
RequestInterfaceCode::Remove => stub.remove(data, reply),
|
||||
RequestInterfaceCode::Resume => stub.resume(data, reply),
|
||||
RequestInterfaceCode::On => stub.on(data, reply),
|
||||
RequestInterfaceCode::Off => stub.off(data, reply),
|
||||
RequestInterfaceCode::Start => stub.start(data, reply),
|
||||
RequestInterfaceCode::Stop => stub.stop(data, reply),
|
||||
RequestInterfaceCode::Show => stub.show(data, reply),
|
||||
RequestInterfaceCode::Touch => stub.touch(data, reply),
|
||||
RequestInterfaceCode::Search => stub.search(data, reply),
|
||||
RequestInterfaceCode::Clear => Ok(()),
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<u32> for RequestInterfaceCode {
|
||||
type Error = IpcStatusCode;
|
||||
|
||||
fn try_from(code: u32) -> IpcResult<Self> {
|
||||
match code {
|
||||
_ if code == Self::Construct as u32 => Ok(Self::Construct),
|
||||
_ if code == Self::Pause as u32 => Ok(Self::Pause),
|
||||
_ if code == Self::Query as u32 => Ok(Self::Query),
|
||||
_ if code == Self::QueryMimeType as u32 => Ok(Self::QueryMimeType),
|
||||
_ if code == Self::Remove as u32 => Ok(Self::Remove),
|
||||
_ if code == Self::Resume as u32 => Ok(Self::Resume),
|
||||
_ if code == Self::On as u32 => Ok(Self::On),
|
||||
_ if code == Self::Off as u32 => Ok(Self::Off),
|
||||
_ if code == Self::Start as u32 => Ok(Self::Start),
|
||||
_ if code == Self::Stop as u32 => Ok(Self::Stop),
|
||||
_ if code == Self::Show as u32 => Ok(Self::Show),
|
||||
_ if code == Self::Touch as u32 => Ok(Self::Touch),
|
||||
_ if code == Self::Search as u32 => Ok(Self::Search),
|
||||
_ if code == Self::Clear as u32 => Ok(Self::Clear),
|
||||
_ => Err(IpcStatusCode::Failed),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Functions between proxy and stub.
|
||||
pub trait RequestServiceInterface: IRemoteBroker {
|
||||
/// Constructs or creates a task.
|
||||
fn construct(
|
||||
&self,
|
||||
_data: &BorrowedMsgParcel,
|
||||
_reply: &mut BorrowedMsgParcel,
|
||||
) -> IpcResult<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Pauses a task.
|
||||
fn pause(&self, _data: &BorrowedMsgParcel, _reply: &mut BorrowedMsgParcel) -> IpcResult<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Queries tasks.
|
||||
fn query(&self, _data: &BorrowedMsgParcel, _reply: &mut BorrowedMsgParcel) -> IpcResult<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Queries the mime type of a task.
|
||||
fn query_mime_type(
|
||||
&self,
|
||||
_data: &BorrowedMsgParcel,
|
||||
_reply: &mut BorrowedMsgParcel,
|
||||
) -> IpcResult<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Removes a task.
|
||||
fn remove(&self, _data: &BorrowedMsgParcel, _reply: &mut BorrowedMsgParcel) -> IpcResult<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Resumes a task.
|
||||
fn resume(&self, _data: &BorrowedMsgParcel, _reply: &mut BorrowedMsgParcel) -> IpcResult<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Sets the `on` callback of a task.
|
||||
fn on(&self, _data: &BorrowedMsgParcel, _reply: &mut BorrowedMsgParcel) -> IpcResult<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Sets the `off` callback of a task.
|
||||
fn off(&self, _data: &BorrowedMsgParcel, _reply: &mut BorrowedMsgParcel) -> IpcResult<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Starts a task.
|
||||
fn start(&self, _data: &BorrowedMsgParcel, _reply: &mut BorrowedMsgParcel) -> IpcResult<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Stops a task.
|
||||
fn stop(&self, _data: &BorrowedMsgParcel, _reply: &mut BorrowedMsgParcel) -> IpcResult<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Shows a specified task details which belongs to the caller.
|
||||
fn show(&self, _data: &BorrowedMsgParcel, _reply: &mut BorrowedMsgParcel) -> IpcResult<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Touches a specified task with token.
|
||||
fn touch(&self, _data: &BorrowedMsgParcel, _reply: &mut BorrowedMsgParcel) -> IpcResult<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Searches tasks of this system.
|
||||
fn search(&self, _data: &BorrowedMsgParcel, _reply: &mut BorrowedMsgParcel) -> IpcResult<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl RequestServiceInterface for RequestServiceProxy {}
|
||||
|
||||
/// RequestService type
|
||||
pub struct RequestService;
|
||||
|
||||
impl IRemoteBroker for RequestService {
|
||||
fn dump(&self, file: &FileDesc, args: &mut Vec<String16>) -> i32 {
|
||||
command::Dump::execute(file, args)
|
||||
}
|
||||
}
|
||||
|
||||
impl RequestServiceInterface for RequestService {
|
||||
fn construct(&self, data: &BorrowedMsgParcel, reply: &mut BorrowedMsgParcel) -> IpcResult<()> {
|
||||
command::Construct::execute(data, reply)
|
||||
}
|
||||
|
||||
fn pause(&self, data: &BorrowedMsgParcel, reply: &mut BorrowedMsgParcel) -> IpcResult<()> {
|
||||
command::Pause::execute(data, reply)
|
||||
}
|
||||
|
||||
fn query(&self, data: &BorrowedMsgParcel, reply: &mut BorrowedMsgParcel) -> IpcResult<()> {
|
||||
command::Query::execute(data, reply)
|
||||
}
|
||||
|
||||
fn query_mime_type(
|
||||
&self,
|
||||
data: &BorrowedMsgParcel,
|
||||
reply: &mut BorrowedMsgParcel,
|
||||
) -> IpcResult<()> {
|
||||
command::QueryMimeType::execute(data, reply)
|
||||
}
|
||||
|
||||
fn remove(&self, data: &BorrowedMsgParcel, reply: &mut BorrowedMsgParcel) -> IpcResult<()> {
|
||||
command::Remove::execute(data, reply)
|
||||
}
|
||||
|
||||
fn resume(&self, data: &BorrowedMsgParcel, reply: &mut BorrowedMsgParcel) -> IpcResult<()> {
|
||||
command::Resume::execute(data, reply)
|
||||
}
|
||||
|
||||
fn on(&self, data: &BorrowedMsgParcel, reply: &mut BorrowedMsgParcel) -> IpcResult<()> {
|
||||
command::On::execute(data, reply)
|
||||
}
|
||||
|
||||
fn off(&self, data: &BorrowedMsgParcel, reply: &mut BorrowedMsgParcel) -> IpcResult<()> {
|
||||
command::Off::execute(data, reply)
|
||||
}
|
||||
|
||||
fn start(&self, data: &BorrowedMsgParcel, reply: &mut BorrowedMsgParcel) -> IpcResult<()> {
|
||||
command::Start::execute(data, reply)
|
||||
}
|
||||
|
||||
fn stop(&self, data: &BorrowedMsgParcel, reply: &mut BorrowedMsgParcel) -> IpcResult<()> {
|
||||
command::Stop::execute(data, reply)
|
||||
}
|
||||
|
||||
fn show(&self, data: &BorrowedMsgParcel, reply: &mut BorrowedMsgParcel) -> IpcResult<()> {
|
||||
command::Show::execute(data, reply)
|
||||
}
|
||||
|
||||
fn touch(&self, data: &BorrowedMsgParcel, reply: &mut BorrowedMsgParcel) -> IpcResult<()> {
|
||||
command::Touch::execute(data, reply)
|
||||
}
|
||||
|
||||
fn search(&self, data: &BorrowedMsgParcel, reply: &mut BorrowedMsgParcel) -> IpcResult<()> {
|
||||
command::Search::execute(data, reply)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn serialize_task_info(tf: TaskInfo, reply: &mut BorrowedMsgParcel) -> IpcResult<()> {
|
||||
reply.write(&(tf.common_data.gauge))?;
|
||||
reply.write(&(tf.common_data.retry))?;
|
||||
reply.write(&(tf.common_data.action as u32))?;
|
||||
reply.write(&(tf.common_data.mode as u32))?;
|
||||
reply.write(&(tf.common_data.reason as u32))?;
|
||||
reply.write(&(tf.common_data.tries))?;
|
||||
reply.write(&(tf.common_data.uid.to_string()))?;
|
||||
reply.write(&(tf.bundle))?;
|
||||
reply.write(&(tf.url))?;
|
||||
reply.write(&(tf.common_data.task_id.to_string()))?;
|
||||
reply.write(&tf.title)?;
|
||||
reply.write(&tf.mime_type)?;
|
||||
reply.write(&(tf.common_data.ctime))?;
|
||||
reply.write(&(tf.common_data.mtime))?;
|
||||
reply.write(&(tf.data))?;
|
||||
reply.write(&(tf.description))?;
|
||||
reply.write(&(tf.common_data.priority))?;
|
||||
|
||||
reply.write(&(tf.form_items.len() as u32))?;
|
||||
for i in 0..tf.form_items.len() {
|
||||
reply.write(&(tf.form_items[i].name))?;
|
||||
reply.write(&(tf.form_items[i].value))?;
|
||||
}
|
||||
|
||||
reply.write(&(tf.file_specs.len() as u32))?;
|
||||
for i in 0..tf.file_specs.len() {
|
||||
reply.write(&(tf.file_specs[i].name))?;
|
||||
reply.write(&(tf.file_specs[i].path))?;
|
||||
reply.write(&(tf.file_specs[i].file_name))?;
|
||||
reply.write(&(tf.file_specs[i].mime_type))?;
|
||||
}
|
||||
|
||||
reply.write(&(tf.progress.common_data.state as u32))?;
|
||||
let index = tf.progress.common_data.index;
|
||||
reply.write(&(index as u32))?;
|
||||
reply.write(&(tf.progress.processed[index] as u64))?;
|
||||
reply.write(&(tf.progress.common_data.total_processed as u64))?;
|
||||
reply.write(&(tf.progress.sizes))?;
|
||||
|
||||
reply.write(&(tf.progress.extras.len() as u32))?;
|
||||
for (k, v) in tf.progress.extras.iter() {
|
||||
reply.write(&(k))?;
|
||||
reply.write(&(v))?;
|
||||
}
|
||||
|
||||
reply.write(&(tf.extras.len() as u32))?;
|
||||
for (k, v) in tf.extras.iter() {
|
||||
reply.write(&(k))?;
|
||||
reply.write(&(v))?;
|
||||
}
|
||||
reply.write(&(tf.common_data.version as u32))?;
|
||||
reply.write(&(tf.each_file_status.len() as u32))?;
|
||||
for item in tf.each_file_status.iter() {
|
||||
reply.write(&(item.path))?;
|
||||
reply.write(&(item.reason as u32))?;
|
||||
reply.write(&(item.message))?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn get_calling_bundle() -> String {
|
||||
debug!("Gets calling bundle");
|
||||
let token_id = get_calling_token_id();
|
||||
debug!("Gets token id {}", &token_id);
|
||||
unsafe { GetCallingBundle(token_id).to_string() }
|
||||
}
|
||||
|
||||
pub(crate) fn is_system_api() -> bool {
|
||||
debug!("Checks if the api is a system_api");
|
||||
let token_id = get_calling_token_id();
|
||||
debug!("Gets token id {}", &token_id);
|
||||
unsafe { RequestIsSystemAPI(token_id) }
|
||||
}
|
||||
|
||||
pub(crate) fn open_file_readwrite(uid: u64, bundle: &str, path: &str) -> IpcResult<File> {
|
||||
match OpenOptions::new()
|
||||
.read(true)
|
||||
.write(true)
|
||||
.append(true)
|
||||
.open(convert_path(uid, bundle, path))
|
||||
{
|
||||
Ok(file) => Ok(file),
|
||||
Err(e) => {
|
||||
error!("open_file_readwrite failed, err is {:?}", e);
|
||||
Err(IpcStatusCode::Failed)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn open_file_readonly(uid: u64, bundle: &str, path: &str) -> IpcResult<File> {
|
||||
match OpenOptions::new()
|
||||
.read(true)
|
||||
.open(convert_path(uid, bundle, path))
|
||||
{
|
||||
Ok(file) => Ok(file),
|
||||
Err(e) => {
|
||||
error!("open_file_readonly failed, err is {:?}", e);
|
||||
Err(IpcStatusCode::Failed)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_path(uid: u64, bundle: &str, path: &str) -> String {
|
||||
let uuid = uid / 200000;
|
||||
let base = "/data/storage/el2/base/";
|
||||
format!(
|
||||
"/data/app/el2/{}/base/{}/{}",
|
||||
uuid,
|
||||
bundle,
|
||||
path.replace(base, "")
|
||||
)
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
pub(crate) fn GetCallingBundle(token_id: u64) -> CStringWrapper;
|
||||
pub(crate) fn RequestIsSystemAPI(token_id: u64) -> bool;
|
||||
}
|
242
services/service/request/src/service/notify/manager.rs
Normal file
242
services/service/request/src/service/notify/manager.rs
Normal file
@ -0,0 +1,242 @@
|
||||
// Copyright (C) 2023 Huawei Device Co., Ltd.
|
||||
// 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.
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
use ipc_rust::{IRemoteObj, InterfaceToken, IpcResult, MsgParcel, RemoteObj};
|
||||
use ylong_runtime::sync::mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender};
|
||||
use ylong_runtime::sync::oneshot::Sender;
|
||||
|
||||
use crate::error::ErrorCode;
|
||||
use crate::service::notify::{Event, NotifyData, NotifyEvent};
|
||||
use crate::service::RequestNotifyInterfaceCode;
|
||||
use crate::task::info::State;
|
||||
|
||||
pub(crate) struct NotifyManager {
|
||||
rx: UnboundedReceiver<NotifyEvent>,
|
||||
remotes: HashMap<NotifyKey, Notifier>,
|
||||
unregistered: HashMap<NotifyKey, Box<NotifyData>>,
|
||||
}
|
||||
|
||||
impl NotifyManager {
|
||||
fn new(rx: UnboundedReceiver<NotifyEvent>) -> Self {
|
||||
Self {
|
||||
rx,
|
||||
remotes: HashMap::new(),
|
||||
unregistered: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn init() -> NotifyEntry {
|
||||
info!("NotifyManager prepare to be inited");
|
||||
let (tx, rx) = unbounded_channel::<NotifyEvent>();
|
||||
ylong_runtime::spawn(Self::new(rx).run());
|
||||
let entry = NotifyEntry::new(tx);
|
||||
info!("NotifyManager is inited");
|
||||
entry
|
||||
}
|
||||
|
||||
pub(crate) async fn run(mut self) {
|
||||
loop {
|
||||
let event = match self.rx.recv().await {
|
||||
Ok(message) => message,
|
||||
Err(e) => {
|
||||
error!("Notifier recv error {:?}", e);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
match event {
|
||||
NotifyEvent::Notify(event, data) => self.notify(event, data),
|
||||
NotifyEvent::On(event, id, obj, tx) => self.on(event, id, obj, tx),
|
||||
NotifyEvent::Off(event, id, sender) => self.off(event, id, sender),
|
||||
NotifyEvent::Clear(id) => self.clear(id),
|
||||
NotifyEvent::Shutdown => {
|
||||
info!("NotifyManager shuts down");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl NotifyManager {
|
||||
fn notify(&mut self, event: Event, data: Box<NotifyData>) {
|
||||
debug!("NotifyManager gets event: {}", event.as_str());
|
||||
let key = NotifyKey::new(event, data.task_id);
|
||||
if let Some(notifier) = self.remotes.get(&key) {
|
||||
debug!("NotifyManager finds key succeed: {:?}", key);
|
||||
// Ignores notify failed.
|
||||
notifier.notify(event, data);
|
||||
} else {
|
||||
debug!("NotifyManager finds key failed: {:?}", key);
|
||||
self.unregistered.insert(key, data);
|
||||
}
|
||||
}
|
||||
|
||||
fn on(&mut self, event: Event, id: u32, obj: RemoteObj, sender: Sender<ErrorCode>) {
|
||||
let key = NotifyKey::new(event, id);
|
||||
let notifier = Notifier::new(obj);
|
||||
|
||||
if let Some(data) = self.unregistered.remove(&key) {
|
||||
debug!("NotifyManager notifies unregistered key: {:?}", key);
|
||||
notifier.notify(event, data);
|
||||
self.unregistered.remove(&key);
|
||||
}
|
||||
self.remotes.insert(key, notifier);
|
||||
debug!("NotifyManager has inserted key: {:?}", key);
|
||||
let _ = sender.send(ErrorCode::ErrOk);
|
||||
}
|
||||
|
||||
fn off(&mut self, event: Event, id: u32, sender: Sender<ErrorCode>) {
|
||||
let key = NotifyKey::new(event, id);
|
||||
if self.remotes.remove(&key).is_some() {
|
||||
debug!("NotifyManager removes key: {:?}", key);
|
||||
// Sends error code immediately, ignore the result.
|
||||
let _ = sender.send(ErrorCode::ErrOk);
|
||||
} else {
|
||||
error!("NotifyManager removes key failed: {:?}", key);
|
||||
// Sends error code immediately, ignore the result.
|
||||
let _ = sender.send(ErrorCode::Other);
|
||||
}
|
||||
}
|
||||
|
||||
fn clear(&mut self, id: u32) {
|
||||
let events = [
|
||||
Event::Complete,
|
||||
Event::Fail,
|
||||
Event::HeaderReceive,
|
||||
Event::Pause,
|
||||
Event::Progress,
|
||||
Event::Remove,
|
||||
Event::Resume,
|
||||
];
|
||||
// Clears objects and unregistered notify data of the target task.
|
||||
for event in events {
|
||||
let key = NotifyKey::new(event, id);
|
||||
self.remotes.remove(&key);
|
||||
self.unregistered.remove(&key);
|
||||
}
|
||||
debug!("NotifyManager has cleared all the key of Task: {:?}", id);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct NotifyEntry {
|
||||
tx: UnboundedSender<NotifyEvent>,
|
||||
}
|
||||
|
||||
impl NotifyEntry {
|
||||
fn new(tx: UnboundedSender<NotifyEvent>) -> Self {
|
||||
Self { tx }
|
||||
}
|
||||
|
||||
pub(crate) fn shutdown(&self) {
|
||||
// Ignore the result.
|
||||
self.send_event(NotifyEvent::shutdown());
|
||||
}
|
||||
|
||||
pub(crate) fn send_event(&self, event: NotifyEvent) {
|
||||
if self.tx.send(event).is_err() {
|
||||
error!("Sends NotifyEvent failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct Notifier {
|
||||
obj: RemoteObj,
|
||||
}
|
||||
|
||||
impl Notifier {
|
||||
fn new(obj: RemoteObj) -> Self {
|
||||
Self { obj }
|
||||
}
|
||||
|
||||
fn notify(&self, event: Event, data: Box<NotifyData>) {
|
||||
debug!("Notifier gets notify data: {:?}", data);
|
||||
if data.progress.common_data.index >= data.progress.sizes.len() {
|
||||
error!("During notify: index out of range");
|
||||
return;
|
||||
}
|
||||
let common_data = &data.progress.common_data;
|
||||
if (common_data.state == State::Running as u8 || common_data.state == State::Retrying as u8)
|
||||
&& common_data.total_processed == 0
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
let mut parcel = match MsgParcel::new() {
|
||||
Some(parcel) => parcel,
|
||||
None => {
|
||||
error!("During notify: create MsgParcel failed");
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
if write_parcel(&mut parcel, event, data.as_ref()).is_err() {
|
||||
error!("During notify: ipc write failed");
|
||||
return;
|
||||
}
|
||||
|
||||
debug!("During notify: send request");
|
||||
if self
|
||||
.obj
|
||||
.send_request(RequestNotifyInterfaceCode::Notify as u32, &parcel, false)
|
||||
.is_err()
|
||||
{
|
||||
error!("During notify: send request failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn write_parcel(parcel: &mut MsgParcel, event: Event, data: &NotifyData) -> IpcResult<()> {
|
||||
parcel.write(&InterfaceToken::new("OHOS.Download.NotifyInterface"))?;
|
||||
parcel.write(&(event.as_str()))?;
|
||||
parcel.write(&(data.task_id.to_string()))?;
|
||||
parcel.write(&(data.progress.common_data.state as u32))?;
|
||||
|
||||
let index = data.progress.common_data.index;
|
||||
parcel.write(&(index as u32))?;
|
||||
parcel.write(&(data.progress.processed[index] as u64))?;
|
||||
|
||||
parcel.write(&(data.progress.common_data.total_processed as u64))?;
|
||||
parcel.write(&(data.progress.sizes))?;
|
||||
parcel.write(&(data.progress.extras.len() as u32))?;
|
||||
|
||||
for (k, v) in data.progress.extras.iter() {
|
||||
parcel.write(&k)?;
|
||||
parcel.write(&v)?;
|
||||
}
|
||||
parcel.write(&(data.action as u32))?;
|
||||
parcel.write(&(data.version as u32))?;
|
||||
|
||||
parcel.write(&(data.each_file_status.len() as u32))?;
|
||||
for status in data.each_file_status.iter() {
|
||||
parcel.write(&(status.path))?;
|
||||
parcel.write(&(status.reason as u32))?;
|
||||
parcel.write(&(status.message))?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
|
||||
struct NotifyKey {
|
||||
event: Event,
|
||||
task_id: u32,
|
||||
}
|
||||
|
||||
impl NotifyKey {
|
||||
fn new(event: Event, task_id: u32) -> Self {
|
||||
Self { event, task_id }
|
||||
}
|
||||
}
|
107
services/service/request/src/service/notify/mod.rs
Normal file
107
services/service/request/src/service/notify/mod.rs
Normal file
@ -0,0 +1,107 @@
|
||||
// Copyright (C) 2023 Huawei Device Co., Ltd.
|
||||
// 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.
|
||||
|
||||
mod manager;
|
||||
|
||||
use ipc_rust::RemoteObj;
|
||||
pub(crate) use manager::{NotifyEntry, NotifyManager};
|
||||
use ylong_runtime::sync::oneshot::{channel, Sender};
|
||||
|
||||
use crate::error::ErrorCode;
|
||||
use crate::task::notify::NotifyData;
|
||||
use crate::utils::Recv;
|
||||
|
||||
pub(crate) enum NotifyEvent {
|
||||
Notify(Event, Box<NotifyData>),
|
||||
On(Event, u32, RemoteObj, Sender<ErrorCode>),
|
||||
Off(Event, u32, Sender<ErrorCode>),
|
||||
Clear(u32),
|
||||
Shutdown,
|
||||
}
|
||||
|
||||
impl NotifyEvent {
|
||||
pub(crate) fn notify(event: Event, data: NotifyData) -> Self {
|
||||
Self::Notify(event, Box::new(data))
|
||||
}
|
||||
|
||||
pub(crate) fn on(event: Event, id: u32, obj: RemoteObj) -> (Self, Recv<ErrorCode>) {
|
||||
let (tx, rx) = channel::<ErrorCode>();
|
||||
(Self::On(event, id, obj, tx), Recv::new(rx))
|
||||
}
|
||||
|
||||
pub(crate) fn off(event: Event, id: u32) -> (Self, Recv<ErrorCode>) {
|
||||
let (tx, rx) = channel::<ErrorCode>();
|
||||
(Self::Off(event, id, tx), Recv::new(rx))
|
||||
}
|
||||
|
||||
pub(crate) fn clear(id: u32) -> Self {
|
||||
Self::Clear(id)
|
||||
}
|
||||
|
||||
pub(crate) fn shutdown() -> Self {
|
||||
Self::Shutdown
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
|
||||
pub(crate) enum Event {
|
||||
Complete,
|
||||
Fail,
|
||||
HeaderReceive,
|
||||
Pause,
|
||||
Progress,
|
||||
Remove,
|
||||
Resume,
|
||||
}
|
||||
|
||||
impl Event {
|
||||
fn as_str(&self) -> &'static str {
|
||||
match self {
|
||||
Self::Complete => "complete",
|
||||
Self::Fail => "fail",
|
||||
Self::HeaderReceive => "headerReceive",
|
||||
Self::Pause => "pause",
|
||||
Self::Progress => "progress",
|
||||
Self::Remove => "remove",
|
||||
Self::Resume => "resume",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&str> for Event {
|
||||
type Error = EventConvertError;
|
||||
|
||||
fn try_from(value: &str) -> Result<Self, Self::Error> {
|
||||
match value {
|
||||
"complete" => Ok(Self::Complete),
|
||||
"fail" => Ok(Self::Fail),
|
||||
"headerReceive" => Ok(Self::HeaderReceive),
|
||||
"pause" => Ok(Self::Pause),
|
||||
"progress" => Ok(Self::Progress),
|
||||
"remove" => Ok(Self::Remove),
|
||||
"resume" => Ok(Self::Resume),
|
||||
_ => Err(EventConvertError),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<String> for Event {
|
||||
type Error = EventConvertError;
|
||||
|
||||
fn try_from(value: String) -> Result<Self, Self::Error> {
|
||||
Event::try_from(value.as_str())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct EventConvertError;
|
65
services/service/request/src/service/permission.rs
Normal file
65
services/service/request/src/service/permission.rs
Normal file
@ -0,0 +1,65 @@
|
||||
// Copyright (C) 2023 Huawei Device Co., Ltd.
|
||||
// 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.
|
||||
|
||||
use ipc_rust::get_calling_token_id;
|
||||
|
||||
use crate::utils::c_wrapper::CStringWrapper;
|
||||
|
||||
static INTERNET_PERMISSION: &str = "ohos.permission.INTERNET";
|
||||
static QUERY_DOWNLOAD: &str = "ohos.permission.DOWNLOAD_SESSION_MANAGER";
|
||||
static QUERY_UPLOAD: &str = "ohos.permission.UPLOAD_SESSION_MANAGER";
|
||||
|
||||
pub(crate) struct PermissionChecker;
|
||||
|
||||
impl PermissionChecker {
|
||||
pub(crate) fn check_internet() -> bool {
|
||||
debug!("Checks INTERNET permission");
|
||||
unsafe {
|
||||
RequestCheckPermission(
|
||||
get_calling_token_id(),
|
||||
CStringWrapper::from(INTERNET_PERMISSION),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn check_query() -> QueryPermission {
|
||||
debug!("Checks QUERY permission");
|
||||
let id = get_calling_token_id();
|
||||
let query_download =
|
||||
unsafe { RequestCheckPermission(id, CStringWrapper::from(QUERY_DOWNLOAD)) };
|
||||
let query_upload =
|
||||
unsafe { RequestCheckPermission(id, CStringWrapper::from(QUERY_UPLOAD)) };
|
||||
info!(
|
||||
"Checks query_download permission is {}, query_upload permission is {}",
|
||||
query_download, query_upload
|
||||
);
|
||||
|
||||
match (query_download, query_upload) {
|
||||
(true, true) => QueryPermission::QueryAll,
|
||||
(true, false) => QueryPermission::QueryDownLoad,
|
||||
(false, true) => QueryPermission::QueryUpload,
|
||||
(false, false) => QueryPermission::NoPermission,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) enum QueryPermission {
|
||||
NoPermission = 0,
|
||||
QueryDownLoad,
|
||||
QueryUpload,
|
||||
QueryAll,
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
pub(crate) fn RequestCheckPermission(token_id: u64, permission: CStringWrapper) -> bool;
|
||||
}
|
65
services/service/request/src/sys_event.rs
Normal file
65
services/service/request/src/sys_event.rs
Normal file
@ -0,0 +1,65 @@
|
||||
// Copyright (C) 2023 Huawei Device Co., Ltd.
|
||||
// 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.
|
||||
|
||||
use hisysevent::{write, EventType, HiSysEventParam};
|
||||
|
||||
const DOMAIN: &str = "REQUEST";
|
||||
|
||||
pub(crate) const ERROR_INFO: &str = "ERROR_INFO";
|
||||
pub(crate) const TASKS_TYPE: &str = "TASKS_TYPE";
|
||||
pub(crate) const TOTAL_FILE_NUM: &str = "TOTAL_FILE_NUM";
|
||||
pub(crate) const FAIL_FILE_NUM: &str = "FAIL_FILE_NUM";
|
||||
pub(crate) const SUCCESS_FILE_NUM: &str = "SUCCESS_FILE_NUM";
|
||||
|
||||
/// System events structure which base on `Hisysevent`.
|
||||
pub(crate) struct SysEvent<'a> {
|
||||
event_kind: EventKind,
|
||||
inner_type: EventType,
|
||||
params: Vec<HiSysEventParam<'a>>,
|
||||
}
|
||||
|
||||
impl<'a> SysEvent<'a> {
|
||||
pub(crate) fn task_fault() -> Self {
|
||||
Self {
|
||||
event_kind: EventKind::TaskFault,
|
||||
inner_type: EventType::Fault,
|
||||
params: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn param(mut self, param: HiSysEventParam<'a>) -> Self {
|
||||
self.params.push(param);
|
||||
self
|
||||
}
|
||||
|
||||
pub(crate) fn write(self) {
|
||||
write(
|
||||
DOMAIN,
|
||||
self.event_kind.as_str(),
|
||||
self.inner_type,
|
||||
self.params.as_slice(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
enum EventKind {
|
||||
TaskFault,
|
||||
}
|
||||
|
||||
impl EventKind {
|
||||
fn as_str(&self) -> &str {
|
||||
match self {
|
||||
EventKind::TaskFault => "TASK_FAULT",
|
||||
}
|
||||
}
|
||||
}
|
110
services/service/request/src/task/config.rs
Normal file
110
services/service/request/src/task/config.rs
Normal file
@ -0,0 +1,110 @@
|
||||
// Copyright (C) 2023 Huawei Device Co., Ltd.
|
||||
// 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.
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
use super::info::Mode;
|
||||
use crate::utils::form_item::{FileSpec, FormItem};
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Debug)]
|
||||
#[repr(u8)]
|
||||
pub(crate) enum Action {
|
||||
DownLoad = 0,
|
||||
UpLoad,
|
||||
Any,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Debug)]
|
||||
#[repr(u8)]
|
||||
pub(crate) enum Version {
|
||||
API9 = 1,
|
||||
API10,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Debug)]
|
||||
#[repr(u8)]
|
||||
pub(crate) enum Network {
|
||||
Any = 0,
|
||||
Wifi,
|
||||
Cellular,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub(crate) struct CommonTaskConfig {
|
||||
pub(crate) task_id: u32,
|
||||
pub(crate) uid: u64,
|
||||
pub(crate) action: Action,
|
||||
pub(crate) mode: Mode,
|
||||
pub(crate) cover: bool,
|
||||
pub(crate) network: Network,
|
||||
pub(crate) metered: bool,
|
||||
pub(crate) roaming: bool,
|
||||
pub(crate) retry: bool,
|
||||
pub(crate) redirect: bool,
|
||||
pub(crate) index: u32,
|
||||
pub(crate) begins: u64,
|
||||
pub(crate) ends: i64,
|
||||
pub(crate) gauge: bool,
|
||||
pub(crate) precise: bool,
|
||||
pub(crate) priority: u32,
|
||||
pub(crate) background: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct TaskConfig {
|
||||
pub(crate) bundle: String,
|
||||
pub(crate) url: String,
|
||||
pub(crate) title: String,
|
||||
pub(crate) description: String,
|
||||
pub(crate) method: String,
|
||||
pub(crate) headers: HashMap<String, String>,
|
||||
pub(crate) data: String,
|
||||
pub(crate) token: String,
|
||||
#[allow(unused)]
|
||||
pub(crate) extras: HashMap<String, String>,
|
||||
pub(crate) version: Version,
|
||||
pub(crate) form_items: Vec<FormItem>,
|
||||
pub(crate) file_specs: Vec<FileSpec>,
|
||||
pub(crate) body_file_names: Vec<String>,
|
||||
pub(crate) common_data: CommonTaskConfig,
|
||||
}
|
||||
|
||||
impl From<u8> for Action {
|
||||
fn from(value: u8) -> Self {
|
||||
match value {
|
||||
0 => Action::DownLoad,
|
||||
1 => Action::UpLoad,
|
||||
_ => Action::Any,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u8> for Version {
|
||||
fn from(value: u8) -> Self {
|
||||
match value {
|
||||
2 => Version::API10,
|
||||
_ => Version::API9,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u8> for Network {
|
||||
fn from(value: u8) -> Self {
|
||||
match value {
|
||||
0 => Network::Any,
|
||||
2 => Network::Cellular,
|
||||
_ => Network::Wifi,
|
||||
}
|
||||
}
|
||||
}
|
173
services/service/request/src/task/download.rs
Normal file
173
services/service/request/src/task/download.rs
Normal file
@ -0,0 +1,173 @@
|
||||
// Copyright (C) 2023 Huawei Device Co., Ltd.
|
||||
// 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.
|
||||
|
||||
use std::pin::Pin;
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::sync::Arc;
|
||||
use std::task::{Context, Poll};
|
||||
|
||||
use ylong_http_client::async_impl::{DownloadOperator, Downloader};
|
||||
use ylong_http_client::{HttpClientError, Response, SpeedLimit, Timeout};
|
||||
|
||||
use super::operator::TaskOperator;
|
||||
use super::reason::Reason;
|
||||
use super::tick::Clock;
|
||||
use crate::task::info::State;
|
||||
use crate::task::RequestTask;
|
||||
|
||||
cfg_oh! {
|
||||
use crate::trace::Trace;
|
||||
}
|
||||
|
||||
const SECONDS_IN_ONE_WEEK: u64 = 7 * 24 * 60 * 60;
|
||||
|
||||
const LOW_SPEED_TIME: u64 = 60;
|
||||
const LOW_SPEED_LIMIT: u64 = 1;
|
||||
|
||||
impl DownloadOperator for TaskOperator {
|
||||
fn poll_download(
|
||||
self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
data: &[u8],
|
||||
) -> Poll<Result<usize, HttpClientError>> {
|
||||
let me = self.get_mut();
|
||||
if me.task.rate_limiting.load(Ordering::SeqCst) {
|
||||
if me.check_point.take().is_none() {
|
||||
Clock::get_instance().register(cx);
|
||||
me.check_point = Some(());
|
||||
return Poll::Pending;
|
||||
}
|
||||
} else {
|
||||
Clock::get_instance().tick();
|
||||
}
|
||||
|
||||
if me.task.range_request.load(Ordering::SeqCst) {
|
||||
if me.task.range_response.load(Ordering::SeqCst) {
|
||||
return me.poll_write_file(cx, data, 0);
|
||||
}
|
||||
// write partial response data
|
||||
let begins = me.task.conf.common_data.begins;
|
||||
let ends = me.task.conf.common_data.ends;
|
||||
return me.poll_write_partial_file(cx, data, begins, ends);
|
||||
}
|
||||
me.poll_write_file(cx, data, 0)
|
||||
}
|
||||
|
||||
fn poll_progress(
|
||||
self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
_downloaded: u64,
|
||||
_total: Option<u64>,
|
||||
) -> Poll<Result<(), HttpClientError>> {
|
||||
self.poll_progress_common(cx)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn build_downloader(
|
||||
task: Arc<RequestTask>,
|
||||
response: Response,
|
||||
) -> Downloader<TaskOperator> {
|
||||
let task_operator = TaskOperator::new(task);
|
||||
|
||||
Downloader::builder()
|
||||
.body(response)
|
||||
.operator(task_operator)
|
||||
.timeout(Timeout::from_secs(SECONDS_IN_ONE_WEEK))
|
||||
.speed_limit(SpeedLimit::new().min_speed(LOW_SPEED_LIMIT, LOW_SPEED_TIME))
|
||||
.build()
|
||||
}
|
||||
|
||||
pub(crate) async fn download(task: Arc<RequestTask>) {
|
||||
download_inner(task.clone()).await;
|
||||
|
||||
#[cfg(feature = "oh")]
|
||||
use hisysevent::{build_number_param, build_str_param};
|
||||
|
||||
#[cfg(feature = "oh")]
|
||||
use crate::sys_event::SysEvent;
|
||||
#[cfg(feature = "oh")]
|
||||
let reason = task.code.lock().unwrap()[0];
|
||||
// If `Reason` is not `Default`a records this sys event.
|
||||
#[cfg(feature = "oh")]
|
||||
if reason != Reason::Default {
|
||||
SysEvent::task_fault()
|
||||
.param(build_str_param!(crate::sys_event::TASKS_TYPE, "DOWNLOAD"))
|
||||
.param(build_number_param!(crate::sys_event::TOTAL_FILE_NUM, 1))
|
||||
.param(build_number_param!(crate::sys_event::FAIL_FILE_NUM, 1))
|
||||
.param(build_number_param!(crate::sys_event::SUCCESS_FILE_NUM, 0))
|
||||
.param(build_number_param!(
|
||||
crate::sys_event::ERROR_INFO,
|
||||
reason as i32
|
||||
))
|
||||
.write();
|
||||
}
|
||||
}
|
||||
|
||||
async fn download_inner(task: Arc<RequestTask>) {
|
||||
info!("begin download");
|
||||
|
||||
// Ensures `_trace` can only be freed when this function exits.
|
||||
#[cfg(feature = "oh")]
|
||||
Trace::start("download file");
|
||||
|
||||
let response = match task.client.as_ref() {
|
||||
Some(client) => {
|
||||
let request = match task.build_download_request().await {
|
||||
Some(request) => request,
|
||||
None => return,
|
||||
};
|
||||
|
||||
let name = task.conf.file_specs[0].path.as_str();
|
||||
let download = task.progress.lock().unwrap().processed[0];
|
||||
// Ensures `_trace` can only be freed when this function exits.
|
||||
#[cfg(feature = "oh")]
|
||||
Trace::start(&format!(
|
||||
"download file name: {name} downloaded size: {download}"
|
||||
));
|
||||
#[cfg(feature = "oh")]
|
||||
Trace::finish();
|
||||
client.request(request).await
|
||||
}
|
||||
None => {
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
task.record_response_header(&response);
|
||||
if !task.handle_response_error(&response).await {
|
||||
error!("response error");
|
||||
return;
|
||||
}
|
||||
let response = response.unwrap();
|
||||
|
||||
if !task.get_file_info(&response) {
|
||||
return;
|
||||
}
|
||||
|
||||
let mut downloader = build_downloader(task.clone(), response);
|
||||
|
||||
let result = downloader.download().await;
|
||||
|
||||
if !task.handle_download_error(&result) {
|
||||
error!("handle_download_error");
|
||||
return;
|
||||
}
|
||||
|
||||
// Makes sure all the data has been written to the target file.
|
||||
if let Some(file) = task.files.get(0) {
|
||||
let _ = file.sync_all().await;
|
||||
}
|
||||
task.set_status(State::Completed, Reason::Default);
|
||||
#[cfg(feature = "oh")]
|
||||
Trace::finish();
|
||||
}
|
382
services/service/request/src/task/ffi.rs
Normal file
382
services/service/request/src/task/ffi.rs
Normal file
@ -0,0 +1,382 @@
|
||||
// Copyright (C) 2023 Huawei Device Co., Ltd.
|
||||
// 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.
|
||||
|
||||
use std::ffi::c_char;
|
||||
|
||||
use super::config::{Action, CommonTaskConfig, Network, TaskConfig, Version};
|
||||
use super::info::{CommonTaskInfo, InfoSet, Mode, TaskInfo, UpdateInfo};
|
||||
use super::notify::{CommonProgress, EachFileStatus, Progress};
|
||||
use super::reason::Reason;
|
||||
use crate::utils::c_wrapper::{
|
||||
CFileSpec, CFormItem, CStringWrapper, DeleteCFileSpec, DeleteCFormItem, DeleteCStringPtr,
|
||||
};
|
||||
use crate::utils::form_item::{FileSpec, FormItem};
|
||||
use crate::utils::{build_vec, hashmap_to_string, split_string, string_to_hashmap};
|
||||
|
||||
#[repr(C)]
|
||||
pub(crate) struct CTaskConfig {
|
||||
pub(crate) bundle: CStringWrapper,
|
||||
pub(crate) url: CStringWrapper,
|
||||
pub(crate) title: CStringWrapper,
|
||||
pub(crate) description: CStringWrapper,
|
||||
pub(crate) method: CStringWrapper,
|
||||
pub(crate) headers: CStringWrapper,
|
||||
pub(crate) data: CStringWrapper,
|
||||
pub(crate) token: CStringWrapper,
|
||||
pub(crate) extras: CStringWrapper,
|
||||
pub(crate) version: u8,
|
||||
pub(crate) form_items_ptr: *const CFormItem,
|
||||
pub(crate) form_items_len: u32,
|
||||
pub(crate) file_specs_ptr: *const CFileSpec,
|
||||
pub(crate) file_specs_len: u32,
|
||||
pub(crate) body_file_names_ptr: *const CStringWrapper,
|
||||
pub(crate) body_file_names_len: u32,
|
||||
pub(crate) common_data: CommonCTaskConfig,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub(crate) struct CommonCTaskConfig {
|
||||
pub(crate) task_id: u32,
|
||||
pub(crate) uid: u64,
|
||||
pub(crate) action: u8,
|
||||
pub(crate) mode: u8,
|
||||
pub(crate) cover: bool,
|
||||
pub(crate) network: u8,
|
||||
pub(crate) metered: bool,
|
||||
pub(crate) roaming: bool,
|
||||
pub(crate) retry: bool,
|
||||
pub(crate) redirect: bool,
|
||||
pub(crate) index: u32,
|
||||
pub(crate) begins: u64,
|
||||
pub(crate) ends: i64,
|
||||
pub(crate) gauge: bool,
|
||||
pub(crate) precise: bool,
|
||||
pub(crate) priority: u32,
|
||||
pub(crate) background: bool,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub(crate) struct CEachFileStatus {
|
||||
pub(crate) path: CStringWrapper,
|
||||
pub(crate) reason: u8,
|
||||
pub(crate) message: CStringWrapper,
|
||||
}
|
||||
|
||||
impl EachFileStatus {
|
||||
pub(crate) fn to_c_struct(&self) -> CEachFileStatus {
|
||||
CEachFileStatus {
|
||||
path: CStringWrapper::from(&self.path),
|
||||
reason: self.reason as u8,
|
||||
message: CStringWrapper::from(&self.message),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn from_c_struct(c_struct: &CEachFileStatus) -> EachFileStatus {
|
||||
EachFileStatus {
|
||||
path: c_struct.path.to_string(),
|
||||
reason: Reason::from(c_struct.reason),
|
||||
message: c_struct.message.to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub(crate) struct CProgress {
|
||||
pub(crate) common_data: CommonProgress,
|
||||
pub(crate) sizes: CStringWrapper,
|
||||
pub(crate) processed: CStringWrapper,
|
||||
pub(crate) extras: CStringWrapper,
|
||||
}
|
||||
|
||||
impl Progress {
|
||||
pub(crate) fn to_c_struct(&self, sizes: &str, processed: &str, extras: &str) -> CProgress {
|
||||
CProgress {
|
||||
common_data: self.common_data.clone(),
|
||||
sizes: CStringWrapper::from(sizes),
|
||||
processed: CStringWrapper::from(processed),
|
||||
extras: CStringWrapper::from(extras),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn from_c_struct(c_struct: &CProgress) -> Self {
|
||||
Progress {
|
||||
common_data: c_struct.common_data.clone(),
|
||||
sizes: split_string(&mut c_struct.sizes.to_string())
|
||||
.map(|s| s.parse::<i64>().unwrap())
|
||||
.collect(),
|
||||
processed: split_string(&mut c_struct.processed.to_string())
|
||||
.map(|s| s.parse::<usize>().unwrap())
|
||||
.collect(),
|
||||
extras: string_to_hashmap(&mut c_struct.extras.to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub(crate) struct CTaskInfo {
|
||||
pub(crate) bundle: CStringWrapper,
|
||||
pub(crate) url: CStringWrapper,
|
||||
pub(crate) data: CStringWrapper,
|
||||
pub(crate) token: CStringWrapper,
|
||||
pub(crate) form_items_ptr: *const CFormItem,
|
||||
pub(crate) form_items_len: u32,
|
||||
pub(crate) file_specs_ptr: *const CFileSpec,
|
||||
pub(crate) file_specs_len: u32,
|
||||
pub(crate) title: CStringWrapper,
|
||||
pub(crate) description: CStringWrapper,
|
||||
pub(crate) mime_type: CStringWrapper,
|
||||
pub(crate) progress: CProgress,
|
||||
pub(crate) each_file_status_ptr: *const CEachFileStatus,
|
||||
pub(crate) each_file_status_len: u32,
|
||||
pub(crate) common_data: CommonTaskInfo,
|
||||
}
|
||||
|
||||
impl TaskInfo {
|
||||
pub(crate) fn to_c_struct(&self, info: &InfoSet) -> CTaskInfo {
|
||||
CTaskInfo {
|
||||
bundle: CStringWrapper::from(&self.bundle),
|
||||
url: CStringWrapper::from(&self.url),
|
||||
data: CStringWrapper::from(&self.data),
|
||||
token: CStringWrapper::from(&self.token),
|
||||
form_items_ptr: info.form_items.as_ptr(),
|
||||
form_items_len: info.form_items.len() as u32,
|
||||
file_specs_ptr: info.file_specs.as_ptr(),
|
||||
file_specs_len: info.file_specs.len() as u32,
|
||||
title: CStringWrapper::from(&self.title),
|
||||
description: CStringWrapper::from(&self.description),
|
||||
mime_type: CStringWrapper::from(&self.mime_type),
|
||||
progress: self
|
||||
.progress
|
||||
.to_c_struct(&info.sizes, &info.processed, &info.extras),
|
||||
each_file_status_ptr: info.each_file_status.as_ptr(),
|
||||
each_file_status_len: info.each_file_status.len() as u32,
|
||||
common_data: self.common_data,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn from_c_struct(c_struct: &CTaskInfo) -> Self {
|
||||
let progress = Progress::from_c_struct(&c_struct.progress);
|
||||
let extras = progress.extras.clone();
|
||||
|
||||
// Removes this logic if api9 and api10 matched.
|
||||
let mime_type = if c_struct.common_data.version == Version::API9 as u8 {
|
||||
c_struct.mime_type.to_string()
|
||||
} else {
|
||||
String::new()
|
||||
};
|
||||
|
||||
let task_info = TaskInfo {
|
||||
bundle: c_struct.bundle.to_string(),
|
||||
url: c_struct.url.to_string(),
|
||||
data: c_struct.data.to_string(),
|
||||
token: c_struct.token.to_string(),
|
||||
form_items: build_vec(
|
||||
c_struct.form_items_ptr,
|
||||
c_struct.form_items_len as usize,
|
||||
FormItem::from_c_struct,
|
||||
),
|
||||
file_specs: build_vec(
|
||||
c_struct.file_specs_ptr,
|
||||
c_struct.file_specs_len as usize,
|
||||
FileSpec::from_c_struct,
|
||||
),
|
||||
title: c_struct.title.to_string(),
|
||||
description: c_struct.description.to_string(),
|
||||
mime_type,
|
||||
progress,
|
||||
extras,
|
||||
each_file_status: build_vec(
|
||||
c_struct.each_file_status_ptr,
|
||||
c_struct.each_file_status_len as usize,
|
||||
EachFileStatus::from_c_struct,
|
||||
),
|
||||
common_data: c_struct.common_data,
|
||||
};
|
||||
|
||||
unsafe { DeleteCFormItem(c_struct.form_items_ptr) };
|
||||
unsafe { DeleteCFileSpec(c_struct.file_specs_ptr) };
|
||||
unsafe { DeleteCEachFileStatus(c_struct.each_file_status_ptr) };
|
||||
task_info
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub(crate) struct CUpdateInfo {
|
||||
pub(crate) mtime: u64,
|
||||
pub(crate) reason: u8,
|
||||
pub(crate) tries: u32,
|
||||
pub(crate) mime_type: CStringWrapper,
|
||||
pub(crate) progress: CProgress,
|
||||
pub(crate) each_file_status_ptr: *const CEachFileStatus,
|
||||
pub(crate) each_file_status_len: u32,
|
||||
}
|
||||
|
||||
impl UpdateInfo {
|
||||
pub(crate) fn to_c_struct(
|
||||
&self,
|
||||
sizes: &str,
|
||||
processed: &str,
|
||||
extras: &str,
|
||||
each_file_status: &Vec<CEachFileStatus>,
|
||||
) -> CUpdateInfo {
|
||||
CUpdateInfo {
|
||||
mtime: self.mtime,
|
||||
reason: self.reason,
|
||||
tries: self.tries,
|
||||
mime_type: CStringWrapper::from(self.mime_type.as_str()),
|
||||
progress: self.progress.to_c_struct(sizes, processed, extras),
|
||||
each_file_status_ptr: each_file_status.as_ptr(),
|
||||
each_file_status_len: each_file_status.len() as u32,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub(crate) struct RequestTaskMsg {
|
||||
pub(crate) task_id: u32,
|
||||
pub(crate) uid: i32,
|
||||
pub(crate) action: u8,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[repr(C)]
|
||||
pub(crate) struct NetworkInfo {
|
||||
pub(crate) network_type: Network,
|
||||
pub(crate) is_metered: bool,
|
||||
pub(crate) is_roaming: bool,
|
||||
}
|
||||
|
||||
impl TaskConfig {
|
||||
pub(crate) fn to_c_struct(&self, task_id: u32, uid: u64) -> CTaskConfig {
|
||||
let form_items: Vec<CFormItem> = self.form_items.iter().map(|x| x.to_c_struct()).collect();
|
||||
let file_specs: Vec<CFileSpec> = self.file_specs.iter().map(|x| x.to_c_struct()).collect();
|
||||
let body_file_names: Vec<CStringWrapper> = self
|
||||
.body_file_names
|
||||
.iter()
|
||||
.map(CStringWrapper::from)
|
||||
.collect();
|
||||
CTaskConfig {
|
||||
bundle: CStringWrapper::from(&self.bundle),
|
||||
url: CStringWrapper::from(&self.url),
|
||||
title: CStringWrapper::from(&self.title),
|
||||
description: CStringWrapper::from(&self.description),
|
||||
method: CStringWrapper::from(&self.method),
|
||||
headers: CStringWrapper::from(&hashmap_to_string(&self.headers)),
|
||||
data: CStringWrapper::from(&self.data),
|
||||
token: CStringWrapper::from(&self.token),
|
||||
extras: CStringWrapper::from(&hashmap_to_string(&self.extras)),
|
||||
version: self.version as u8,
|
||||
form_items_ptr: form_items.as_ptr(),
|
||||
form_items_len: form_items.len() as u32,
|
||||
file_specs_ptr: file_specs.as_ptr(),
|
||||
file_specs_len: file_specs.len() as u32,
|
||||
body_file_names_ptr: body_file_names.as_ptr() as *const CStringWrapper,
|
||||
body_file_names_len: body_file_names.len() as u32,
|
||||
common_data: CommonCTaskConfig {
|
||||
task_id,
|
||||
uid,
|
||||
action: self.common_data.action as u8,
|
||||
mode: self.common_data.mode as u8,
|
||||
cover: self.common_data.cover,
|
||||
network: self.common_data.network as u8,
|
||||
metered: self.common_data.metered,
|
||||
roaming: self.common_data.roaming,
|
||||
retry: self.common_data.retry,
|
||||
redirect: self.common_data.redirect,
|
||||
index: self.common_data.index,
|
||||
begins: self.common_data.begins,
|
||||
ends: self.common_data.ends,
|
||||
gauge: self.common_data.gauge,
|
||||
precise: self.common_data.precise,
|
||||
priority: self.common_data.priority,
|
||||
background: self.common_data.background,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn from_c_struct(c_struct: &CTaskConfig) -> Self {
|
||||
let task_config = TaskConfig {
|
||||
bundle: c_struct.bundle.to_string(),
|
||||
url: c_struct.url.to_string(),
|
||||
title: c_struct.title.to_string(),
|
||||
description: c_struct.description.to_string(),
|
||||
method: c_struct.method.to_string(),
|
||||
headers: string_to_hashmap(&mut c_struct.headers.to_string()),
|
||||
data: c_struct.data.to_string(),
|
||||
token: c_struct.token.to_string(),
|
||||
extras: string_to_hashmap(&mut c_struct.extras.to_string()),
|
||||
version: Version::from(c_struct.version),
|
||||
form_items: build_vec(
|
||||
c_struct.form_items_ptr,
|
||||
c_struct.form_items_len as usize,
|
||||
FormItem::from_c_struct,
|
||||
),
|
||||
file_specs: build_vec(
|
||||
c_struct.file_specs_ptr,
|
||||
c_struct.file_specs_len as usize,
|
||||
FileSpec::from_c_struct,
|
||||
),
|
||||
body_file_names: build_vec(
|
||||
c_struct.body_file_names_ptr,
|
||||
c_struct.body_file_names_len as usize,
|
||||
CStringWrapper::to_string,
|
||||
),
|
||||
common_data: CommonTaskConfig {
|
||||
task_id: c_struct.common_data.task_id,
|
||||
uid: c_struct.common_data.uid,
|
||||
action: Action::from(c_struct.common_data.action),
|
||||
mode: Mode::from(c_struct.common_data.mode),
|
||||
cover: c_struct.common_data.cover,
|
||||
network: Network::from(c_struct.common_data.network),
|
||||
metered: c_struct.common_data.metered,
|
||||
roaming: c_struct.common_data.roaming,
|
||||
retry: c_struct.common_data.retry,
|
||||
redirect: c_struct.common_data.redirect,
|
||||
index: c_struct.common_data.index,
|
||||
begins: c_struct.common_data.begins,
|
||||
ends: c_struct.common_data.ends,
|
||||
gauge: c_struct.common_data.gauge,
|
||||
precise: c_struct.common_data.precise,
|
||||
priority: c_struct.common_data.priority,
|
||||
background: c_struct.common_data.background,
|
||||
},
|
||||
};
|
||||
unsafe { DeleteCFormItem(c_struct.form_items_ptr) };
|
||||
unsafe { DeleteCFileSpec(c_struct.file_specs_ptr) };
|
||||
unsafe { DeleteCStringPtr(c_struct.body_file_names_ptr) };
|
||||
task_config
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
pub(crate) fn GetNetworkInfo() -> *const NetworkInfo;
|
||||
pub(crate) fn DeleteCTaskInfo(ptr: *const CTaskInfo);
|
||||
pub(crate) fn RecordRequestTaskInfo(taskInfo: *const CTaskInfo) -> bool;
|
||||
pub(crate) fn DeleteCEachFileStatus(ptr: *const CEachFileStatus);
|
||||
pub(crate) fn UpdateRequestTaskInfo(taskId: u32, updateInfo: *const CUpdateInfo) -> bool;
|
||||
pub(crate) fn HasRequestTaskRecord(taskId: u32) -> bool;
|
||||
pub(crate) fn PublishStateChangeEvents(
|
||||
bundleName: *const c_char,
|
||||
bundleNameLen: u32,
|
||||
taskId: u32,
|
||||
state: i32,
|
||||
);
|
||||
|
||||
pub(crate) fn RequestBackgroundNotify(
|
||||
msg: RequestTaskMsg,
|
||||
path: *const c_char,
|
||||
pathLen: i32,
|
||||
percent: u32,
|
||||
);
|
||||
|
||||
}
|
185
services/service/request/src/task/info.rs
Normal file
185
services/service/request/src/task/info.rs
Normal file
@ -0,0 +1,185 @@
|
||||
// Copyright (C) 2023 Huawei Device Co., Ltd.
|
||||
// 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.
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
use super::ffi::CEachFileStatus;
|
||||
use super::notify::{EachFileStatus, Progress};
|
||||
use crate::task::config::Action;
|
||||
use crate::task::reason::Reason;
|
||||
use crate::utils::c_wrapper::{CFileSpec, CFormItem};
|
||||
use crate::utils::form_item::{FileSpec, FormItem};
|
||||
use crate::utils::hashmap_to_string;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct TaskInfo {
|
||||
pub(crate) bundle: String,
|
||||
pub(crate) url: String,
|
||||
pub(crate) data: String,
|
||||
pub(crate) token: String,
|
||||
pub(crate) form_items: Vec<FormItem>,
|
||||
pub(crate) file_specs: Vec<FileSpec>,
|
||||
pub(crate) title: String,
|
||||
pub(crate) description: String,
|
||||
pub(crate) mime_type: String,
|
||||
pub(crate) progress: Progress,
|
||||
pub(crate) extras: HashMap<String, String>,
|
||||
pub(crate) each_file_status: Vec<EachFileStatus>,
|
||||
pub(crate) common_data: CommonTaskInfo,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub(crate) struct CommonTaskInfo {
|
||||
pub(crate) task_id: u32,
|
||||
pub(crate) uid: u64,
|
||||
pub(crate) action: u8,
|
||||
pub(crate) mode: u8,
|
||||
pub(crate) ctime: u64,
|
||||
pub(crate) mtime: u64,
|
||||
pub(crate) reason: u8,
|
||||
pub(crate) gauge: bool,
|
||||
pub(crate) retry: bool,
|
||||
pub(crate) tries: u32,
|
||||
pub(crate) version: u8,
|
||||
pub(crate) priority: u32,
|
||||
}
|
||||
|
||||
pub(crate) struct InfoSet {
|
||||
pub(crate) form_items: Vec<CFormItem>,
|
||||
pub(crate) file_specs: Vec<CFileSpec>,
|
||||
pub(crate) sizes: String,
|
||||
pub(crate) processed: String,
|
||||
pub(crate) extras: String,
|
||||
pub(crate) each_file_status: Vec<CEachFileStatus>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Debug)]
|
||||
#[repr(u8)]
|
||||
pub(crate) enum Mode {
|
||||
BackGround = 0,
|
||||
FrontEnd,
|
||||
Any,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Debug)]
|
||||
#[repr(u8)]
|
||||
pub(crate) enum State {
|
||||
Initialized = 0x00,
|
||||
Waiting = 0x10,
|
||||
Running = 0x20,
|
||||
Retrying = 0x21,
|
||||
Paused = 0x30,
|
||||
Stopped = 0x31,
|
||||
Completed = 0x40,
|
||||
Failed = 0x41,
|
||||
Removed = 0x50,
|
||||
Created = 0x60,
|
||||
Any,
|
||||
}
|
||||
|
||||
pub(crate) struct UpdateInfo {
|
||||
pub(crate) mtime: u64,
|
||||
pub(crate) reason: u8,
|
||||
pub(crate) tries: u32,
|
||||
pub(crate) mime_type: String,
|
||||
pub(crate) progress: Progress,
|
||||
pub(crate) each_file_status: Vec<EachFileStatus>,
|
||||
}
|
||||
|
||||
impl From<u8> for Mode {
|
||||
fn from(value: u8) -> Self {
|
||||
match value {
|
||||
0 => Mode::BackGround,
|
||||
1 => Mode::FrontEnd,
|
||||
_ => Mode::Any,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u8> for State {
|
||||
fn from(value: u8) -> Self {
|
||||
match value {
|
||||
0 => State::Initialized,
|
||||
16 => State::Waiting,
|
||||
32 => State::Running,
|
||||
33 => State::Retrying,
|
||||
48 => State::Paused,
|
||||
49 => State::Stopped,
|
||||
64 => State::Completed,
|
||||
65 => State::Failed,
|
||||
80 => State::Removed,
|
||||
96 => State::Created,
|
||||
_ => State::Any,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TaskInfo {
|
||||
pub(crate) fn build_info_set(&self) -> InfoSet {
|
||||
InfoSet {
|
||||
form_items: self.form_items.iter().map(|x| x.to_c_struct()).collect(),
|
||||
file_specs: self.file_specs.iter().map(|x| x.to_c_struct()).collect(),
|
||||
sizes: format!("{:?}", self.progress.sizes),
|
||||
processed: format!("{:?}", self.progress.processed),
|
||||
extras: hashmap_to_string(&self.extras),
|
||||
each_file_status: self
|
||||
.each_file_status
|
||||
.iter()
|
||||
.map(|x| x.to_c_struct())
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct DumpAllInfo {
|
||||
pub(crate) vec: Vec<DumpAllEachInfo>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct DumpAllEachInfo {
|
||||
pub(crate) task_id: u32,
|
||||
pub(crate) action: Action,
|
||||
pub(crate) state: State,
|
||||
pub(crate) reason: Reason,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct DumpOneInfo {
|
||||
pub(crate) task_id: u32,
|
||||
pub(crate) action: Action,
|
||||
pub(crate) state: State,
|
||||
pub(crate) reason: Reason,
|
||||
pub(crate) total_size: i64,
|
||||
pub(crate) tran_size: usize,
|
||||
pub(crate) url: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Debug, Eq, PartialOrd, Ord)]
|
||||
pub(crate) enum ApplicationState {
|
||||
Foreground = 2,
|
||||
Background = 4,
|
||||
Terminated = 5,
|
||||
}
|
||||
|
||||
impl From<u8> for ApplicationState {
|
||||
fn from(value: u8) -> Self {
|
||||
match value {
|
||||
2 => ApplicationState::Foreground,
|
||||
4 => ApplicationState::Background,
|
||||
5 => ApplicationState::Terminated,
|
||||
_ => panic!("wrong application value"),
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user