【OpenHarmony】IPC之SaMgr的创建

文章目录

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

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值