文章目录
ContextObject的设置
openharmony/foundation/systemabilitymgr/samgr/services/samgr/native/source/main.cpp
int main(int argc, char *argv[])
{
HILOGI("%{public}s called, enter System Ability Manager ", __func__);
Samgr::MemoryGuard cacheGuard;
OHOS::sptr<OHOS::SystemAbilityManager> manager = OHOS::SystemAbilityManager::GetInstance();
manager->Init();
OHOS::sptr<OHOS::IRemoteObject> serv = manager->AsObject();
if (!IPCSkeleton::SetContextObject(serv)) {
HILOGE("set context fail!"); // add log for dfx
}
manager->AddSamgrToAbilityMap();
int result = SetParameter("bootevent.samgr.ready", "true");
HILOGI("set samgr ready ret : %{public}s", result == 0 ? "succeed" : "failed");
manager->StartDfxTimer();
OHOS::IPCSkeleton::JoinWorkThread();
return -1;
}
openharmony/foundation/communication/ipc/ipc/native/src/core/source/ipc_skeleton.cpp
bool IPCSkeleton::SetContextObject(sptr<IRemoteObject> &object)
{
IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent();
if (current != nullptr) {
return current->SetRegistryObject(object);
}
return false;
}
openharmony/foundation/communication/ipc/ipc/native/src/core/source/ipc_process_skeleton.cpp
bool IPCProcessSkeleton::SetRegistryObject(sptr<IRemoteObject> &object)
{
CHECK_INSTANCE_EXIT_WITH_RETVAL(exitFlag_, false);
if (object == nullptr) {
ZLOGE(LOG_LABEL, "object is null");
return false;
}
auto current = ProcessSkeleton::GetInstance();
if (current == nullptr) {
ZLOGE(LOG_LABEL, "get process skeleton failed");
return false;
}
IRemoteInvoker *invoker = IPCThreadSkeleton::GetRemoteInvoker(IRemoteObject::IF_PROT_DEFAULT);
if (invoker == nullptr) {
ZLOGE(LOG_LABEL, "fail to get invoker");
return false;
}
bool ret = invoker->SetRegistryObject(object);
if (ret) {
current->SetRegistryObject(object);
current->SetSamgrFlag(true);
}
ZLOGI(LOG_LABEL, "set registry result:%{public}d", ret);
return ret;
}
IRemoteInvoker有两种,BinderInvoder和DBinderDatabusInvoker,BinderInvoker是默认的,看下BinderInvoker的SetRegistryObject
openharmony/foundation/communication/ipc/ipc/native/src/mock/source/binder_invoker.cpp
bool BinderInvoker::SetRegistryObject(sptr<IRemoteObject> &object)
{
if ((binderConnector_ == nullptr) || (!binderConnector_->IsDriverAlive())) {
return false;
}
if (object->IsProxyObject()) {
ZLOGE(LABEL, "set wrong object!");
return false;
}
Parcel dummy;
int result = binderConnector_->WriteBinder(BINDER_SET_CONTEXT_MGR, &dummy);
if (result != ERR_NONE) {
ZLOGE(LABEL, "set registry fail, driver error:%{public}d", result);
return false;
}
return true;
}
openharmony/foundation/communication/ipc/ipc/native/src/mock/source/binder_connector.cpp
int BinderConnector::WriteBinder(unsigned long request, void *value)
{
int err = -EINTR;
while (err == -EINTR) {
if (ioctl(driverFD_, request, value) >= 0) {
err = ERR_NONE;
} else {
err = -errno;
}
if (err == -EINTR) {
ZLOGE(LABEL, "ioctl_binder returned EINTR");
ReportEvent(DbinderErrorCode::KERNEL_DRIVER_ERROR, std::string(DbinderErrorCode::ERROR_CODE),
KERNEL_DRIVER_WRITE_IPC_DRIVER_FAILURE, __FUNCTION__);
}
}
return err;
}
WriteBinder就开始和Binder驱动交互,使用系统调用ioctl,给驱动发送BINDER_SET_CONTEXT_MGR命令,参数&dummy:Parcel是哑的,实质在驱动层没有用
openharmony/kernel/linux/linux-5.10/drivers/android/binder.c
static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
......
case BINDER_SET_CONTEXT_MGR_EXT: {
struct flat_binder_object fbo;
if (copy_from_user(&fbo, ubuf, sizeof(fbo))) {
ret = -EINVAL;
goto err;
}
ret = binder_ioctl_set_ctx_mgr(filp, &fbo);
if (ret)
goto err;
break;
}
case BINDER_SET_CONTEXT_MGR:
ret = binder_ioctl_set_ctx_mgr(filp, NULL);
if (ret)
goto err;
break;
.......
}
static int binder_ioctl_set_ctx_mgr(struct file *filp,
struct flat_binder_object *fbo)
{
int ret = 0;
struct binder_proc *proc = filp->private_data;
struct binder_context *context = proc->context;
struct binder_node *new_node;
kuid_t curr_euid = current_euid();
mutex_lock(&context->context_mgr_node_lock);
if (context->binder_context_mgr_node) {
pr_err("BINDER_SET_CONTEXT_MGR already set\n");
ret = -EBUSY;
goto out;
}
ret = security_binder_set_context_mgr(proc->cred);
if (ret < 0)
goto out;
if (uid_valid(context->binder_context_mgr_uid)) {
if (!uid_eq(context->binder_context_mgr_uid, curr_euid)) {
pr_err("BINDER_SET_CONTEXT_MGR bad uid %d != %d\n",
from_kuid(&init_user_ns, curr_euid),
from_kuid(&init_user_ns,
context->binder_context_mgr_uid));
ret = -EPERM;
goto out;
}
} else {
context->binder_context_mgr_uid = curr_euid;
}
new_node = binder_new_node(proc, fbo);
if (!new_node) {
ret = -ENOMEM;
goto out;
}
binder_node_lock(new_node);
new_node->local_weak_refs++;
new_node->local_strong_refs++;
new_node->has_strong_ref = 1;
new_node->has_weak_ref = 1;
context->binder_context_mgr_node = new_node;
binder_node_unlock(new_node);
binder_put_node(new_node);
out:
mutex_unlock(&context->context_mgr_node_lock);
return ret;
}
根据当前进程创建binder_node,并设置为binder_context_mgr_node