Android12之ServiceManager::addService注册服务的本质(一百五十八)

news2025/1/8 4:29:24

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长!

优质专栏:Audio工程师进阶系列原创干货持续更新中……】🚀

人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药.

更多原创,欢迎关注:Android系统攻城狮

欢迎关注Android系统攻城狮

1.前言

本篇目的:理解ServiceManager成员函数addService是如何添加服务的。

2.ServiceManager::addService如何添加服务实现

Status ServiceManager::addService(const std::string& name, const sp<IBinder>& binder, bool allowIsolated, int32_t dumpPriority) {
    auto ctx = mAccess->getCallingContext();

    // apps cannot add services
    if (multiuser_get_app_id(ctx.uid) >= AID_APP) {
        return Status::fromExceptionCode(Status::EX_SECURITY);
    }

    if (!mAccess->canAdd(ctx, name)) {
        return Status::fromExceptionCode(Status::EX_SECURITY);
    }

    if (binder == nullptr) {
        return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
    }

    if (!isValidServiceName(name)) {
        LOG(ERROR) << "Invalid service name: " << name;
        return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
    }

#ifndef VENDORSERVICEMANAGER
    if (!meetsDeclarationRequirements(binder, name)) {
        // already logged
        return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
    }
#endif  // !VENDORSERVICEMANAGER

    // implicitly unlinked when the binder is removed
    if (binder->remoteBinder() != nullptr &&
        binder->linkToDeath(sp<ServiceManager>::fromExisting(this)) != OK) {
        LOG(ERROR) << "Could not linkToDeath when adding " << name;
        return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
    }

    // Overwrite the old service if it exists
    mNameToService[name] = Service {
        .binder = binder,
        .allowIsolated = allowIsolated,
        .dumpPriority = dumpPriority,
        .debugPid = ctx.debugPid,
    };

    auto it = mNameToRegistrationCallback.find(name);
    if (it != mNameToRegistrationCallback.end()) {
        for (const sp<IServiceCallback>& cb : it->second) {
            mNameToService[name].guaranteeClient = true;
            // permission checked in registerForNotifications
            cb->onRegistration(name, binder);
        }
    }

    return Status::ok();
}

<1>.关键点

mNameToService[name] = Service {
.binder = binder,
.allowIsolated = allowIsolated,
.dumpPriority = dumpPriority,
.debugPid = ctx.debugPid,
};

<2>.注释

其中name表示服务名,binder表示每个服务的实例对象,将他们存放在mNameToService里面,那么mNameToService是什么类型呢?接着往下看

<3>.mNameToService定义

# ServiceManager.h
struct Service {
        sp<IBinder> binder; // not null
        bool allowIsolated;
        int32_t dumpPriority;
        bool hasClients = false; // notifications sent on true -> false.
        bool guaranteeClient = false; // forces the client check to true
        pid_t debugPid = 0; // the process in which this service runs

        // the number of clients of the service, including servicemanager itself
        ssize_t getNodeStrongRefCount();
    };
using ServiceMap = std::map<std::string, Service>;
ServiceMap mNameToService;

  由以上代码可以看到mNameToService的类型是ServiceMap,ServiceMap又是std::map<std::string, Service>的别名,它是一个C++的STL的map容器,第一个参数是key,第二个是value。
  第一个参数的类型是string,第二个是Service类。

<4>.再看mNameToService[name]

mNameToService[name] = Service {
        .binder = binder,
        .allowIsolated = allowIsolated,
        .dumpPriority = dumpPriority,
        .debugPid = ctx.debugPid,
    };
我们再看上边表达式初始化,将类Service的所有成员变量插入到map容器,对应的key就是name,Service的成员变量包括.binder(表示服务类对象),dumpPriority(表示优先级)。

3.addService应用实例

#include <cstdio>
#include <iostream>
#include <typeinfo>
#include <map>

using namespace std;

class Binder{
};

//struct Service {
class Service {
public:
  Binder *binder;
  bool allowIsolated;
  int32_t dumpPriority;
  bool hasClients = false;
  bool guaranteeClient = false;
  pid_t pid = 0;
  ssize_t getNodeStrongRefCount();
};

//using设置别名:ServiceMap;容器map第一个参数是key,第二个是value;value为Service,Service又是一个类,包含变量和函数.
using ServiceMap = map<string, Service>;
ServiceMap mNameToService;

int main(){

  Binder *binder1 = new Binder;
  string name = "manager";
  mNameToService[name] = Service {
    .binder = binder1,
    .allowIsolated = false,
    .dumpPriority = 20,
    .guaranteeClient = true,
    .pid = 10,
  };

  string name_01 = "camera";
  Binder *binder2 = new Binder;
  mNameToService[name_01] = Service {
    .binder = binder2,
    .allowIsolated = false,
    .dumpPriority = 24,
    .guaranteeClient = false,
    .pid = 11,
  };

  //first:表示key的值;second:表示value的值,即Service.
  for(const auto& pair : mNameToService) {
    printf("xxx-------->line = %d, first_name = %s, priority = %d, pid = %d\n",__LINE__,pair.first.c_str(), pair.second.dumpPriority,pair.second.pid);
  }
}

打印:
xxx-------->line = 51, first_name = camera, priority = 24, pid = 11
xxx-------->line = 51, first_name = manager, priority = 20, pid = 10

4.总结

ServiceManager调用addService注册服务类,本质是将服务名+服务的对象插入到C++的map容器中,Client使用的时候,可以从map容器中获取就可以了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/707452.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何用smardaten90天快速开发并上线智慧空间loT物联平台?

前言 大家好&#xff0c;我是小白白&#xff0c;前段时间一位好友接手了一个“烫手山芋”开发任务&#xff0c;77万㎡的科技园区需要打造智慧空间物联平台。要求接入600园区设备&#xff0c;处理15000日数据量&#xff0c;在打造整体IOT物联底座之上&#xff0c;构建起整个园区…

三电阻采样的劣势分析

最近控制过程中&#xff0c;被下三桥采样小坑了一下。 如下图所示为下桥臂三电阻采样方式&#xff0c;该方法的采样器件是高精度电阻&#xff0c;电阻两端电压经过采样调理电路输出至单片机ADC&#xff0c;三电阻采样成本低、结构简单&#xff0c;并且采样信号和输出强电之间是…

【Unity3D】素描特效

1 非真实渲染 法线贴图和凹凸映射中讲述了普通光照的渲染原理&#xff0c;实现的效果比较贴近真实世界&#xff08;照相写实主义&#xff0c;Photorealism&#xff09;&#xff0c;非真实渲染&#xff08;Non-Photorealism Rendering&#xff0c;NPR&#xff09;在照相写实主义…

7-数组创建函数还有哪些?【视频版】

目录 问题视频解答 问题 视频解答 点击观看&#xff1a; 7-数组创建函数还有哪些&#xff1f;

基于IDEA操作springboot项目构建docker镜像部署到云服务器并在idea把镜像推送到harbor仓库

云服务器系统环境: 华为云 Ubuntu 9.3.0-17ubuntu1~20.04 1.ECS准备docker相关环境 1.1ECS安装docker 一行一行执行 都是从官网找的命令 sudo -i apt update apt install apt-transport-https ca-certificates curl gnupg-agent software-properties-common curl -fsSL htt…

Linux学习之screen和系统日志

screen yum install -y screen安装screen。 输入screen就可以进入screen环境。 在screen环境中执行tail -f /var/log/messages。 可以先按Ctrla&#xff0c;这时没有反应&#xff0c;需要紧接着迅速按d才能退出screen环境。 使用screen -r 11326还可以进入到刚刚挂起的s…

【Rust】基本语法

文章目录 变量与可变性变量与常量Shadowing&#xff08;隐藏&#xff09;数据类型标量类型1.整数类型2.浮点类型3.布尔类型4.字符类型 复合类型1.Tuple2.数组 函数if表达式循环1.loop2.while3.for 变量与可变性 声明变量使用let关键字&#xff0c;默认情况下&#xff0c;变量是…

Android 开发环境搭建

系列文章 MySQL安装教程&#xff08;详细&#xff09; 本文链接&#xff1a;https://blog.csdn.net/youcheng_ge/article/details/126037520 MySQL卸载教程&#xff08;详细&#xff09; 本文链接&#xff1a;https://blog.csdn.net/youcheng_ge/article/details/129279265 …

【C++】类型转换和IO流

C完结 文章目录 前言一、C的四种类型转换二、IO流总结 前言 首先我们看看C语言中的类型转换&#xff1a; 在 C 语言中&#xff0c;如果 赋值运算符左右两侧类型不同&#xff0c;或者形参与实参类型不匹配&#xff0c;或者返回值类型与 接收返回值类型不一致时&#xff0c;就需…

tmux-解决ssh长时间不操作便会话结束的问题

Tmux 是一个终端复用器&#xff08;terminal multiplexer&#xff09;&#xff0c;非常有用&#xff0c;属于常用的开发工具。 如果电脑死机会话中断的话会导致服务器上基于bash的所有进程都被强制关闭。tmux确实是解决这个问题的好办法&#xff0c;而且很容易上手&#xff0c…

帝国CMS自动刷新首页和自定义列表页:实现网站内容的自动更新

本文将介绍一种实现帝国CMS自动刷新首页和自定义列表页的方法。 以下是具体的实现步骤&#xff1a; 1、设置自定义key 添加网站 设置发布网站 发布成功 首先&#xff0c;在您的帝国CMS根目录下创建一个名为"htmlindex"的文件夹&#xff08;您可以自行命名&#xff…

基于网格式搜索SVM方法的电力负荷预测

来源公众号:320科技工作室 随着生活质量的提高&#xff0c;人们对电的需求不断上升&#xff0c;电力系统的发展变得尤为重要。准确的电力负荷预测能够使电力部门降低发电成本&#xff0c;合理安排设备维护以及节省能源&#xff0c;并为电力规划以及制定合理发电量提供相关依据…

PACS医学影像系统(完整版)

一、PACS影像存取与传输系统以实现医学影像数字化存储、诊断为核心任务&#xff0c;从医学影像设备&#xff08;如CT、CR、DR、MR、DSA、RF等&#xff09;获取影像&#xff0c;集中存储、综合管理医学影像及病人相关信息&#xff0c;建立数字化工作流程。 二、系统可实现检查预…

【Echarts系列】— echarts饼图、圆环图配置代码图文详解

前言 简介&#xff1a;本文将从头开始&#xff0c;带你快速上手 echarts最常用图例—饼图 准备&#xff1a;请自行先将echarts图例引入你的项目&#xff0c;本文不多介绍。&#xff08;引入 echarts教程&#xff1a;http://t.csdn.cn/mkTa4&#xff09; 心得&#xff1a;echar…

LangChain 基于 ChatGPT 整合 Google 搜索 强化问答应用

一、LangChain Agents LangChain 中的 Agents 是什么呢&#xff0c;对于官方的描述是&#xff1a;某些应用程序不仅需要预先确定的对 LLM/其他工具的调用链&#xff0c;还可能需要依赖于用户输入的未知链。在这些类型的链中&#xff0c;有一个 Agents 可以访问一套工具。根据用…

【ISO26262】汽车功能安全第4部分:系统层面

第4部分:产品开发:系统层面 GB/T34590的本部分规定了车辆在系统层面产品开发的要求,包括: ———启动系统层面产品开发; ———技术安全要求的定义; ———技术安全概念; ———系统设计; ———相关项集成和测试; ———安全确认; ———功能安全评估;及 ———生产发布。

程序运行期间加载动态库

note 相关系统调用接口&#xff1a;dlopen\dlclose\dlerror\dlsym code math.c int add(int x, int y) {return (xy); }int sub(int x, int y) {return (x-y); } main.c #include <stdio.h> #include <stdlib.h> #include <dlfcn.h>int main(int argc, …

VMware网络模式大揭秘:打造高效稳定的虚拟机通讯网络

文章目录 一 VMWare网络连接1.1 查看VM网络模式1.2 VMWare三种网络模式1.2.1 桥接模式&#xff08;Bridged Mode&#xff09;1.2.2 主机模式&#xff08;Host-Only Mode&#xff09;1.2.3 NAT模式&#xff08;Network Address Translation Mode&#xff09; 1.3 补充知识&#…

linux基础命令总结

目录标题 目录操作1.绝对路径和相对路径2.目录的基本操作3.chomd、chown、chgrp4.cd命令 文件操作1.touch2.more4.cat5.grep6.rm7.cp8.mv9.find 磁盘操作1.df2.du date、passwd1.date2.passwd su、clear、man、who1.su2.man3.clear4.who unameuptimefreepsps与grep、kill1.与gr…

【Leetcode】动态规划 刷题训练(八)

文章目录 413. 等差数列划分状态转移方程完整代码 978. 最长湍流子数组题目解析状态转移方程f[i]状态转移方程g[i]状态转移方程 完整代码 139. 单词拆分状态转移方程初始化完整代码 413. 等差数列划分 点击查看&#xff1a;等差数列划分 如果一个数列 至少有三个元素 &#x…