multiuser

Signed-off-by: fqwert <yanglv2@huawei.com>
Change-Id: I22b2ad5dd1d4c75c923674fbf98171318ba07908
This commit is contained in:
fqwert 2024-05-18 14:37:46 +08:00
parent 54485c5afd
commit 4f63d3c85c
37 changed files with 553 additions and 292 deletions

View File

@ -28,6 +28,7 @@
],
"deps": {
"components": [
"os_account",
"samgr",
"ipc",
"certificate_manager",

View File

@ -22,7 +22,9 @@
"ohos.permission.GET_NETWORK_INFO",
"ohos.permission.CONNECTIVITY_INTERNAL",
"ohos.permission.SEND_TASK_COMPLETE_EVENT",
"ohos.permission.ACCESS_CERT_MANAGER"
"ohos.permission.ACCESS_CERT_MANAGER",
"ohos.permission.INTERACT_ACROSS_LOCAL_ACCOUNTS_EXTENSION",
"ohos.permission.MANAGE_LOCAL_ACCOUNTS"
]
}
]

View File

@ -9,9 +9,15 @@
"dump_level": 1,
"start-on-demand": {
"commonevent": [
{
{
"name": "usual.event.CONNECTIVITY_CHANGE",
"value": "3"
},
{
"name": "usual.event.USER_REMOVED"
},
{
"name": "usual.event.USER_SWITCHED"
}
]
}

View File

@ -71,6 +71,7 @@ enum Reason : uint32_t {
IO_ERROR,
UNSUPPORT_RANGE_REQUEST,
OTHERS_ERROR,
ACCOUNT_STOPPED,
};
enum class SubscribeType : uint32_t {

View File

@ -14,6 +14,22 @@
import("//base/request/request/request_aafwk.gni")
import("//build/ohos.gni")
rust_cxx("download_server_cxx_gen") {
sources = [
"src/manage/account.rs",
"src/task/ffi.rs",
]
}
config("download_server_cxx_config") {
visibility = [ ":*" ]
include_dirs = [
"include",
"../common/include",
"${target_gen_dir}/src",
]
}
ohos_static_library("download_server_cxx") {
sanitize = {
integer_overflow = true
@ -25,7 +41,10 @@ ohos_static_library("download_server_cxx") {
}
stack_protector_ret = true
public_configs = [ ":download_server_cxx_config" ]
sources = [
"src/cxx/account.cpp",
"src/cxx/application_state_observer.cpp",
"src/cxx/background_notification.cpp",
"src/cxx/c_check_permission.cpp",
@ -42,11 +61,7 @@ ohos_static_library("download_server_cxx") {
"src/cxx/request_cert_mgr_adapter.cpp",
"src/cxx/url_policy.cpp",
]
include_dirs = [
"include",
"../common/include",
]
sources += get_target_outputs(":download_server_cxx_gen")
external_deps = [
"ability_base:base",
@ -64,6 +79,7 @@ ohos_static_library("download_server_cxx") {
"hilog:libhilog",
"ipc:ipc_single",
"netmanager_base:net_conn_manager_if",
"os_account:os_account_innerkits",
"relational_store:native_appdatafwk",
"relational_store:native_dataability",
"relational_store:native_rdb",
@ -71,7 +87,10 @@ ohos_static_library("download_server_cxx") {
"samgr:samgr_proxy",
]
deps = [ "//third_party/rust/crates/cxx:cxx_cppdeps" ]
deps = [
":download_server_cxx_gen",
"//third_party/rust/crates/cxx:cxx_cppdeps",
]
defines = []
if (request_telephony_core_service && request_telephony_cellular_data) {

View File

@ -0,0 +1,84 @@
/*
* Copyright (c) 2024 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.
*/
#ifndef ACCOUNT_H
#define ACCOUNT_H
#include <memory>
#include <vector>
#include "cxx.h"
#include "os_account_info.h"
#include "os_account_manager.h"
#include "os_account_subscribe_info.h"
#include "os_account_subscriber.h"
#include "refbase.h"
namespace OHOS::Request {
using namespace OHOS::AccountSA;
struct TaskManagerTx;
class SubscriberWrapper : public OsAccountSubscriber {
public:
explicit SubscriberWrapper(
OS_ACCOUNT_SUBSCRIBE_TYPE type, rust::box<TaskManagerTx> task_manager,
rust::fn<void(const int &id, const TaskManagerTx &task_manager)>
on_accounts_changed,
rust::fn<void(const int &newId, const int &oldId,
const TaskManagerTx &task_manager)>
on_accounts_switch);
~SubscriberWrapper();
virtual void OnAccountsChanged(const int &id) override;
virtual void OnAccountsSwitch(const int &newId, const int &oldId) override;
private:
TaskManagerTx *task_manager_;
rust::fn<void(const int &id, const TaskManagerTx &task_manager)>
on_accounts_changed_;
rust::fn<void(const int &newId, const int &oldId,
const TaskManagerTx &task_manager)>
on_accounts_switch_;
};
int RegistryAccountSubscriber(
OS_ACCOUNT_SUBSCRIBE_TYPE type, rust::box<TaskManagerTx> task_manager,
rust::fn<void(const int &id, const TaskManagerTx &task_manager)>
on_accounts_changed,
rust::fn<void(const int &newId, const int &oldId,
const TaskManagerTx &task_manager)>
on_accounts_switch);
inline ErrCode GetForegroundOsAccount(int &account) {
return OsAccountManager::GetForegroundOsAccountLocalId(account);
}
inline ErrCode GetBackgroundOsAccounts(rust::vec<int> &accounts) {
auto v = std::vector<int32_t>();
auto ret = OsAccountManager::GetBackgroundOsAccountLocalIds(v);
if (ret == 0) {
for (auto &account : v) {
accounts.push_back(account);
};
}
return ret;
}
inline ErrCode GetOsAccountLocalIdFromUid(const int uid, int &id) {
return OsAccountManager::GetOsAccountLocalIdFromUid(uid, id);
}
} // namespace OHOS::Request
#endif // ACCOUNT_H

View File

@ -18,23 +18,13 @@
#include <stdint.h>
#include <sys/types.h>
#include "c_string_wrapper.h"
#include "cxx.h"
#ifdef __cplusplus
extern "C" {
#endif
namespace OHOS::Request {
struct RequestTaskMsg;
struct RequestTaskMsg {
uint32_t taskId;
pid_t uid;
uint8_t action;
};
void RequestBackgroundNotify(RequestTaskMsg msg, rust::str filePath, rust::str fileName, uint32_t percent);
void RequestBackgroundNotify(
RequestTaskMsg msg, CStringWrapper wrappedPath, CStringWrapper wrappedFileName, uint32_t percent);
#ifdef __cplusplus
}
#endif
} // namespace OHOS::Request
#endif // REQUEST_BACKGROUND_NOTIFICATION_H

View File

@ -16,6 +16,8 @@
#ifndef C_REQUEST_DATABASE_H
#define C_REQUEST_DATABASE_H
#include <stdint.h>
#include <cstdint>
#include <vector>
@ -24,6 +26,7 @@
#include "c_progress.h"
#include "c_task_config.h"
#include "c_task_info.h"
#include "cxx.h"
#include "network_adapter.h"
#include "rdb_errno.h"
#include "rdb_helper.h"
@ -123,6 +126,8 @@ public:
std::shared_ptr<OHOS::NativeRdb::ResultSet> Query(
const OHOS::NativeRdb::AbsRdbPredicates &predicates, const std::vector<std::string> &columns);
bool Delete(const OHOS::NativeRdb::AbsRdbPredicates &predicates);
int DeleteAllAccountTasks(int user_id);
int OnAccountChange(int user_id);
private:
RequestDataBase();
@ -131,6 +136,11 @@ private:
std::shared_ptr<OHOS::NativeRdb::RdbStore> store_;
};
inline RequestDataBase *GetDatabaseInstance()
{
return &RequestDataBase::GetInstance();
}
class RequestDBOpenCallback : public OHOS::NativeRdb::RdbOpenCallback {
public:
int OnCreate(OHOS::NativeRdb::RdbStore &rdbStore) override;

View File

@ -17,15 +17,13 @@
#define COMMON_EVENT_NOTIFY_H
#include <cstdint>
#ifdef __cplusplus
extern "C" {
#endif
constexpr const char *EVENT_NAME_COMPLETE = "ohos.request.event.COMPLETE";
void PublishStateChangeEvents(const char *bundleName, uint32_t len, uint32_t taskId, int32_t state);
#include "cxx.h"
namespace OHOS::Request {
void PublishStateChangeEvent(rust::str bundleName, uint32_t taskId, int32_t state);
#ifdef __cplusplus
}
#endif
#endif // COMMON_EVENT_NOTIFY_H

View File

@ -19,11 +19,11 @@ use hisysevent::{build_number_param, write, EventType};
use samgr::definition::DOWNLOAD_SERVICE_ID;
use system_ability_fwk::ability::{Ability, Handler};
use crate::manage::account::update_accounts;
use crate::manage::network::listener::NetworkChangeListener;
use crate::manage::{SystemConfigManager, TaskManager};
use crate::manage::{account, SystemConfigManager, TaskManager};
use crate::service::client::ClientManager;
use crate::service::runcount::RunCountManager;
pub(crate) static mut PANIC_INFO: Option<String> = None;
use crate::manage::events::TaskManagerEvent;
use crate::manage::task_manager::TaskManagerTx;
@ -57,11 +57,8 @@ impl RequestAbility {
task_manager: Mutex::new(None),
}
}
}
impl Ability for RequestAbility {
/// Callback to deal safwk onstart for this system_ability
fn on_start(&self, handler: Handler) {
fn init(&self, handler: Handler) {
info!("ability init");
std::panic::set_hook(Box::new(|info| unsafe {
@ -76,6 +73,8 @@ impl Ability for RequestAbility {
.unwrap();
info!("ylong_runtime init succeed");
update_accounts();
let runcount_manager = RunCountManager::init();
info!("runcount_manager init succeed");
@ -102,10 +101,27 @@ impl Ability for RequestAbility {
let stub = RequestServiceStub::new(task_manager, client_manger, runcount_manager);
info!("ability init succeed");
info!("ability publish succeed");
if !handler.publish(stub) {
service_start_fault();
}
info!("ability publish succeed");
}
}
impl Ability for RequestAbility {
fn on_start_with_reason(
&self,
reason: system_ability_fwk::cxx_share::SystemAbilityOnDemandReason,
handler: Handler,
) {
info!("on_start_with_reason: {:?}", reason);
if reason.name == "usual.event.USER_REMOVED" {
let user_id = reason.value.parse::<i32>().unwrap();
account::remove_account_tasks(user_id);
self.init(handler);
} else {
self.init(handler);
}
}
fn on_device_level_changed(&self, change_type: i32, level: i32, action: String) {

View File

@ -0,0 +1,69 @@
/*
* Copyright (c) 2024 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.
*/
#include "account.h"
#include <memory>
#include "cxx.h"
#include "log.h"
#include "os_account_info.h"
#include "os_account_manager.h"
#include "os_account_subscribe_info.h"
#include "os_account_subscriber.h"
namespace OHOS::Request {
SubscriberWrapper::SubscriberWrapper(OS_ACCOUNT_SUBSCRIBE_TYPE type, rust::box<TaskManagerTx> task_manager,
rust::fn<void(const int &id, const TaskManagerTx &task_manager)> on_accounts_changed,
rust::fn<void(const int &newId, const int &oldId, const TaskManagerTx &task_manager)> on_accounts_switch)
: OsAccountSubscriber(OsAccountSubscribeInfo(type, ""))
{
task_manager_ = task_manager.into_raw();
on_accounts_changed_ = on_accounts_changed;
on_accounts_switch_ = on_accounts_switch;
}
SubscriberWrapper::~SubscriberWrapper()
{
rust::box<TaskManagerTx>::from_raw(task_manager_);
}
void SubscriberWrapper::OnAccountsChanged(const int &id)
{
REQUEST_HILOGI("SubscriberWrapper::resume account tasks=%{public}d", id);
on_accounts_changed_(id, *task_manager_);
}
void SubscriberWrapper::OnAccountsSwitch(const int &newId, const int &oldId)
{
REQUEST_HILOGI("SubscriberWrapper::OnAccountsSwitch newId=%{public}d, oldId=%{public}d", newId, oldId);
on_accounts_switch_(newId, oldId, *task_manager_);
}
int RegistryAccountSubscriber(OS_ACCOUNT_SUBSCRIBE_TYPE type, rust::box<TaskManagerTx> task_manager,
rust::fn<void(const int &id, const TaskManagerTx &task_manager)> on_accounts_changed,
rust::fn<void(const int &newId, const int &oldId, const TaskManagerTx &task_manager)> on_accounts_switch)
{
auto const Wrapper = std::static_pointer_cast<OsAccountSubscriber>(
std::make_shared<SubscriberWrapper>(type, std::move(task_manager), on_accounts_changed, on_accounts_switch));
return OsAccountManager::SubscribeOsAccount(Wrapper);
}
int GetForegroundOsAccountLocalId(int &id)
{
return OsAccountManager::GetForegroundOsAccountLocalId(id);
}
} // namespace OHOS::Request

View File

@ -22,20 +22,22 @@
#include "notification_content.h"
#include "notification_helper.h"
#include "string_wrapper.h"
#include "task/ffi.rs.h"
#include "want_params.h"
namespace OHOS::Request {
using namespace OHOS::Notification;
static constexpr uint8_t DOWNLOAD_ACTION = 0;
void RequestBackgroundNotify(
RequestTaskMsg msg, CStringWrapper wrappedPath, CStringWrapper wrappedFileName, uint32_t percent)
void RequestBackgroundNotify(RequestTaskMsg msg, rust::str filePath, rust::str fileName, uint32_t percent)
{
REQUEST_HILOGD("Background Notification, percent is %{public}d", percent);
auto requestTemplate = std::make_shared<NotificationTemplate>();
std::string filepath(wrappedPath.cStr, wrappedPath.len);
requestTemplate->SetTemplateName("downloadTemplate");
OHOS::AAFwk::WantParams wantParams;
wantParams.SetParam("progressValue", OHOS::AAFwk::Integer::Box(percent));
wantParams.SetParam("fileName", OHOS::AAFwk::String::Box(filepath));
wantParams.SetParam("fileName", OHOS::AAFwk::String::Box(std::string(filePath)));
std::shared_ptr<NotificationNormalContent> normalContent = std::make_shared<NotificationNormalContent>();
if (msg.action == DOWNLOAD_ACTION) {
wantParams.SetParam("title", OHOS::AAFwk::String::Box("Download"));
@ -45,10 +47,10 @@ void RequestBackgroundNotify(
normalContent->SetTitle("Upload");
}
requestTemplate->SetTemplateData(std::make_shared<OHOS::AAFwk::WantParams>(wantParams));
std::string contentText(wrappedFileName.cStr, wrappedFileName.len);
normalContent->SetText(contentText);
normalContent->SetText(std::string(fileName));
auto content = std::make_shared<NotificationContent>(normalContent);
NotificationRequest req(msg.taskId);
NotificationRequest req(msg.task_id);
req.SetCreatorUid(msg.uid);
req.SetContent(content);
req.SetTemplate(requestTemplate);
@ -57,4 +59,6 @@ void RequestBackgroundNotify(
if (errCode != OHOS::ERR_OK) {
REQUEST_HILOGE("notification errCode: %{public}d", errCode);
}
}
} // namespace OHOS::Request

View File

@ -16,10 +16,14 @@
#include "c_request_database.h"
#include <securec.h>
#include <stdint.h>
#include <algorithm>
#include <cstdint>
#include <string>
#include "c_enumration.h"
#include "cxx.h"
#include "log.h"
#include "rdb_errno.h"
@ -92,6 +96,21 @@ bool RequestDataBase::Delete(const OHOS::NativeRdb::AbsRdbPredicates &predicates
return ret == OHOS::NativeRdb::E_OK;
}
int RequestDataBase::DeleteAllAccountTasks(int user_id)
{
REQUEST_HILOGI("Delete all account tasks for user: %{public}d", user_id);
std::string Delete = "DELETE from request_task WHERE uid/200000 = " + std::to_string(user_id);
return store_->ExecuteSql(Delete);
}
int RequestDataBase::OnAccountChange(int user_id)
{
std::string OnAccountChange = "UPDATE request_task SET reason = 4 WHERE uid/200000 = " + std::to_string(user_id)
+ " AND state = " + std::to_string(static_cast<uint8_t>(State::WAITING))
+ " AND reason = 21";
return store_->ExecuteSql(OnAccountChange);
}
int RequestDBOpenCallback::OnCreate(OHOS::NativeRdb::RdbStore &store)
{
return OHOS::NativeRdb::E_OK;
@ -1440,4 +1459,4 @@ CStringWrapper GetAppBundle(uint64_t uid)
res = WrapperCString(temp);
return res;
}
}

View File

@ -22,25 +22,26 @@
#include "common_event_publish_info.h"
#include "log.h"
namespace OHOS::Request {
using namespace OHOS::EventFwk;
void PublishStateChangeEvents(const char *bundleName, uint32_t len, uint32_t taskId, int32_t state)
void PublishStateChangeEvent(rust::str bundleName, uint32_t taskId, int32_t state)
{
REQUEST_HILOGD("PublishStateChangeEvents in.");
static constexpr const char *eventAction = "ohos.request.event.COMPLETE";
std::string bundle(bundleName, len);
Want want;
want.SetAction(eventAction);
want.SetBundle(bundle);
want.SetBundle(std::string(bundleName));
std::string data = std::to_string(taskId);
CommonEventData commonData(want, state, data);
CommonEventPublishInfo publishInfo;
publishInfo.SetBundleName(bundle);
publishInfo.SetBundleName(std::string(bundleName));
bool res = CommonEventManager::PublishCommonEvent(commonData, publishInfo);
if (!res) {
REQUEST_HILOGE("PublishStateChangeEvents failed!");
}
}
}
} // namespace OHOS::Request

View File

@ -14,7 +14,6 @@
#[derive(Clone, Copy, PartialEq, Debug)]
pub(crate) enum ErrorCode {
ErrOk = 0,
_UnloadingSA = 1,
IpcSizeTooLarge = 2,
ChannelNotOpen = 5,
Permission = 201,
@ -23,7 +22,6 @@ pub(crate) enum ErrorCode {
FileOperationErr = 13400001,
Other = 13499999,
TaskEnqueueErr = 21900004,
_TaskModeErr,
TaskNotFound,
TaskNotFound = 21900006,
TaskStateErr,
}

View File

@ -12,7 +12,6 @@
// limitations under the License.
//! This create implement the request proxy and stub
#![feature(io_error_other)]
#![warn(
missing_docs,
@ -24,8 +23,8 @@
#[macro_use]
mod hilog;
mod ability;
mod error;
mod init;
mod manage;
mod service;
mod sys_event;

View File

@ -0,0 +1,184 @@
// Copyright (C) 2024 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::{AtomicI32, Ordering};
use std::sync::Mutex;
pub(crate) use ffi::*;
use super::TaskManager;
use crate::manage::events::TaskManagerEvent;
use crate::manage::task_manager::TaskManagerTx;
#[derive(Debug)]
pub(crate) enum AccountEvent {
Switch,
Active,
Remove(i32),
}
const DEFAULT_USER_ID: i32 = 100;
static FOREGROUND_ACCOUNT: AtomicI32 = AtomicI32::new(DEFAULT_USER_ID);
static BACKGOUNFD_ACCOUNTS: Mutex<Vec<i32>> = Mutex::new(Vec::new());
#[allow(unreachable_pub)]
#[cxx::bridge(namespace = "OHOS::Request")]
mod ffi {
#[repr(i32)]
enum OS_ACCOUNT_SUBSCRIBE_TYPE {
INVALID_TYPE = -1,
ACTIVED = 0,
ACTIVATING,
UNLOCKED,
CREATED,
REMOVED,
STOPPING,
STOPPED,
SWITCHING,
SWITCHED,
}
extern "Rust" {
type TaskManagerTx;
}
unsafe extern "C++" {
include!("account.h");
include!("c_request_database.h");
include!("os_account_subscribe_info.h");
type OS_ACCOUNT_SUBSCRIBE_TYPE;
type RequestDataBase;
fn GetForegroundOsAccount(account: &mut i32) -> i32;
fn GetBackgroundOsAccounts(accounts: &mut Vec<i32>) -> i32;
fn GetOsAccountLocalIdFromUid(uid: i32, user_id: &mut i32) -> i32;
fn GetDatabaseInstance() -> *mut RequestDataBase;
fn DeleteAllAccountTasks(self: Pin<&mut RequestDataBase>, user_id: i32) -> i32;
fn OnAccountChange(self: Pin<&mut RequestDataBase>, user_id: i32) -> i32;
fn RegistryAccountSubscriber(
subscribe_type: OS_ACCOUNT_SUBSCRIBE_TYPE,
task_manager: Box<TaskManagerTx>,
on_accounts_changed: fn(&i32, task_manager: &TaskManagerTx),
on_accounts_switch: fn(&i32, &i32, task_manager: &TaskManagerTx),
) -> i32;
}
}
impl TaskManager {
pub(crate) async fn handle_account_event(&mut self, event: AccountEvent) {
update_accounts();
match event {
AccountEvent::Active => self.scheduler.on_user_change().await,
AccountEvent::Switch => self.scheduler.on_user_change().await,
AccountEvent::Remove(user_id) => remove_account_tasks(user_id),
}
}
}
pub(crate) fn remove_account_tasks(user_id: i32) {
info!("delte database task by user_id: {}", user_id);
let res =
unsafe { Pin::new_unchecked(&mut (*GetDatabaseInstance())).DeleteAllAccountTasks(user_id) };
info!("delete data task finished: {}", res);
if res != 0 {
error!("delete account tasks failed: {}", res);
}
}
pub(crate) fn is_foreground_user(uid: u64) -> bool {
get_user_id_from_uid(uid) == FOREGROUND_ACCOUNT.load(Ordering::Acquire)
}
pub(crate) fn is_active_user(uid: u64) -> bool {
get_user_id_from_uid(uid) == FOREGROUND_ACCOUNT.load(Ordering::Acquire)
|| BACKGOUNFD_ACCOUNTS
.lock()
.unwrap()
.contains(&get_user_id_from_uid(uid))
}
fn get_user_id_from_uid(uid: u64) -> i32 {
let mut user_id = 0;
let res = GetOsAccountLocalIdFromUid(uid as i32, &mut user_id);
if res != 0 {
error!("GetOsAccountLocalIdFromUid failed: {}", res);
}
user_id
}
pub(crate) fn update_accounts() {
let mut foreground_account = 0;
let res = GetForegroundOsAccount(&mut foreground_account);
if res != 0 {
error!("GetForegroundOsAccount failed: {}", res);
foreground_account = DEFAULT_USER_ID;
}
unsafe {
Pin::new_unchecked(&mut (*GetDatabaseInstance())).OnAccountChange(foreground_account);
}
{
let mut accounts = BACKGOUNFD_ACCOUNTS.lock().unwrap();
GetBackgroundOsAccounts(&mut accounts);
for account in accounts.iter() {
unsafe {
Pin::new_unchecked(&mut (*GetDatabaseInstance())).OnAccountChange(*account);
}
}
}
FOREGROUND_ACCOUNT.store(foreground_account, Ordering::Release);
}
pub(crate) fn registry_account_subscribe(task_manager: TaskManagerTx) {
info!("registry_account_subscribe");
let ret = RegistryAccountSubscriber(
OS_ACCOUNT_SUBSCRIBE_TYPE::SWITCHED,
Box::new(task_manager.clone()),
|_, _| {},
|_new_id, _old_id, task_manager| {
task_manager.send_event(TaskManagerEvent::Account(AccountEvent::Switch));
},
);
if ret != 0 {
error!("registry_account_switch_subscribe failed: {}", ret);
}
let ret = RegistryAccountSubscriber(
OS_ACCOUNT_SUBSCRIBE_TYPE::ACTIVED,
Box::new(task_manager.clone()),
|_id, task_manager| {
task_manager.send_event(TaskManagerEvent::Account(AccountEvent::Active));
},
|_, _, _| {},
);
if ret != 0 {
error!("registry_account_active_subscribe failed: {}", ret);
}
let ret = RegistryAccountSubscriber(
OS_ACCOUNT_SUBSCRIBE_TYPE::REMOVED,
Box::new(task_manager),
|id, task_manager| {
task_manager.send_event(TaskManagerEvent::Account(AccountEvent::Remove(*id)));
},
|_, _, _| {},
);
if ret != 0 {
error!("registry_account_active_subscribe failed: {}", ret);
}
}

View File

@ -11,8 +11,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use crate::ability::SYSTEM_CONFIG_MANAGER;
use crate::error::ErrorCode;
use crate::init::SYSTEM_CONFIG_MANAGER;
use crate::manage::app_state::{AppState, GetTopBundleName};
use crate::manage::TaskManager;
use crate::task::config::TaskConfig;

View File

@ -15,6 +15,7 @@ use std::fmt::Debug;
use ylong_runtime::sync::oneshot::{channel, Sender};
use super::account::AccountEvent;
use crate::error::ErrorCode;
use crate::task::config::{Action, TaskConfig, Version};
use crate::task::info::{ApplicationState, DumpAllInfo, DumpOneInfo, TaskInfo};
@ -42,6 +43,7 @@ pub(crate) enum TaskManagerEvent {
Schedule(ScheduleEvent),
Task(TaskEvent),
Device(i32),
Account(AccountEvent),
}
impl TaskManagerEvent {

View File

@ -11,15 +11,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
pub(crate) mod account;
pub(crate) mod app_state;
pub(crate) mod config;
pub(crate) mod database;
pub(crate) mod events;
pub(crate) mod network;
pub(crate) mod notifier;
pub(crate) mod scheduler;
pub(crate) mod task_manager;
pub(crate) mod notifier;
pub(crate) use config::{SystemConfig, SystemConfigManager};
pub(crate) use task_manager::TaskManager;

View File

@ -20,8 +20,8 @@ use qos::Qos;
use queue::{NotifyTask, RunningQueue};
use super::app_state::AppStateManagerTx;
use crate::ability::SYSTEM_CONFIG_MANAGER;
use crate::error::ErrorCode;
use crate::init::SYSTEM_CONFIG_MANAGER;
use crate::manage::database::Database;
use crate::manage::notifier::Notifier;
use crate::manage::scheduler::qos::{QosChanges, RssCapacity};
@ -86,7 +86,7 @@ impl Scheduler {
pub(crate) fn tasks(&self) -> impl Iterator<Item = &Arc<RequestTask>> {
self.upload_queue.tasks().chain(self.download_queue.tasks())
}
pub(crate) fn get_task(&self, uid: u64, task_id: u32) -> Option<&Arc<RequestTask>> {
self.upload_queue
.get_task(uid, task_id)
@ -183,6 +183,11 @@ impl Scheduler {
self.reschedule(changes).await;
}
pub(crate) async fn on_user_change(&mut self) {
let changes = self.qos.change_user();
self.reschedule(changes).await;
}
pub(crate) async fn on_rss_change(&mut self, level: i32) {
let new_rss = RssCapacity::new(level);
let changes = self.qos.change_rss(new_rss);

View File

@ -14,6 +14,7 @@
use std::cmp;
use std::ops::Deref;
use crate::manage::account::is_foreground_user;
use crate::manage::database::{Database, TaskQosInfo};
use crate::task::config::Action;
use crate::task::ffi::NetworkInfo;
@ -41,6 +42,10 @@ impl SortedApps {
self.inner = reload_all_app_from_database();
}
pub(crate) fn change_user(&mut self) {
self.inner = reload_all_app_from_database();
}
pub(crate) fn change_app_state(&mut self, uid: u64, state: ApplicationState) {
let mut need_remove_app = None;
@ -199,7 +204,13 @@ impl PartialEq for App {
impl PartialOrd for App {
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
Some(self.state.cmp(&other.state))
let self_is_foreground = is_foreground_user(self.uid);
let other_is_foreground = is_foreground_user(other.uid);
Some(
self_is_foreground
.cmp(&other_is_foreground)
.then(self.state.cmp(&other.state)),
)
}
}

View File

@ -67,6 +67,11 @@ impl Qos {
self.reschedule(Action::Any)
}
pub(crate) fn change_user(&mut self) -> QosChanges {
self.apps.change_user();
self.reschedule(Action::Any)
}
pub(crate) fn change_rss(&mut self, rss: RssCapacity) -> QosChanges {
self.capacity = rss;
self.reschedule(Action::Any)

View File

@ -11,7 +11,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use std::ops::Deref;
use std::sync::{Arc, Mutex};
use std::time::Duration;
@ -36,7 +35,7 @@ struct Inner {
impl SAKeeper {
pub(crate) fn new(tx: TaskManagerTx) -> Self {
info!("Countdown 60s future started");
let tx = tx.deref();
let tx = &tx.tx;
let handle = count_down(tx.clone());
Self {
tx: tx.clone(),

View File

@ -23,8 +23,8 @@ use keeper::SAKeeper;
pub(crate) use notify_task::NotifyTask;
use running_task::RunningTask;
use crate::ability::SYSTEM_CONFIG_MANAGER;
use crate::error::ErrorCode;
use crate::init::SYSTEM_CONFIG_MANAGER;
use crate::manage::app_state::AppStateManagerTx;
use crate::manage::database::Database;
use crate::manage::notifier::Notifier;

View File

@ -154,10 +154,12 @@ impl Drop for RunningTask {
if state == State::Waiting && reason == Reason::RunningTaskMeetLimits {
return;
}
let _ = self.tx.send(TaskManagerEvent::Task(TaskEvent::Finished(
self.task_id(),
self.uid(),
self.version(),
)));
let _ = self
.tx
.send_event(TaskManagerEvent::Task(TaskEvent::Finished(
self.task_id(),
self.uid(),
self.version(),
)));
}
}

View File

@ -21,8 +21,9 @@ use ylong_runtime::time::sleep;
use super::app_state::AppStateManagerTx;
// use super::app_state::AppStateManager;
use super::events::{ScheduleEvent, ServiceEvent, StateEvent, TaskEvent, TaskManagerEvent};
use crate::ability::PANIC_INFO;
use crate::error::ErrorCode;
use crate::init::PANIC_INFO;
use crate::manage::account::registry_account_subscribe;
use crate::manage::app_state::AppStateManager;
use crate::manage::database::Database;
use crate::manage::network::NetworkManager;
@ -51,9 +52,8 @@ const RESTORE_ALL_TASKS_INTERVAL: u64 = 10;
pub(crate) struct TaskManager {
pub(crate) scheduler: Scheduler,
pub(crate) database: Database,
#[allow(dead_code)]
pub(crate) tx: TaskManagerTx,
pub(crate) rx: TaskManagerRx,
pub(crate) app_state_manager: AppStateManagerTx,
pub(crate) client_manager: ClientManagerEntry,
@ -71,6 +71,7 @@ impl TaskManager {
let rx = TaskManagerRx::new(rx);
let app_state_manager = AppStateManager::init(client_manager.clone(), tx.clone());
registry_account_subscribe(tx.clone());
let task_manager = Self::new(
tx.clone(),
@ -110,13 +111,12 @@ impl TaskManager {
) -> Self {
Self {
scheduler: Scheduler::init(
tx.clone(),
tx,
runcount_manager,
app_state_manager.clone(),
client_manager.clone(),
),
database: Database::new(),
tx,
rx,
app_state_manager,
client_manager,
@ -147,6 +147,7 @@ impl TaskManager {
TaskManagerEvent::Device(level) => {
self.scheduler.on_rss_change(level).await;
}
TaskManagerEvent::Account(event) => self.handle_account_event(event).await,
}
debug!("TaskManager handles events finished");
@ -308,9 +309,10 @@ impl TaskManager {
}
}
#[allow(unreachable_pub)]
#[derive(Clone)]
pub(crate) struct TaskManagerTx {
tx: UnboundedSender<TaskManagerEvent>,
pub struct TaskManagerTx {
pub(crate) tx: UnboundedSender<TaskManagerEvent>,
}
impl TaskManagerTx {
@ -333,14 +335,6 @@ impl TaskManagerTx {
}
}
impl Deref for TaskManagerTx {
type Target = UnboundedSender<TaskManagerEvent>;
fn deref(&self) -> &Self::Target {
&self.tx
}
}
pub(crate) struct TaskManagerRx {
rx: UnboundedReceiver<TaskManagerEvent>,
}

View File

@ -17,8 +17,8 @@ use ylong_runtime::sync::mpsc::{unbounded_channel, UnboundedReceiver, UnboundedS
use ylong_runtime::sync::oneshot::Sender;
use super::{Client, ClientEvent};
use crate::ability::PANIC_INFO;
use crate::error::ErrorCode;
use crate::init::PANIC_INFO;
#[derive(Clone)]
pub(crate) struct ClientManagerEntry {

View File

@ -66,7 +66,6 @@ impl RemoteStub for RequestServiceStub {
let res = match code {
interface::CONSTRUCT => self.construct(data, reply),
interface::PAUSE => self.pause(data, reply),
interface::QUERY => self.query(data, reply),
interface::QUERY_MIME_TYPE => self.query_mime_type(data, reply),
interface::REMOVE => self.remove(data, reply),

View File

@ -18,8 +18,8 @@ use ylong_runtime::sync::mpsc::{unbounded_channel, UnboundedReceiver, UnboundedS
use ylong_runtime::sync::oneshot::Sender;
use super::{RunCountEvent, SubClient, SubKey};
use crate::ability::PANIC_INFO;
use crate::error::ErrorCode;
use crate::init::PANIC_INFO;
#[derive(Clone)]
pub(crate) struct RunCountManagerEntry {

View File

@ -11,7 +11,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use std::ffi::c_char;
use super::config::{Action, CommonTaskConfig, ConfigSet, Network, TaskConfig, Version};
use super::info::{CommonTaskInfo, InfoSet, Mode, TaskInfo, UpdateInfo};
@ -251,13 +250,6 @@ impl UpdateInfo {
}
}
#[repr(C)]
pub(crate) struct RequestTaskMsg {
pub(crate) task_id: u32,
pub(crate) uid: i32,
pub(crate) action: u8,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub(crate) struct NetworkInfo {
@ -377,33 +369,35 @@ impl TaskConfig {
}
}
pub(crate) fn publish_event(bundle: &str, task_id: u32, state: State) {
let len = bundle.len();
unsafe {
PublishStateChangeEvents(
bundle.as_ptr() as *const c_char,
len as u32,
task_id,
state as i32,
);
}
}
#[link(name = "download_server_cxx", kind = "static")]
extern "C" {
pub(crate) fn GetNetworkInfo() -> *const NetworkInfo;
pub(crate) fn DeleteCEachFileStatus(ptr: *const CEachFileStatus);
pub(crate) fn PublishStateChangeEvents(
bundle_name: *const c_char,
bundle_name_len: u32,
task_id: u32,
state: i32,
);
pub(crate) fn RequestBackgroundNotify(
msg: RequestTaskMsg,
wrapped_path: CStringWrapper,
wrapped_file_name: CStringWrapper,
percent: u32,
);
}
pub(crate) use tffi::*;
#[allow(unreachable_pub)]
#[cxx::bridge(namespace = "OHOS::Request")]
mod tffi {
pub(crate) struct RequestTaskMsg {
pub(crate) task_id: u32,
pub(crate) uid: i32,
pub(crate) action: u8,
}
unsafe extern "C++" {
include!("common_event_notify.h");
include!("background_notification.h");
fn PublishStateChangeEvent(bundleName: &str, taskId: u32, state: i32);
fn RequestBackgroundNotify(
msg: RequestTaskMsg,
wrapped_path: &str,
wrapped_file_name: &str,
percent: u32,
);
}
}

View File

@ -19,9 +19,12 @@ use std::task::{Context, Poll};
use ylong_http_client::HttpClientError;
use ylong_runtime::io::AsyncWrite;
use super::info::Mode;
use crate::manage::account::is_active_user;
use crate::manage::notifier::Notifier;
use crate::task::config::Version;
use crate::task::info::State;
use crate::task::reason::Reason;
use crate::task::request_task::RequestTask;
use crate::utils::get_current_timestamp;
@ -53,11 +56,17 @@ impl TaskOperator {
if (state != State::Running && state != State::Retrying)
|| (self.task.conf.version == Version::API10 && !self.task.check_net_work_status())
{
debug!("pause the task");
info!("pause the task");
return Poll::Ready(Err(HttpClientError::user_aborted()));
}
if !self.task.check_app_state() {
debug!("pause for app state");
info!("pause for app state");
return Poll::Ready(Err(HttpClientError::user_aborted()));
}
if self.task.conf.common_data.mode == Mode::BackGround && !is_active_user(self.task.uid()) {
info!("pause for user stopped");
self.task.set_status(State::Waiting, Reason::AccountStopped);
return Poll::Ready(Err(HttpClientError::user_aborted()));
}

View File

@ -34,6 +34,7 @@ pub(crate) enum Reason {
IoError,
UnsupportedRangeRequest,
OthersError,
AccountStopped,
}
impl From<u8> for Reason {
@ -88,6 +89,7 @@ impl Reason {
Reason::IoError => "Io Error",
Reason::UnsupportedRangeRequest => "The server is not support range request",
Reason::OthersError => "Some other error occured",
Reason::AccountStopped => "Account stopped"
}
}
}

View File

@ -34,10 +34,9 @@ use crate::manage::SystemConfig;
use crate::service::client::ClientManagerEntry;
use crate::task::client::build_client;
use crate::task::config::{Action, TaskConfig};
use crate::task::ffi::{publish_event, RequestBackgroundNotify, RequestTaskMsg};
use crate::task::ffi::{PublishStateChangeEvent, RequestBackgroundNotify, RequestTaskMsg};
use crate::task::files::{AttachedFiles, Files};
use crate::task::tick::Clock;
use crate::utils::c_wrapper::CStringWrapper;
use crate::utils::get_current_timestamp;
const RETRY_INTERVAL: u64 = 20;
@ -798,19 +797,19 @@ impl RequestTask {
Notifier::progress(&self.client_manager, notify_data.clone());
match state {
State::Completed => {
publish_event(
PublishStateChangeEvent(
self.conf.bundle.as_str(),
self.conf.common_data.task_id,
State::Completed,
State::Completed as i32,
);
Notifier::complete(&self.client_manager, notify_data)
}
State::Failed => {
publish_event(
PublishStateChangeEvent(
self.conf.bundle.as_str(),
self.conf.common_data.task_id,
State::Failed,
State::Failed as i32,
);
Notifier::fail(&self.client_manager, notify_data)
@ -958,11 +957,10 @@ impl RequestTask {
uid: self.conf.common_data.uid as i32,
action: self.conf.common_data.action as u8,
};
unsafe {
let c_path = CStringWrapper::from(self.conf.file_specs[index].path.as_str());
let c_file_name = CStringWrapper::from(self.conf.file_specs[index].file_name.as_str());
RequestBackgroundNotify(task_msg, c_path, c_file_name, percent as u32);
};
let path = self.conf.file_specs[index].path.as_str();
let file_name = self.conf.file_specs[index].file_name.as_str();
RequestBackgroundNotify(task_msg, path, file_name, percent as u32);
}
pub(crate) fn get_upload_info(&self, index: usize) -> (bool, u64) {

View File

@ -26,19 +26,15 @@ ohos_unittest("saTest") {
]
sources = [
"../../../../services/src/cxx/background_notification.cpp",
"../../../../services/src/cxx/c_check_permission.cpp",
"../../../../services/src/cxx/c_event_handler.cpp",
"../../../../services/src/cxx/c_string_wrapper.cpp",
"../../../../services/src/cxx/common_event_notify.cpp",
"../../../../services/src/cxx/get_calling_bundle.cpp",
"../../../../services/src/cxx/get_top_bundle.cpp",
"../../../../services/src/cxx/network_adapter.cpp",
"src/background_notification_test.cpp",
"src/c_check_permission_test.cpp",
"src/c_event_handler_test.cpp",
"src/c_string_wrapper_test.cpp",
"src/common_event_notify_test.cpp",
"src/get_bundle_test.cpp",
"src/network_adapter_test.cpp",
]

View File

@ -1,94 +0,0 @@
/*
* 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.
*/
#include "background_notification.h"
#include <gtest/gtest.h>
#include <cstdint>
#include "c_string_wrapper.h"
#include "js_common.h"
using namespace testing::ext;
using namespace OHOS::Request;
class BackgroundNotificationTest : public testing::Test {
public:
static void SetUpTestCase(void);
static void TearDownTestCase(void);
void SetUp();
void TearDown();
};
void BackgroundNotificationTest::SetUpTestCase(void)
{
// input testsuit setup stepsetup invoked before all testcases
}
void BackgroundNotificationTest::TearDownTestCase(void)
{
// input testsuit teardown stepteardown invoked after all testcases
}
void BackgroundNotificationTest::SetUp(void)
{
// input testcase setup stepsetup invoked before each testcases
}
void BackgroundNotificationTest::TearDown(void)
{
// input testcase teardown stepteardown invoked after each testcases
}
/**
* @tc.name: BackGroundNotifyTest_001
* @tc.desc: Test RequestBackgroundNotify interface base function - download
* @tc.type: FUNC
* @tc.require: Issue Number
*/
HWTEST_F(BackgroundNotificationTest, BackGroundNotifyTest_001, TestSize.Level1)
{
RequestTaskMsg msg = RequestTaskMsg{
123, // uint32_t taskId
123456, // pid_t uid
static_cast<uint8_t>(Action::DOWNLOAD) // uint8_t action
};
CStringWrapper wrappedPath = WrapperCString("../BUILD.gn");
CStringWrapper wrappedFileName = WrapperCString("BUILD.gn");
uint32_t percent = 50;
RequestBackgroundNotify(msg, wrappedPath, wrappedFileName, percent);
}
/**
* @tc.name: BackGroundNotifyTest_002
* @tc.desc: Test RequestBackgroundNotify interface base function - upload
* @tc.type: FUNC
* @tc.require: Issue Number
*/
HWTEST_F(BackgroundNotificationTest, BackGroundNotifyTest_002, TestSize.Level1)
{
RequestTaskMsg msg = RequestTaskMsg{
123, // uint32_t taskId
123456, // pid_t uid
static_cast<uint8_t>(Action::UPLOAD) // uint8_t action
};
CStringWrapper wrappedPath = WrapperCString("../BUILD.gn");
CStringWrapper wrappedFileName = WrapperCString("BUILD.gn");
uint32_t percent = 50;
RequestBackgroundNotify(msg, wrappedPath, wrappedFileName, percent);
}

View File

@ -1,62 +0,0 @@
/*
* 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.
*/
#include "common_event_notify.h"
#include <gtest/gtest.h>
using namespace testing::ext;
class CommonEventNotifyTest : public testing::Test {
public:
static void SetUpTestCase(void);
static void TearDownTestCase(void);
void SetUp();
void TearDown();
};
void CommonEventNotifyTest::SetUpTestCase(void)
{
// input testsuit setup stepsetup invoked before all testcases
}
void CommonEventNotifyTest::TearDownTestCase(void)
{
// input testsuit teardown stepteardown invoked after all testcases
}
void CommonEventNotifyTest::SetUp(void)
{
// input testcase setup stepsetup invoked before each testcases
}
void CommonEventNotifyTest::TearDown(void)
{
// input testcase teardown stepteardown invoked after each testcases
}
/**
* @tc.name: PublishStateChangeEventsTest_001
* @tc.desc: Test PublishStateChangeEvents interface base function
* @tc.type: FUNC
* @tc.require: Issue Number
*/
HWTEST_F(CommonEventNotifyTest, PublishStateChangeEventsTest_001, TestSize.Level1)
{
const char *bundleName = "com.example.myapplication";
uint32_t len = strlen(bundleName);
uint32_t taskId = 123456;
int32_t state = 0x40; // State::Completed
PublishStateChangeEvents(bundleName, len, taskId, state);
}