* 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 "ability_runtime/cj_ability_context.h"
#include "data_share_predicates_impl.h"
#include "contacts.h"
#include "contacts_control.h"
#include "contacts_permission.h"
#include "datashare_helper.h"
#include "datashare_predicates.h"
#include "hilog_wrapper_api.h"
#include "native/ffi_remote_data.h"
using namespace OHOS;
using namespace OHOS::AbilityRuntime;
using namespace OHOS::ContactsFfi;
using namespace OHOS::DataShare;
using namespace OHOS::FFI;
namespace OHOS {
namespace ContactsFfi {
bool IsInvalidId(int id)
{
return id <= 0;
}
std::shared_ptr<DataShareHelper> dsHelperFromContext(int64_t contextId)
{
sptr<CJAbilityContext> context = FFIData::GetData<CJAbilityContext>(contextId);
if (context == nullptr) {
HILOG_ERROR("dsHelperFromContext context is null");
return nullptr;
}
return DataShareHelper::Creator(context->GetToken(), CONTACTS_DATA_URI);
}
int64_t Contacts::CJaddContact(int64_t contextId, DataShareValuesBucket rawContact,
std::vector<DataShareValuesBucket> contactData, int32_t *errCode)
{
HILOG_INFO("CJaddContact data size = %{public}d", (int) contactData.size());
std::shared_ptr<DataShareHelper> dataShareHelper = dsHelperFromContext(contextId);
if (dataShareHelper == nullptr) {
HILOG_ERROR("CJaddContact Permission denied!");
*errCode = PERMISSION_ERROR;
return Contacts::INVALID_CONTACT_ID;
}
ContactsControl contactsControl;
int rawId = contactsControl.RawContactInsert(dataShareHelper, rawContact);
unsigned int size = contactData.size();
for (unsigned int i = 0; i < size; ++i) {
contactData[i].Put("raw_contact_id", rawId);
}
int code = contactsControl.ContactDataInsert(dataShareHelper, contactData);
dataShareHelper->Release();
dataShareHelper = nullptr;
*errCode = code;
if (code == SUCCESS) {
HILOG_INFO("CJaddContact returns id = %{public}d", rawId);
return rawId;
} else {
HILOG_ERROR("CJaddContact gets errCode = %{public}d and returns id = -1", code);
return Contacts::INVALID_CONTACT_ID;
}
}
void Contacts::CJdeleteContact(int64_t contextId, int64_t predicatesId, int32_t *errCode)
{
std::shared_ptr<DataShareHelper> dataShareHelper = dsHelperFromContext(contextId);
if (dataShareHelper == nullptr) {
HILOG_ERROR("CJdeleteContact Permission denied!");
*errCode = PERMISSION_ERROR;
return;
}
std::shared_ptr<DataSharePredicates> predicates =
FFIData::GetData<DataSharePredicatesImpl>(predicatesId)->GetPredicates();
ContactsControl contactsControl;
int code = contactsControl.ContactDelete(dataShareHelper, *predicates);
dataShareHelper->Release();
dataShareHelper = nullptr;
*errCode = code;
}
DataSharePredicates buildQueryDataPredicates(int64_t contactId)
{
DataSharePredicates predicates;
if (contactId != 0) {
std::vector<std::string> fields;
fields.push_back("raw_contact_id");
predicates.EqualTo("is_deleted", "0");
predicates.And();
predicates.EqualTo("contact_id", std::to_string(contactId));
predicates.GroupBy(fields);
}
return predicates;
}
int GetRawIdByResultSet(const std::shared_ptr<DataShare::DataShareResultSet> &resultSet)
{
if (resultSet == nullptr) {
return -1;
}
int resultSetNum = resultSet->GoToFirstRow();
int intValue = 0;
while (resultSetNum == OHOS::NativeRdb::E_OK) {
resultSet->GetInt(0, intValue);
resultSetNum = resultSet->GoToNextRow();
}
resultSet->Close();
return intValue;
}
void Contacts::CJupdateContact(int64_t contextId, int64_t contactId, std::vector<DataShareValuesBucket> contactData,
int64_t predicatesId, int32_t *errCode)
{
std::shared_ptr<DataShareHelper> dataShareHelper = dsHelperFromContext(contextId);
if (dataShareHelper == nullptr) {
HILOG_ERROR("CJupdateContact Permission denied!");
*errCode = PERMISSION_ERROR;
return;
}
if (IsInvalidId(contactId)) {
HILOG_ERROR("CJupdateContact Parameter invalid! %{public}lld", static_cast<long long>(contactId));
*errCode = PARAMETER_ERROR;
return;
}
std::shared_ptr<DataSharePredicates> deletePredicates =
FFIData::GetData<DataSharePredicatesImpl>(predicatesId)->GetPredicates();
ContactsControl contactsControl;
std::vector<std::string> queryDataColumns;
queryDataColumns.push_back("raw_contact_id");
DataSharePredicates queryDataPredicates = buildQueryDataPredicates(contactId);
std::shared_ptr<DataShareResultSet> resultSet =
contactsControl.ContactQuery(dataShareHelper, queryDataColumns, queryDataPredicates);
int rawId = GetRawIdByResultSet(resultSet);
if (rawId <= 0) {
HILOG_ERROR("CJupdateContact contact rawId equals %{public}d", rawId);
*errCode = ERROR;
dataShareHelper->Release();
dataShareHelper = nullptr;
return;
}
unsigned int size = contactData.size();
for (unsigned int i = 0; i < size; ++i) {
contactData[i].Put("raw_contact_id", rawId);
}
deletePredicates->And();
deletePredicates->EqualTo("raw_contact_id", std::to_string(rawId));
int resultCode = contactsControl.ContactDataDelete(dataShareHelper, *(deletePredicates));
if (resultCode >= 0) {
resultCode = contactsControl.ContactDataInsert(dataShareHelper, contactData);
}
dataShareHelper->Release();
dataShareHelper = nullptr;
*errCode = resultCode;
}
DataSharePredicates buildIsLocalContactPredicates(int64_t id)
{
DataShare::DataSharePredicates predicates;
if (id != 0) {
predicates.EqualTo("is_deleted", "0");
predicates.And();
predicates.EqualTo("contact_id", std::to_string(id));
predicates.And();
predicates.EqualTo("account_type", "com.ohos.contacts");
predicates.And();
predicates.EqualTo("account_name", "phone");
}
return predicates;
}
bool Contacts::CJisLocalContact(int64_t contextId, int64_t contactId, int32_t *errCode)
{
ContactsTelephonyPermission permission;
if (!permission.CheckPermission(Permission::READ_CONTACTS)) {
HILOG_ERROR("CJisLocalContact Permission denied!");
*errCode = PERMISSION_ERROR;
return false;
}
if (IsInvalidId(contactId)) {
HILOG_ERROR("CJisLocalContact Parameter invalid! %{public}lld", static_cast<long long>(contactId));
*errCode = PARAMETER_ERROR;
return false;
}
std::shared_ptr<DataShareHelper> dataShareHelper = dsHelperFromContext(contextId);
if (dataShareHelper == nullptr) {
HILOG_ERROR("CJisLocalContact Permission denied!");
*errCode = PERMISSION_ERROR;
return false;
}
ContactsControl contactsControl;
DataSharePredicates predicates = buildIsLocalContactPredicates(contactId);
std::vector<std::string> columns;
std::shared_ptr<DataShareResultSet> resultSet = contactsControl.ContactQuery(dataShareHelper, columns, predicates);
if (resultSet == nullptr) {
return false;
}
int resultSetNum = resultSet->GoToFirstRow();
bool isLocal = resultSetNum == OHOS::NativeRdb::E_OK;
resultSet->Close();
dataShareHelper->Release();
dataShareHelper = nullptr;
return isLocal;
}
DataSharePredicates buildIsMyCardPredicates(int64_t id)
{
DataShare::DataSharePredicates predicates;
if (id != 0) {
predicates.EqualTo("is_deleted", "0");
predicates.And();
predicates.EqualTo("contact_id", std::to_string(id));
}
return predicates;
}
bool Contacts::CJisMyCard(int64_t contextId, int64_t contactId, int32_t *errCode)
{
ContactsTelephonyPermission permission;
if (!permission.CheckPermission(Permission::READ_CONTACTS)) {
HILOG_ERROR("CJisMyCard Permission denied!");
*errCode = PERMISSION_ERROR;
return false;
}
if (IsInvalidId(contactId)) {
HILOG_ERROR("CJisMyCard Parameter invalid! %{public}lld", static_cast<long long>(contactId));
*errCode = PARAMETER_ERROR;
return false;
}
std::shared_ptr<DataShareHelper> dataShareHelper = dsHelperFromContext(contextId);
if (dataShareHelper == nullptr) {
HILOG_ERROR("CJisMyCard Permission denied!");
*errCode = PERMISSION_ERROR;
return false;
}
ContactsControl contactsControl;
DataSharePredicates predicates = buildIsMyCardPredicates(contactId);
std::vector<std::string> columns;
std::shared_ptr<DataShareResultSet> resultSet = contactsControl.MyCardQuery(dataShareHelper, columns, predicates);
if (resultSet == nullptr) {
dataShareHelper->Release();
dataShareHelper = nullptr;
return false;
}
int resultSetNum = resultSet->GoToFirstRow();
bool isMyCard = resultSetNum == OHOS::NativeRdb::E_OK;
resultSet->Close();
dataShareHelper->Release();
dataShareHelper = nullptr;
return isMyCard;
}
ContactsData* Contacts::CJqueryMyCard(int64_t contextId, int64_t predicatesId, int32_t *errCode)
{
ContactsTelephonyPermission permission;
if (!permission.CheckPermission(Permission::READ_CONTACTS)) {
HILOG_ERROR("CJqueryMyCard Permission denied!");
*errCode = PERMISSION_ERROR;
return nullptr;
}
std::shared_ptr<DataShareHelper> dataShareHelper = dsHelperFromContext(contextId);
if (dataShareHelper == nullptr) {
HILOG_ERROR("CJqueryMyCard Permission denied!");
*errCode = PERMISSION_ERROR;
return nullptr;
}
std::shared_ptr<DataSharePredicates> predicates =
FFIData::GetData<DataSharePredicatesImpl>(predicatesId)->GetPredicates();
ContactsControl contactsControl;
std::vector<std::string> columns;
std::shared_ptr<DataShareResultSet> resultSet = contactsControl.MyCardQuery(dataShareHelper, columns, *predicates);
ContactsData* contacts = parseResultSetForContacts(resultSet, errCode);
dataShareHelper->Release();
dataShareHelper = nullptr;
return contacts;
}
GroupsData* Contacts::CJqueryGroups(int64_t contextId, int64_t predicatesId, int32_t *errCode)
{
ContactsTelephonyPermission permission;
if (!permission.CheckPermission(Permission::READ_CONTACTS)) {
HILOG_ERROR("CJqueryGroups Permission denied!");
*errCode = PERMISSION_ERROR;
return nullptr;
}
std::shared_ptr<DataShareHelper> dataShareHelper = dsHelperFromContext(contextId);
if (dataShareHelper == nullptr) {
HILOG_ERROR("CJqueryGroups Permission denied!");
*errCode = PERMISSION_ERROR;
return nullptr;
}
std::shared_ptr<DataSharePredicates> predicates =
FFIData::GetData<DataSharePredicatesImpl>(predicatesId)->GetPredicates();
ContactsControl contactsControl;
std::vector<std::string> columns;
std::shared_ptr<DataShareResultSet> resultSet = contactsControl.GroupsQuery(dataShareHelper, columns, *predicates);
GroupsData* groups = parseResultSetForGroups(resultSet, errCode);
dataShareHelper->Release();
dataShareHelper = nullptr;
return groups;
}
HoldersData* Contacts::CJqueryHolders(int64_t contextId, int32_t *errCode)
{
ContactsTelephonyPermission permission;
if (!permission.CheckPermission(Permission::READ_CONTACTS)) {
HILOG_ERROR("CJqueryHolders Permission denied!");
*errCode = PERMISSION_ERROR;
return nullptr;
}
std::shared_ptr<DataShareHelper> dataShareHelper = dsHelperFromContext(contextId);
if (dataShareHelper == nullptr) {
HILOG_ERROR("CJqueryHolders Permission denied!");
*errCode = PERMISSION_ERROR;
return nullptr;
}
ContactsControl contactsControl;
DataSharePredicates predicates;
std::vector<std::string> columns;
std::shared_ptr<DataShareResultSet> resultSet = contactsControl.HolderQuery(dataShareHelper, columns, predicates);
HoldersData* holders = parseResultSetForHolders(resultSet, errCode);
dataShareHelper->Release();
dataShareHelper = nullptr;
return holders;
}
ContactsData* Contacts::CJqueryContacts(int64_t contextId, int64_t predicatesId, int32_t *errCode)
{
ContactsTelephonyPermission permission;
if (!permission.CheckPermission(Permission::READ_CONTACTS)) {
HILOG_ERROR("CJqueryContacts Permission denied!");
*errCode = PERMISSION_ERROR;
return nullptr;
}
std::shared_ptr<DataShareHelper> dataShareHelper = dsHelperFromContext(contextId);
if (dataShareHelper == nullptr) {
HILOG_ERROR("CJqueryContacts Permission denied!");
*errCode = PERMISSION_ERROR;
return nullptr;
}
std::shared_ptr<DataSharePredicates> predicates =
FFIData::GetData<DataSharePredicatesImpl>(predicatesId)->GetPredicates();
ContactsControl contactsControl;
std::vector<std::string> columns;
std::shared_ptr<DataShareResultSet> resultSet =
contactsControl.ContactQuery(dataShareHelper, columns, *predicates);
ContactsData* contacts = parseResultSetForContacts(resultSet, errCode);
dataShareHelper->Release();
dataShareHelper = nullptr;
return contacts;
}
}
}