支持多用户

Signed-off-by: LY <liuyong235@huawei.com>
This commit is contained in:
LY 2024-08-16 17:46:23 +08:00
parent 09b1dceee4
commit 85d5e10585
20 changed files with 744 additions and 10 deletions

View File

@ -69,6 +69,7 @@
"memmgr", "memmgr",
"napi", "napi",
"openssl", "openssl",
"os_account",
"preferences", "preferences",
"resource_management", "resource_management",
"safwk", "safwk",

View File

@ -108,6 +108,7 @@ ohos_shared_library("intl_util") {
"src/locale_matcher.cpp", "src/locale_matcher.cpp",
"src/locale_util.cpp", "src/locale_util.cpp",
"src/measure_data.cpp", "src/measure_data.cpp",
"src/multi_users.cpp",
"src/number_format.cpp", "src/number_format.cpp",
"src/phone_number_format.cpp", "src/phone_number_format.cpp",
"src/plural_rules.cpp", "src/plural_rules.cpp",
@ -168,6 +169,7 @@ ohos_shared_library("intl_util") {
"libxml2:libxml2", "libxml2:libxml2",
"openssl:libcrypto_shared", "openssl:libcrypto_shared",
"openssl:libssl_shared", "openssl:libssl_shared",
"os_account:os_account_innerkits",
"preferences:native_preferences", "preferences:native_preferences",
] ]
public_external_deps = [] public_external_deps = []

View File

@ -12,7 +12,7 @@
# limitations under the License. # limitations under the License.
persist.global.language=zh-Hans persist.global.language=zh-Hans
persist.global.locale=zh-Hans-CN persist.global.locale=zh-Hans-CN
persist.global.is24Hour= persist.global.is24Hour=default
persist.global.preferredLanguages= persist.global.preferredLanguages=
const.global.language=zh-Hans const.global.language=zh-Hans
const.global.locale=zh-Hans-CN const.global.locale=zh-Hans-CN

View File

@ -105,6 +105,9 @@ public:
static bool IsValidRegion(const std::string &region); static bool IsValidRegion(const std::string &region);
static bool IsValidTag(const std::string &tag); static bool IsValidTag(const std::string &tag);
static bool IsValid24HourClockValue(const std::string &tag); static bool IsValid24HourClockValue(const std::string &tag);
static std::string GetLanguageKey();
static std::string GetLocaleKey();
static std::string GetHourKey();
private: private:
static void Split(const std::string &src, const std::string &sep, std::vector<std::string> &dest); static void Split(const std::string &src, const std::string &sep, std::vector<std::string> &dest);

View File

@ -0,0 +1,61 @@
/*
* 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 OHOS_GLOBAL_I18N_MULTI_USERS_H
#define OHOS_GLOBAL_I18N_MULTI_USERS_H
#include <string>
#include "i18n_types.h"
#include "preferences.h"
#include "preferences_helper.h"
namespace OHOS {
namespace Global {
namespace I18n {
class MultiUsers {
public:
static void InitMultiUser();
static void SwitchUser(const std::string& curLocalId);
static void AddUser(const std::string& localId);
static void RemoveUser(const std::string& localId);
static I18nErrorCode SaveLanguage(const std::string& localId, const std::string& language);
static I18nErrorCode SaveLocale(const std::string& localId, const std::string& locale);
static I18nErrorCode SaveIs24Hour(const std::string& localId, const std::string& is24Hour);
private:
static I18nErrorCode SaveGlobalParam(const std::string& localId);
static I18nErrorCode LoadGlobalParam(const std::string& localId);
static I18nErrorCode GetForegroundLocalId(std::string& localId);
static I18nErrorCode RemoveGlobalParam(const std::string& localId);
static std::string ReadMultiUsersParameter(const std::string& paramKey, const std::string& localId);
static I18nErrorCode WriteMultiUsersParameter(const std::string& paramKey, const std::string& paramValue,
const std::string& localId, bool isDel);
static bool IsValidLocalId(const std::string& localId);
static void InitPreferences();
static std::string GetParamFromPreferences(const std::string& paramKey);
static I18nErrorCode SetParamFromPreferences(const std::string& paramKey, const std::string& paramValue);
static const std::string MULTI_USERS_LANGUAGE_KEY;
static const std::string MULTI_USERS_LOCALE_KEY;
static const std::string MULTI_USERS_HOUR_KEY;
static const std::string INIT_KEY;
static const std::string PREFERENCE_PATH;
static const int32_t DEFAULT_LOCAL_ID;
static const int CONFIG_LEN;
static std::shared_ptr<NativePreferences::Preferences> preferences;
};
} // namespace I18n
} // namespace Global
} // namespace OHOS
#endif

View File

@ -32,6 +32,7 @@ static const uint32_t BYTE_ARRAY_INDEX_THIRD = 3;
static std::set<std::string> availableIDs; static std::set<std::string> availableIDs;
void Split(const std::string &src, const std::string &sep, std::vector<std::string> &dest); void Split(const std::string &src, const std::string &sep, std::vector<std::string> &dest);
void Merge(const std::vector<std::string>& src, const std::string& sep, std::string& dest);
std::string ReadSystemParameter(const char *paramKey, const int paramLength); std::string ReadSystemParameter(const char *paramKey, const int paramLength);
int32_t ConvertString2Int(const std::string &numberStr, int32_t& status); int32_t ConvertString2Int(const std::string &numberStr, int32_t& status);
bool IsValidLocaleTag(icu::Locale &locale); bool IsValidLocaleTag(icu::Locale &locale);

View File

@ -27,6 +27,7 @@
#include "ipc_skeleton.h" #include "ipc_skeleton.h"
#include "libxml/parser.h" #include "libxml/parser.h"
#include "locale_info.h" #include "locale_info.h"
#include "multi_users.h"
#include "unicode/localebuilder.h" #include "unicode/localebuilder.h"
#include "unicode/locdspnm.h" #include "unicode/locdspnm.h"
#include "unicode/locid.h" #include "unicode/locid.h"
@ -1076,7 +1077,7 @@ bool LocaleConfig::IsEmpty24HourClock()
bool LocaleConfig::Is24HourClock() bool LocaleConfig::Is24HourClock()
{ {
std::string is24Hour = ReadSystemParameter(HOUR_KEY, CONFIG_LEN); std::string is24Hour = ReadSystemParameter(HOUR_KEY, CONFIG_LEN);
if (is24Hour.empty()) { if (is24Hour.compare("default") == 0) {
std::string systemLocale = GetSystemLocale(); std::string systemLocale = GetSystemLocale();
return Is24HourLocale(systemLocale); return Is24HourLocale(systemLocale);
} }
@ -1188,6 +1189,7 @@ I18nErrorCode LocaleConfig::SetSystemLanguage(const std::string &languageTag)
} }
std::string newLocaleTag = UpdateLanguageOfLocale(languageTag); std::string newLocaleTag = UpdateLanguageOfLocale(languageTag);
if (SetSystemLocale(newLocaleTag) == I18nErrorCode::SUCCESS) { if (SetSystemLocale(newLocaleTag) == I18nErrorCode::SUCCESS) {
MultiUsers::SaveLanguage("", languageTag);
return I18nErrorCode::SUCCESS; return I18nErrorCode::SUCCESS;
} }
// reset system language to old language in case that system language is inconsist with system locale's lanuage. // reset system language to old language in case that system language is inconsist with system locale's lanuage.
@ -1214,6 +1216,7 @@ I18nErrorCode LocaleConfig::SetSystemLocale(const std::string &localeTag)
if (SetParameter(LOCALE_KEY, localeTag.data()) != 0) { if (SetParameter(LOCALE_KEY, localeTag.data()) != 0) {
return I18nErrorCode::UPDATE_SYSTEM_LOCALE_FAILED; return I18nErrorCode::UPDATE_SYSTEM_LOCALE_FAILED;
} }
MultiUsers::SaveLocale("", localeTag);
#ifdef SUPPORT_GRAPHICS #ifdef SUPPORT_GRAPHICS
UpdateConfiguration(AAFwk::GlobalConfigurationKey::SYSTEM_LANGUAGE, localeTag); UpdateConfiguration(AAFwk::GlobalConfigurationKey::SYSTEM_LANGUAGE, localeTag);
return PublishCommonEvent(EventFwk::CommonEventSupport::COMMON_EVENT_LOCALE_CHANGED); return PublishCommonEvent(EventFwk::CommonEventSupport::COMMON_EVENT_LOCALE_CHANGED);
@ -1224,7 +1227,7 @@ I18nErrorCode LocaleConfig::SetSystemLocale(const std::string &localeTag)
bool LocaleConfig::IsValid24HourClockValue(const std::string &tag) bool LocaleConfig::IsValid24HourClockValue(const std::string &tag)
{ {
if (tag.compare("true") == 0 || tag.compare("false") == 0 || tag.length() == 0) { if (tag.compare("true") == 0 || tag.compare("false") == 0 || tag.compare("default") == 0) {
return true; return true;
} }
return false; return false;
@ -1241,6 +1244,7 @@ I18nErrorCode LocaleConfig::Set24HourClock(const std::string &option)
option.c_str()); option.c_str());
return I18nErrorCode::UPDATE_24_HOUR_CLOCK_FAILED; return I18nErrorCode::UPDATE_24_HOUR_CLOCK_FAILED;
} }
MultiUsers::SaveIs24Hour("", option);
#ifdef SUPPORT_GRAPHICS #ifdef SUPPORT_GRAPHICS
UpdateConfiguration(AAFwk::GlobalConfigurationKey::SYSTEM_HOUR, option); UpdateConfiguration(AAFwk::GlobalConfigurationKey::SYSTEM_HOUR, option);
return PublishCommonEvent(EventFwk::CommonEventSupport::COMMON_EVENT_TIME_CHANGED); return PublishCommonEvent(EventFwk::CommonEventSupport::COMMON_EVENT_TIME_CHANGED);
@ -1425,6 +1429,21 @@ std::string LocaleConfig::CreateLocaleFromRegion(const std::string &regionTag)
} }
return localeTag; return localeTag;
} }
std::string LocaleConfig::GetLanguageKey()
{
return LANGUAGE_KEY;
}
std::string LocaleConfig::GetLocaleKey()
{
return LOCALE_KEY;
}
std::string LocaleConfig::GetHourKey()
{
return HOUR_KEY;
}
} // namespace I18n } // namespace I18n
} // namespace Global } // namespace Global
} // namespace OHOS } // namespace OHOS

View File

@ -0,0 +1,349 @@
/*
* 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 "i18n_hilog.h"
#include "locale_config.h"
#include "os_account_manager.h"
#include "parameter.h"
#include "utils.h"
#include "multi_users.h"
namespace OHOS {
namespace Global {
namespace I18n {
const std::string MultiUsers::MULTI_USERS_LANGUAGE_KEY = "languageData";
const std::string MultiUsers::MULTI_USERS_LOCALE_KEY = "localeData";
const std::string MultiUsers::MULTI_USERS_HOUR_KEY = "is24HourData";
const std::string MultiUsers::INIT_KEY = "init";
const std::string MultiUsers::PREFERENCE_PATH = "/data/service/el1/public/i18n/global/GlobalParamData";
const int32_t MultiUsers::DEFAULT_LOCAL_ID = 100;
const int MultiUsers::CONFIG_LEN = 128;
std::shared_ptr<NativePreferences::Preferences> MultiUsers::preferences = nullptr;
void MultiUsers::InitMultiUser()
{
InitPreferences();
if (preferences == nullptr) {
HILOG_ERROR_I18N("InitMultiUser: InitPreferences failed");
return;
}
bool init = preferences->GetBool(INIT_KEY, false);
std::string localId;
I18nErrorCode errCode = GetForegroundLocalId(localId);
if (errCode != I18nErrorCode::SUCCESS) {
HILOG_ERROR_I18N("InitMultiUser: get foreground local id failed");
return;
}
if (!init) {
AddUser(localId);
preferences->PutBool(INIT_KEY, true);
preferences->Flush();
HILOG_ERROR_I18N("InitMultiUser: init multi user data success");
}
}
void MultiUsers::SwitchUser(const std::string& curLocalId)
{
if (!IsValidLocalId(curLocalId)) {
HILOG_ERROR_I18N("SwitchUser: curLocalId is an invalid LocalId");
return;
}
I18nErrorCode errCode = LoadGlobalParam(curLocalId);
if (errCode != I18nErrorCode::SUCCESS) {
HILOG_ERROR_I18N("SwitchUser: load global params failed");
}
}
void MultiUsers::AddUser(const std::string& localId)
{
if (!IsValidLocalId(localId)) {
HILOG_ERROR_I18N("AddUser: %{public}s is invalid local id", localId.c_str());
return;
}
I18nErrorCode errCode = SaveGlobalParam(localId);
if (errCode != I18nErrorCode::SUCCESS) {
HILOG_ERROR_I18N("AddUser: add global param failed");
}
}
void MultiUsers::RemoveUser(const std::string& localId)
{
if (!IsValidLocalId(localId)) {
HILOG_ERROR_I18N("RemoveUser: %{public}s is invalid local id", localId.c_str());
return;
}
I18nErrorCode errCode = RemoveGlobalParam(localId);
if (errCode != I18nErrorCode::SUCCESS) {
HILOG_ERROR_I18N("RemoveUser: remove global param failed");
}
}
I18nErrorCode MultiUsers::GetForegroundLocalId(std::string& localId)
{
int id = 0;
int errCode = OHOS::AccountSA::OsAccountManager::GetForegroundOsAccountLocalId(id);
if (errCode != 0) {
HILOG_ERROR_I18N("GetForegroundLocalId: get foreground locale Id failed, errCode is %{public}d", errCode);
return I18nErrorCode::FAILED;
}
localId = std::to_string(id);
return I18nErrorCode::SUCCESS;
}
I18nErrorCode MultiUsers::SaveLanguage(const std::string& localId, const std::string& language)
{
std::string foregroundLocalId = localId;
I18nErrorCode errCode = I18nErrorCode::SUCCESS;
if (localId.empty()) {
errCode = MultiUsers::GetForegroundLocalId(foregroundLocalId);
}
if (errCode != I18nErrorCode::SUCCESS) {
HILOG_ERROR_I18N("SaveLanguage: get foreground locale Id failed");
return I18nErrorCode::FAILED;
}
errCode =
WriteMultiUsersParameter(MULTI_USERS_LANGUAGE_KEY, language, foregroundLocalId, false);
if (errCode != I18nErrorCode::SUCCESS) {
HILOG_ERROR_I18N("SaveLanguage: save language of user %{public}s failed", foregroundLocalId.c_str());
return I18nErrorCode::FAILED;
}
return I18nErrorCode::SUCCESS;
}
I18nErrorCode MultiUsers::SaveLocale(const std::string& localId, const std::string& locale)
{
std::string foregroundLocalId = localId;
I18nErrorCode errCode = I18nErrorCode::SUCCESS;
if (localId.empty()) {
errCode = MultiUsers::GetForegroundLocalId(foregroundLocalId);
}
if (errCode != I18nErrorCode::SUCCESS) {
HILOG_ERROR_I18N("SaveLocale: get foreground locale Id failed");
return I18nErrorCode::FAILED;
}
errCode =
WriteMultiUsersParameter(MULTI_USERS_LOCALE_KEY, locale, foregroundLocalId, false);
if (errCode != I18nErrorCode::SUCCESS) {
HILOG_ERROR_I18N("SaveLocale: save locale of user %{public}s failed", foregroundLocalId.c_str());
return I18nErrorCode::FAILED;
}
return I18nErrorCode::SUCCESS;
}
I18nErrorCode MultiUsers::SaveIs24Hour(const std::string& localId, const std::string& is24Hour)
{
HILOG_ERROR_I18N("TestLog: SaveIs24Hour start");
std::string foregroundLocalId = localId;
I18nErrorCode errCode = I18nErrorCode::SUCCESS;
if (localId.empty()) {
HILOG_ERROR_I18N("TestLog: localId");
errCode = MultiUsers::GetForegroundLocalId(foregroundLocalId);
}
if (errCode != I18nErrorCode::SUCCESS) {
HILOG_ERROR_I18N("TestLog: get foreground locale Id failed");
HILOG_ERROR_I18N("SaveLanguage: get foreground locale Id failed");
return I18nErrorCode::FAILED;
}
HILOG_ERROR_I18N("TestLog: foregroundLocalId is %{public}s", foregroundLocalId.c_str());
errCode =
WriteMultiUsersParameter(MULTI_USERS_HOUR_KEY, is24Hour, foregroundLocalId, false);
if (errCode != I18nErrorCode::SUCCESS) {
HILOG_ERROR_I18N("SaveIs24Hour: save is24Hour of user %{public}s failed", foregroundLocalId.c_str());
return I18nErrorCode::FAILED;
}
return I18nErrorCode::SUCCESS;
}
I18nErrorCode MultiUsers::SaveGlobalParam(const std::string& localId)
{
std::string language = ReadSystemParameter(LocaleConfig::GetLanguageKey().data(), CONFIG_LEN);
std::string locale = ReadSystemParameter(LocaleConfig::GetLocaleKey().data(), CONFIG_LEN);
std::string is24Hour = ReadSystemParameter(LocaleConfig::GetHourKey().data(), CONFIG_LEN);
I18nErrorCode errCode = SaveLanguage(localId, language);
if (errCode != I18nErrorCode::SUCCESS) {
HILOG_ERROR_I18N("SaveGlobalParam: save language of user %{public}s failed", localId.c_str());
return I18nErrorCode::FAILED;
}
errCode = SaveLocale(localId, locale);
if (errCode != I18nErrorCode::SUCCESS) {
HILOG_ERROR_I18N("SaveGlobalParam: save locale of user %{public}s failed", localId.c_str());
return I18nErrorCode::FAILED;
}
errCode = SaveIs24Hour(localId, is24Hour);
if (errCode != I18nErrorCode::SUCCESS) {
HILOG_ERROR_I18N("SaveGlobalParam: save is24Hour of user %{public}s failed", localId.c_str());
return I18nErrorCode::FAILED;
}
return I18nErrorCode::SUCCESS;
}
I18nErrorCode MultiUsers::LoadGlobalParam(const std::string& localId)
{
std::string newLocale = ReadMultiUsersParameter(MULTI_USERS_LOCALE_KEY, localId);
if (!newLocale.empty() && SetParameter(LocaleConfig::GetLocaleKey().data(), newLocale.data()) != 0) {
HILOG_ERROR_I18N("LoadGlobalParam: set locale %{public}s failed", newLocale.c_str());
return I18nErrorCode::FAILED;
}
std::string newLanguage = ReadMultiUsersParameter(MULTI_USERS_LANGUAGE_KEY, localId);
if (!newLanguage.empty() && LocaleConfig::SetSystemLanguage(newLanguage) != 0) {
HILOG_ERROR_I18N("LoadGlobalParam: set language %{public}s failed", newLanguage.c_str());
return I18nErrorCode::FAILED;
}
std::string newIs24Hour = ReadMultiUsersParameter(MULTI_USERS_HOUR_KEY, localId);
if (!newIs24Hour.empty() && LocaleConfig::Set24HourClock(newIs24Hour) != 0) {
HILOG_ERROR_I18N("LoadGlobalParam: set is24Hour %{public}s failed", newIs24Hour.c_str());
return I18nErrorCode::FAILED;
}
return I18nErrorCode::SUCCESS;
}
I18nErrorCode MultiUsers::RemoveGlobalParam(const std::string& localId)
{
I18nErrorCode errCode = WriteMultiUsersParameter(MULTI_USERS_LANGUAGE_KEY, "", localId, true);
if (errCode != I18nErrorCode::SUCCESS) {
HILOG_ERROR_I18N("RemoveGlobalParam: remove language of user %{public}s failed", localId.c_str());
return I18nErrorCode::FAILED;
}
errCode = WriteMultiUsersParameter(MULTI_USERS_LOCALE_KEY, "", localId, true);
if (errCode != I18nErrorCode::SUCCESS) {
HILOG_ERROR_I18N("RemoveGlobalParam: remove locale of user %{public}s failed", localId.c_str());
return I18nErrorCode::FAILED;
}
errCode = WriteMultiUsersParameter(MULTI_USERS_HOUR_KEY, "", localId, true);
if (errCode != I18nErrorCode::SUCCESS) {
HILOG_ERROR_I18N("RemoveGlobalParam: remove is24Hour of user %{public}s failed", localId.c_str());
return I18nErrorCode::FAILED;
}
return I18nErrorCode::SUCCESS;
}
std::string MultiUsers::ReadMultiUsersParameter(const std::string& paramKey, const std::string& localId)
{
std::string param = GetParamFromPreferences(paramKey);
if (param.empty()) {
return "";
}
std::vector<std::string> multiUsersParam;
Split(param, ";", multiUsersParam);
for (auto& userParam : multiUsersParam) {
std::vector<std::string> content;
Split(userParam, ":", content);
// 2 is number of param
if (content.size() != 2) {
continue;
}
if (content[0] == localId) {
return content[1];
}
}
return "";
}
I18nErrorCode MultiUsers::WriteMultiUsersParameter(const std::string& paramKey, const std::string& paramValue,
const std::string& localId, bool isDel)
{
std::string param = GetParamFromPreferences(paramKey);
std::vector<std::string> multiUsersParam;
Split(param, ";", multiUsersParam);
std::vector<std::string> newMultiUsersParam;
bool userIsExist = false;
for (auto& userParam : multiUsersParam) {
std::vector<std::string> content;
Split(userParam, ":", content);
// 2 is number of param
if (content.size() != 2) {
continue;
}
std::string userLocalId = content[0];
if (!isDel && userLocalId == localId) {
content[1] = paramValue;
Merge(content, ":", userParam);
userIsExist = true;
}
newMultiUsersParam.emplace_back(userParam);
if (isDel && userLocalId == localId) {
newMultiUsersParam.pop_back();
}
}
if (!isDel && !userIsExist) {
newMultiUsersParam.push_back(localId + ":" + paramValue);
}
std::string newParam;
Merge(newMultiUsersParam, ";", newParam);
if (SetParamFromPreferences(paramKey, newParam) != I18nErrorCode::SUCCESS) {
HILOG_ERROR_I18N("WriteMultiUsersParameter: set param %{public}s failed", paramKey.c_str());
return I18nErrorCode::FAILED;
}
return I18nErrorCode::SUCCESS;
}
bool MultiUsers::IsValidLocalId(const std::string& localId)
{
if (std::atoi(localId.c_str()) < DEFAULT_LOCAL_ID) {
HILOG_ERROR_I18N("IsValidLocalId: %{public}s is an invalid local ID", localId.c_str());
return false;
}
return true;
}
void MultiUsers::InitPreferences()
{
if (preferences == nullptr) {
HILOG_ERROR_I18N("InitPreferences: preferences Init");
OHOS::NativePreferences::Options opt(PREFERENCE_PATH);
int status;
preferences = NativePreferences::PreferencesHelper::GetPreferences(opt, status);
if (status != 0) {
HILOG_ERROR_I18N("InitPreferences: get preferences failed");
preferences = nullptr;
}
}
}
std::string MultiUsers::GetParamFromPreferences(const std::string& paramKey)
{
InitPreferences();
if (preferences == nullptr) {
HILOG_ERROR_I18N("GetParamFromPreferences: preferences is nullptr");
return "";
}
return preferences->GetString(paramKey, "");
}
I18nErrorCode MultiUsers::SetParamFromPreferences(const std::string& paramKey, const std::string& paramValue)
{
InitPreferences();
if (preferences == nullptr) {
HILOG_ERROR_I18N("SetParamFromPreferences: preferences is nullptr");
return I18nErrorCode::FAILED;
}
int status = preferences->PutString(paramKey, paramValue);
if (status != 0) {
HILOG_ERROR_I18N("SetParamFromPreferences: put param %{public}s failed", paramKey.c_str());
return I18nErrorCode::FAILED;
}
preferences->Flush();
return I18nErrorCode::SUCCESS;
}
} // namespace I18n
} // namespace Global
} // namespace OHOS

View File

@ -13,8 +13,8 @@
* limitations under the License. * limitations under the License.
*/ */
#include <climits>
#include <algorithm> #include <algorithm>
#include <climits>
#include <filesystem> #include <filesystem>
#include <fstream> #include <fstream>
#include <dirent.h> #include <dirent.h>
@ -58,6 +58,19 @@ void Split(const string &src, const string &sep, vector<string> &dest)
} }
} }
void Merge(const std::vector<std::string>& src, const std::string& sep, std::string& dest)
{
if (src.size() == 0) {
dest = "";
return;
}
dest = src[0];
for (size_t i = 1; i < src.size(); ++i) {
dest += sep;
dest += src[i];
}
}
std::string ReadSystemParameter(const char *paramKey, const int paramLength) std::string ReadSystemParameter(const char *paramKey, const int paramLength)
{ {
char param[paramLength]; char param[paramLength];

View File

@ -52,6 +52,7 @@ ohos_unittest("intl_test") {
"libphonenumber:phonenumber_standard", "libphonenumber:phonenumber_standard",
"libpng:libpng", "libpng:libpng",
"openssl:libssl_shared", "openssl:libssl_shared",
"preferences:native_preferences",
] ]
if (i18n_support_app_preferred_language) { if (i18n_support_app_preferred_language) {
defines = [ "SUPPORT_APP_PREFERRED_LANGUAGE" ] defines = [ "SUPPORT_APP_PREFERRED_LANGUAGE" ]

View File

@ -127,6 +127,12 @@ int IntlFuncTest0094(void);
int IntlFuncTest0095(void); int IntlFuncTest0095(void);
int IntlFuncTest0096(void); int IntlFuncTest0096(void);
int IntlFuncTest0097(void); int IntlFuncTest0097(void);
int IntlFuncTest0098(void);
int IntlFuncTest0099(void);
int IntlFuncTest00100(void);
int IntlFuncTest00101(void);
int IntlFuncTest00102(void);
int IntlFuncTest00103(void);
} // namespace I18n } // namespace I18n
} // namespace Global } // namespace Global
} // namespace OHOS } // namespace OHOS

View File

@ -39,6 +39,7 @@
#include "locale_info.h" #include "locale_info.h"
#include "locale_matcher.h" #include "locale_matcher.h"
#include "measure_data.h" #include "measure_data.h"
#include "multi_users.h"
#include "number_format.h" #include "number_format.h"
#include "parameter.h" #include "parameter.h"
#include "phone_number_format.h" #include "phone_number_format.h"
@ -1827,6 +1828,40 @@ HWTEST_F(IntlTest, IntlFuncTest0097, TestSize.Level1)
bool isWeekend = calendarMock->IsWeekend(); bool isWeekend = calendarMock->IsWeekend();
EXPECT_FALSE(isWeekend); EXPECT_FALSE(isWeekend);
} }
/**
* @tc.name: IntlFuncTest00103
* @tc.desc: Test Intl multi users
* @tc.type: FUNC
*/
HWTEST_F(IntlTest, IntlFuncTest00103, TestSize.Level1)
{
std::string path = "/data/service/el1/public/i18n/global/GlobalParamData";
OHOS::NativePreferences::Options opt(path);
int status;
std::shared_ptr<NativePreferences::Preferences> preferences =
NativePreferences::PreferencesHelper::GetPreferences(opt, status);
MultiUsers::AddUser("101");
MultiUsers::SwitchUser("101");
MultiUsers::RemoveUser("100");
if (preferences != nullptr) {
std::string language = preferences->GetString("languageData", "");
std::string locale = preferences->GetString("localeData", "");
std::string is24Hour = preferences->GetString("is24HourData", "");
EXPECT_EQ(language, "101:zh-Hans");
EXPECT_EQ(locale, "101:zh-Hans-CN");
EXPECT_EQ(is24Hour, "101:false");
}
MultiUsers::RemoveUser("101");
if (preferences != nullptr) {
std::string language = preferences->GetString("languageData", "");
std::string locale = preferences->GetString("localeData", "");
std::string is24Hour = preferences->GetString("is24HourData", "");
EXPECT_EQ(language, "");
EXPECT_EQ(locale, "");
EXPECT_EQ(is24Hour, "");
}
}
} // namespace I18n } // namespace I18n
} // namespace Global } // namespace Global
} // namespace OHOS } // namespace OHOS

View File

@ -6,7 +6,21 @@
"libpath": "libi18n_sa.z.so", "libpath": "libi18n_sa.z.so",
"run-on-create": false, "run-on-create": false,
"distributed": false, "distributed": false,
"dump_level": 1 "dump_level": 1,
"start-on-demand": {
"allow-update":false,
"commonevent":[
{
"name":"usual.event.USER_SWITCHED"
},
{
"name":"usual.event.USER_ADDED"
},
{
"name":"usual.event.USER_REMOVED"
}
]
}
} }
] ]
} }

View File

@ -67,6 +67,7 @@ ohos_shared_library("i18n_sa") {
sources = [ sources = [
"./src/i18n_service_ability.cpp", "./src/i18n_service_ability.cpp",
"./src/i18n_service_ability_stub.cpp", "./src/i18n_service_ability_stub.cpp",
"./src/i18n_service_event.cpp",
] ]
include_dirs = [ include_dirs = [
"./include", "./include",
@ -79,6 +80,7 @@ ohos_shared_library("i18n_sa") {
"../frameworks/intl:preferred_language", "../frameworks/intl:preferred_language",
] ]
external_deps = [ external_deps = [
"ability_base:want",
"ability_runtime:ability_manager", "ability_runtime:ability_manager",
"access_token:libaccesstoken_sdk", "access_token:libaccesstoken_sdk",
"access_token:libtokenid_sdk", "access_token:libtokenid_sdk",

View File

@ -3,9 +3,10 @@
{ {
"name": "boot", "name": "boot",
"cmds": [ "cmds": [
"mkdir /data/service/el1/public/i18n/ 0744 i18n_service i18n_service", "mkdir /data/service/el1/public/i18n/ 0755 i18n_service i18n_service",
"mkdir /data/service/el1/public/i18n/timezone/ 0755 i18n_service i18n_service", "mkdir /data/service/el1/public/i18n/timezone/ 0755 i18n_service i18n_service",
"mkdir /data/service/el1/public/i18n/libphonenumber/ 0755 i18n_service i18n_service", "mkdir /data/service/el1/public/i18n/libphonenumber/ 0755 i18n_service i18n_service",
"mkdir /data/service/el1/public/i18n/global/ 0777 i18n_service i18n_service",
"exec /system/bin/hmos_cust_timezone_mount", "exec /system/bin/hmos_cust_timezone_mount",
"exec /system/bin/hmos_cust_libphonenumber_mount" "exec /system/bin/hmos_cust_libphonenumber_mount"
] ]
@ -19,7 +20,8 @@
"gid": ["i18n", "shell"], "gid": ["i18n", "shell"],
"permission": [ "permission": [
"ohos.permission.UPDATE_CONFIGURATION", "ohos.permission.UPDATE_CONFIGURATION",
"ohos.permission.MANAGE_SECURE_SETTINGS" "ohos.permission.MANAGE_SECURE_SETTINGS",
"ohos.permission.MANAGE_LOCAL_ACCOUNTS"
], ],
"ondemand": true, "ondemand": true,
"secon": "u:r:i18n_service:s0" "secon": "u:r:i18n_service:s0"

View File

@ -18,6 +18,7 @@
#include "event_handler.h" #include "event_handler.h"
#include "i18n_service_ability_stub.h" #include "i18n_service_ability_stub.h"
#include "i18n_service_event.h"
#include "system_ability.h" #include "system_ability.h"
namespace OHOS { namespace OHOS {
@ -48,7 +49,7 @@ protected:
/** /**
* @brief Called when i18n service start. * @brief Called when i18n service start.
*/ */
void OnStart() override; void OnStart(const SystemAbilityOnDemandReason& startReason) override;
/** /**
* @brief Called when i18n service stop. * @brief Called when i18n service stop.
@ -58,6 +59,7 @@ protected:
private: private:
// i18n service unload event handler. // i18n service unload event handler.
std::shared_ptr<AppExecFwk::EventHandler> handler; std::shared_ptr<AppExecFwk::EventHandler> handler;
I18nServiceEvent* i18nServiceEvent = nullptr;
}; };
} // namespace I18n } // namespace I18n
} // namespace Global } // namespace Global

View File

@ -0,0 +1,77 @@
/*
* 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 OHOS_GLOBAL_I18N_I18N_SERVICE_EVENT_H
#define OHOS_GLOBAL_I18N_I18N_SERVICE_EVENT_H
#include <functional>
#include <memory>
#include <singleton.h>
#include <string>
#include <unordered_map>
#include "common_event_subscriber.h"
#include "system_ability.h"
#include "want.h"
namespace OHOS {
namespace Global {
namespace I18n {
class I18nServiceEvent {
public:
I18nServiceEvent();
~I18nServiceEvent();
void CheckStartReason(const SystemAbilityOnDemandReason& startReason);
void SubscriberEvent();
private:
class I18nServiceSubscriber : public EventFwk::CommonEventSubscriber {
public:
explicit I18nServiceSubscriber(const EventFwk::CommonEventSubscribeInfo& subscribeInfo,
I18nServiceEvent& registry) : CommonEventSubscriber(subscribeInfo), registry_(registry)
{}
~I18nServiceSubscriber() = default;
void OnReceiveEvent(const EventFwk::CommonEventData& data) override
{
registry_.OnReceiveEvent(data);
}
private:
I18nServiceEvent& registry_;
};
void UnSubscriberEvent();
void OnReceiveEvent(const EventFwk::CommonEventData& data);
void HandleSwitchUser(const EventFwk::CommonEventData& data) const;
void HandleAddUser(const EventFwk::CommonEventData& data) const;
void HandleRemoveUser(const EventFwk::CommonEventData& data) const;
using EventHandle = std::function<void(const EventFwk::CommonEventData&)>;
typedef void (I18nServiceEvent::*HandleEventFunc)(const EventFwk::CommonEventData&) const;
std::unordered_map<std::string, EventHandle> eventHandles;
std::unordered_map<std::string, HandleEventFunc> handleEventFunc;
std::shared_ptr<I18nServiceSubscriber> subscriber = nullptr;
std::string userSwitchKey;
std::string userAdded;
std::string userRemoved;
static const int RETRY;
};
} // namespace I18n
} // namespace Global
} // namespace OHOS
#endif // OHOS_GLOBAL_I18N_I18N_SERVICE_EVENT_H

View File

@ -43,7 +43,6 @@ public:
SET_USING_LOCAL_DIGIT = 4, SET_USING_LOCAL_DIGIT = 4,
ADD_PREFERRED_LANGUAGE = 5, ADD_PREFERRED_LANGUAGE = 5,
REMOVE_PREFERRED_LANGUAGE = 6, REMOVE_PREFERRED_LANGUAGE = 6,
VERIFY_LIBPHONENUMBER_UPDATE = 7,
}; };
DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.global.II18nServiceAbility"); DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.global.II18nServiceAbility");

View File

@ -18,6 +18,7 @@
#include "locale_config.h" #include "locale_config.h"
#include "mem_mgr_client.h" #include "mem_mgr_client.h"
#include "mem_mgr_proxy.h" #include "mem_mgr_proxy.h"
#include "multi_users.h"
#include "preferred_language.h" #include "preferred_language.h"
#include "preferences.h" #include "preferences.h"
#include "preferences_helper.h" #include "preferences_helper.h"
@ -93,9 +94,15 @@ void I18nServiceAbility::UnloadI18nServiceAbility()
} }
} }
void I18nServiceAbility::OnStart() void I18nServiceAbility::OnStart(const SystemAbilityOnDemandReason& startReason)
{ {
HILOG_INFO_I18N("I18nServiceAbility start."); HILOG_INFO_I18N("I18nServiceAbility start.");
i18nServiceEvent = new I18nServiceEvent();
if (i18nServiceEvent != nullptr) {
i18nServiceEvent->SubscriberEvent();
i18nServiceEvent->CheckStartReason(startReason);
}
MultiUsers::InitMultiUser();
bool status = Publish(this); bool status = Publish(this);
if (status) { if (status) {
HILOG_INFO_I18N("I18nServiceAbility Publish success."); HILOG_INFO_I18N("I18nServiceAbility Publish success.");
@ -112,6 +119,10 @@ void I18nServiceAbility::OnStop()
{ {
int pid = getpid(); int pid = getpid();
Memory::MemMgrClient::GetInstance().NotifyProcessStatus(pid, 1, 0, I18N_SA_ID); Memory::MemMgrClient::GetInstance().NotifyProcessStatus(pid, 1, 0, I18N_SA_ID);
if (i18nServiceEvent != nullptr) {
delete i18nServiceEvent;
i18nServiceEvent = nullptr;
}
HILOG_INFO_I18N("I18nServiceAbility Stop."); HILOG_INFO_I18N("I18nServiceAbility Stop.");
} }
} // namespace I18n } // namespace I18n

View File

@ -0,0 +1,136 @@
/*
* 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 <common_event_data.h>
#include <common_event_manager.h>
#include <common_event_support.h>
#include "common_event_subscriber.h"
#include "i18n_hilog.h"
#include "multi_users.h"
#include "i18n_service_event.h"
namespace OHOS {
namespace Global {
namespace I18n {
const int I18nServiceEvent::RETRY = 3;
I18nServiceEvent::I18nServiceEvent()
{
userSwitchKey = "usual.event.USER_SWITCHED";
userAdded = "usual.event.USER_ADDED";
userRemoved = "usual.event.USER_REMOVED";
handleEventFunc.emplace(userSwitchKey, &I18nServiceEvent::HandleSwitchUser);
handleEventFunc.emplace(userAdded, &I18nServiceEvent::HandleAddUser);
handleEventFunc.emplace(userRemoved, &I18nServiceEvent::HandleRemoveUser);
for (auto& it : I18nServiceEvent::handleEventFunc) {
eventHandles.emplace(it.first, std::bind(it.second, this, std::placeholders::_1));
}
}
I18nServiceEvent::~I18nServiceEvent()
{
eventHandles.clear();
handleEventFunc.clear();
UnSubscriberEvent();
}
void I18nServiceEvent::SubscriberEvent()
{
if (subscriber) {
return;
}
EventFwk::MatchingSkills matchingSkills;
for (auto& event : handleEventFunc) {
matchingSkills.AddEvent(event.first);
}
EventFwk::CommonEventSubscribeInfo subscribeInfo(matchingSkills);
subscriber = std::make_shared<I18nServiceSubscriber>(subscribeInfo, *this);
int32_t retry = 3;
do {
bool status = EventFwk::CommonEventManager::SubscribeCommonEvent(subscriber);
if (status) {
HILOG_INFO_I18N("SubscriberEvent: SubscriberEvent success.");
return;
}
HILOG_INFO_I18N("SubscriberEvent: SubscriberEvent failed %{public}d.", retry);
retry--;
sleep(1);
} while (retry);
HILOG_INFO_I18N("SubscriberEvent: SubscriberEvent failed");
}
void I18nServiceEvent::UnSubscriberEvent()
{
if (subscriber) {
bool status = EventFwk::CommonEventManager::UnSubscribeCommonEvent(subscriber);
if (status != 0) {
HILOG_INFO_I18N("UnSubscriberEvent: UnSubscriberEvent failed");
}
subscriber = nullptr;
}
}
void I18nServiceEvent::CheckStartReason(const SystemAbilityOnDemandReason& startReason)
{
std::string action = startReason.GetName();
HILOG_INFO_I18N("CheckStartReason: start reason is %{public}s", action.c_str());
if (action == userSwitchKey) {
std::string localId = std::to_string(startReason.GetExtraData().GetCode());
MultiUsers::SwitchUser(localId);
} else if (action == userAdded) {
std::string localId = std::to_string(startReason.GetExtraData().GetCode());
MultiUsers::AddUser(localId);
} else if (action == userRemoved) {
std::string localId = std::to_string(startReason.GetExtraData().GetCode());
MultiUsers::RemoveUser(localId);
}
}
void I18nServiceEvent::OnReceiveEvent(const EventFwk::CommonEventData& data)
{
AAFwk::Want want = data.GetWant();
std::string action = want.GetAction();
auto it = eventHandles.find(action);
if (it == eventHandles.end()) {
HILOG_INFO_I18N("OnReceiveEvent: ignore event %{public}s", action.c_str());
return;
}
HILOG_INFO_I18N("OnReceiveEvent: handle event %{public}s", action.c_str());
it->second(data);
}
void I18nServiceEvent::HandleSwitchUser(const EventFwk::CommonEventData& data) const
{
AAFwk::Want want = data.GetWant();
std::string localId = std::to_string(data.GetCode());
MultiUsers::SwitchUser(localId);
}
void I18nServiceEvent::HandleAddUser(const EventFwk::CommonEventData& data) const
{
std::string localId = std::to_string(data.GetCode());
MultiUsers::AddUser(localId);
}
void I18nServiceEvent::HandleRemoveUser(const EventFwk::CommonEventData& data) const
{
std::string localId = std::to_string(data.GetCode());
MultiUsers::RemoveUser(localId);
}
} // namespace I18n
} // namespace Global
} // namespace OHOS