IMS中Binder案例

2023-10-27

android12-release


1、FWK层中AIDL形式

Android 接口定义语言 (AIDL)Android 应用层 到 HAL 层

AIDL形式是Android中binder机制的具体实现。按照规范aidl/hidl文件自动生成相应代码文件:
客户端获取proxyasInterface(android.os.IBinder obj)
服务端实现Stub:class Stub extends android.os.Binder

1.1 服务端实现Stub

InputManagerService继承IInputManager.StubSystemServer.java中服务初始化添加到ServiceManager
frameworks/base/services/core/java/com/android/server/input/InputManagerService.java

frameworks/base/core/java/android/hardware/input/IInputManager.aidl

/** @hide */
interface IInputManager {
    // Gets input device information.
    InputDevice getInputDevice(int deviceId);
    int[] getInputDeviceIds();

    // Enable/disable input device.
    boolean isInputDeviceEnabled(int deviceId);
    void enableInputDevice(int deviceId);
    void disableInputDevice(int deviceId);

    // Reports whether the hardware supports the given keys; returns true if successful
    boolean hasKeys(int deviceId, int sourceMask, in int[] keyCodes, out boolean[] keyExists);

    // Temporarily changes the pointer speed.
    void tryPointerSpeed(int speed);

    // Injects an input event into the system.  To inject into windows owned by other
    // applications, the caller must have the INJECT_EVENTS permission.
    @UnsupportedAppUsage
    boolean injectInputEvent(in InputEvent ev, int mode);

    VerifiedInputEvent verifyInputEvent(in InputEvent ev);

    // Calibrate input device position
    TouchCalibration getTouchCalibrationForInputDevice(String inputDeviceDescriptor, int rotation);
    void setTouchCalibrationForInputDevice(String inputDeviceDescriptor, int rotation,
            in TouchCalibration calibration);

    // Keyboard layouts configuration.
    KeyboardLayout[] getKeyboardLayouts();
    KeyboardLayout[] getKeyboardLayoutsForInputDevice(in InputDeviceIdentifier identifier);
    KeyboardLayout getKeyboardLayout(String keyboardLayoutDescriptor);
    String getCurrentKeyboardLayoutForInputDevice(in InputDeviceIdentifier identifier);
    void setCurrentKeyboardLayoutForInputDevice(in InputDeviceIdentifier identifier,
            String keyboardLayoutDescriptor);
    String[] getEnabledKeyboardLayoutsForInputDevice(in InputDeviceIdentifier identifier);
    void addKeyboardLayoutForInputDevice(in InputDeviceIdentifier identifier,
            String keyboardLayoutDescriptor);
    void removeKeyboardLayoutForInputDevice(in InputDeviceIdentifier identifier,
            String keyboardLayoutDescriptor);

    // Registers an input devices changed listener.
    void registerInputDevicesChangedListener(IInputDevicesChangedListener listener);

    // Queries whether the device is currently in tablet mode
    int isInTabletMode();
    // Registers a tablet mode change listener
    void registerTabletModeChangedListener(ITabletModeChangedListener listener);

    // Queries whether the device's microphone is muted by switch
    int isMicMuted();

    // Input device vibrator control.
    void vibrate(int deviceId, in VibrationEffect effect, IBinder token);
    void vibrateCombined(int deviceId, in CombinedVibration vibration, IBinder token);
    void cancelVibrate(int deviceId, IBinder token);
    int[] getVibratorIds(int deviceId);
    boolean isVibrating(int deviceId);
    boolean registerVibratorStateListener(int deviceId, in IVibratorStateListener listener);
    boolean unregisterVibratorStateListener(int deviceId, in IVibratorStateListener listener);

    // Input device battery query.
    int getBatteryStatus(int deviceId);
    int getBatteryCapacity(int deviceId);

    void setPointerIconType(int typeId);
    void setCustomPointerIcon(in PointerIcon icon);

    oneway void requestPointerCapture(IBinder inputChannelToken, boolean enabled);

    /** Create an input monitor for gestures. */
    InputMonitor monitorGestureInput(String name, int displayId);

    // Add a runtime association between the input port and the display port. This overrides any
    // static associations.
    void addPortAssociation(in String inputPort, int displayPort);
    // Remove the runtime association between the input port and the display port. Any existing
    // static association for the cleared input port will be restored.
    void removePortAssociation(in String inputPort);

    // Add a runtime association between the input device and display.
    void addUniqueIdAssociation(in String inputDeviceName, in String displayUniqueId);
    // Remove the runtime association between the input device and display.
    void removeUniqueIdAssociation(in String inputDeviceName);

    InputSensorInfo[] getSensorList(int deviceId);

    boolean registerSensorListener(IInputSensorEventListener listener);

    void unregisterSensorListener(IInputSensorEventListener listener);

    boolean enableSensor(int deviceId, int sensorType, int samplingPeriodUs,
                int maxBatchReportLatencyUs);

    void disableSensor(int deviceId, int sensorType);

    boolean flushSensor(int deviceId, int sensorType);

    List<Light> getLights(int deviceId);

    LightState getLightState(int deviceId, int lightId);

    void setLightStates(int deviceId, in int[] lightIds, in LightState[] states, in IBinder token);

    void openLightSession(int deviceId, String opPkg, in IBinder token);

    void closeLightSession(int deviceId, in IBinder token);
}

frameworks/base/services/java/com/android/server/SystemServer.java

t.traceBegin("StartInputManagerService");
inputManager = new InputManagerService(context);
t.traceEnd();

t.traceBegin("DeviceStateManagerService");
mSystemServiceManager.startService(DeviceStateManagerService.class);
t.traceEnd();

if (!disableCameraService) {
    t.traceBegin("StartCameraServiceProxy");
    mSystemServiceManager.startService(CameraServiceProxy.class);
    t.traceEnd();
}

t.traceBegin("StartWindowManagerService");
// WMS needs sensor service ready
mSystemServiceManager.startBootPhase(t, SystemService.PHASE_WAIT_FOR_SENSOR_SERVICE);
wm = WindowManagerService.main(context, inputManager, !mFirstBoot, mOnlyCore,
        new PhoneWindowManager(), mActivityManagerService.mActivityTaskManager);
ServiceManager.addService(Context.WINDOW_SERVICE, wm, /* allowIsolated= */ false,
        DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PROTO);
ServiceManager.addService(Context.INPUT_SERVICE, inputManager,
        /* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL);
t.traceEnd();

1.2 客户端获取proxy

应用端获取服务getSystemService(Context.INPUT_SERVICE)),这里获取InputManager初始化InputManager.getInstance()(即是 IInputManager.Stub.asInterface(ServiceManager.getServiceOrThrow(Context.INPUT_SERVICE))
frameworks/base/core/java/android/app/SystemServiceRegistry.java


在这里插入图片描述

frameworks/base/core/java/android/hardware/input/InputManager.java

/**
 * Gets an instance of the input manager.
 *
 * @return The input manager instance.
 *
 * @hide
 */
@UnsupportedAppUsage
public static InputManager getInstance() {
    synchronized (InputManager.class) {
        if (sInstance == null) {
            try {
                sInstance = new InputManager(IInputManager.Stub
                        .asInterface(ServiceManager.getServiceOrThrow(Context.INPUT_SERVICE)));
            } catch (ServiceNotFoundException e) {
                throw new IllegalStateException(e);
            }
        }
        return sInstance;
    }
}

2、Native层中AIDL形式

Android 接口定义语言 (AIDL)Android 应用层 到 HAL 层

AIDL形式是Android中binder机制的具体实现。按照规范aidl/hidl文件自动生成相应代码文件:
C++中客户端对应Bp端,服务端对应Bn端

2.1 服务端对应Bn端

JNI调用到Native层,ServiceManager中添加"inputflinger"对应InputManager,InputManager继承BnInputFlinger端,对应方法实现返回binder::Status

  • defaultServiceManager()->addService(String16("inputflinger"), im); 添加"inputflinger"服务
  • class InputManager : public InputManagerInterface, public BnInputFlinger 对应Bn端

frameworks/native/libs/input/Android.bp
frameworks/native/libs/input/android/os/IInputFlinger.aidl

package android.os;

import android.FocusRequest;
import android.InputChannel;
import android.InputWindowInfo;
import android.os.ISetInputWindowsListener;

/** @hide */
interface IInputFlinger
{
    // SurfaceFlinger is the caller of this method, it uses the listener callback to ensure the
    // ordering when needed.
    // SurfaceFlinger calls this only every VSync, so overflow of binder's oneway buffer
    // shouldn't be a concern.
    oneway void setInputWindows(in InputWindowInfo[] inputHandles,
            in @nullable ISetInputWindowsListener setInputWindowsListener);
    InputChannel createInputChannel(in @utf8InCpp String name);
    void removeInputChannel(in IBinder connectionToken);
    /**
     * Sets focus to the window identified by the token. This must be called
     * after updating any input window handles.
     */
    oneway void setFocusedWindow(in FocusRequest request);
}

frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp

NativeInputManager::NativeInputManager(jobject contextObj,
        jobject serviceObj, const sp<Looper>& looper) :
        mLooper(looper), mInteractive(true) {
    JNIEnv* env = jniEnv();

    mServiceObj = env->NewGlobalRef(serviceObj);

    {
        AutoMutex _l(mLock);
        mLocked.systemUiLightsOut = false;
        mLocked.pointerSpeed = 0;
        mLocked.pointerGesturesEnabled = true;
        mLocked.showTouches = false;
        mLocked.pointerCapture = false;
        mLocked.pointerDisplayId = ADISPLAY_ID_DEFAULT;
    }
    mInteractive = true;

    InputManager* im = new InputManager(this, this);
    mInputManager = im;
    defaultServiceManager()->addService(String16("inputflinger"), im);
}

frameworks/native/services/inputflinger/InputManager.cpp
frameworks/native/services/inputflinger/InputManager.h

binder::Status setInputWindows(
        const std::vector<InputWindowInfo>& handles,
        const sp<ISetInputWindowsListener>& setInputWindowsListener) override;

binder::Status createInputChannel(const std::string& name, InputChannel* outChannel) override;
binder::Status removeInputChannel(const sp<IBinder>& connectionToken) override;
binder::Status setFocusedWindow(const FocusRequest&) override;

2.2 客户端对应Bp端

系统中查看在SurfaceFlinger::bootFinished()中有获取"inputflinger"服务使用。

  • defaultServiceManager()->getService(String16("inputflinger")) 获取"inputflinger"服务
  • mInputFlinger = interface_cast<os::IInputFlinger>(input) 转化Bp端,查看 Binder系列2-ServiceManager模板interface_cast => 模板::android::sp<Bp##INTERFACE>::make(obj)

frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp

void SurfaceFlinger::bootFinished() {
    if (mBootFinished == true) {
        ALOGE("Extra call to bootFinished");
        return;
    }
    mBootFinished = true;
    if (mStartPropertySetThread->join() != NO_ERROR) {
        ALOGE("Join StartPropertySetThread failed!");
    }

    if (mRenderEnginePrimeCacheFuture.valid()) {
        mRenderEnginePrimeCacheFuture.get();
    }
    const nsecs_t now = systemTime();
    const nsecs_t duration = now - mBootTime;
    ALOGI("Boot is finished (%ld ms)", long(ns2ms(duration)) );

    mFrameTracer->initialize();
    mFrameTimeline->onBootFinished();

    // wait patiently for the window manager death
    const String16 name("window");
    mWindowManager = defaultServiceManager()->getService(name);
    if (mWindowManager != 0) {
        mWindowManager->linkToDeath(static_cast<IBinder::DeathRecipient*>(this));
    }

    // stop boot animation
    // formerly we would just kill the process, but we now ask it to exit so it
    // can choose where to stop the animation.
    property_set("service.bootanim.exit", "1");

    const int LOGTAG_SF_STOP_BOOTANIM = 60110;
    LOG_EVENT_LONG(LOGTAG_SF_STOP_BOOTANIM,
                   ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));

    sp<IBinder> input(defaultServiceManager()->getService(String16("inputflinger")));

    static_cast<void>(schedule([=] {
        if (input == nullptr) {
            ALOGE("Failed to link to input service");
        } else {
            mInputFlinger = interface_cast<os::IInputFlinger>(input);
        }

        readPersistentProperties();
        mPowerAdvisor.onBootFinished();
        mBootStage = BootStage::FINISHED;

        if (property_get_bool("sf.debug.show_refresh_rate_overlay", false)) {
            enableRefreshRateOverlay(true);
        }
    }));
}
void SurfaceFlinger::updateInputFlinger() {
    ATRACE_CALL();
    if (!mInputFlinger) {
        return;
    }

    if (mVisibleRegionsDirty || mInputInfoChanged) {
        mInputInfoChanged = false;
        updateInputWindowInfo();
    } else if (mInputWindowCommands.syncInputWindows) {
        // If the caller requested to sync input windows, but there are no
        // changes to input windows, notify immediately.
        setInputWindowsFinished();
    }

    for (const auto& focusRequest : mInputWindowCommands.focusRequests) {
        mInputFlinger->setFocusedWindow(focusRequest);
    }
    mInputWindowCommands.clear();
}
void SurfaceFlinger::updateInputWindowInfo() {
    std::vector<InputWindowInfo> inputInfos;

    mDrawingState.traverseInReverseZOrder([&](Layer* layer) {
        if (!layer->needsInputInfo()) return;
        sp<DisplayDevice> display;
        if (enablePerWindowInputRotation()) {
            for (const auto& pair : ON_MAIN_THREAD(mDisplays)) {
                const auto& displayDevice = pair.second;
                if (!displayDevice->getCompositionDisplay()
                             ->belongsInOutput(layer->getLayerStack(),
                                               layer->getPrimaryDisplayOnly())) {
                    continue;
                }
                display = displayDevice;
            }
        }
        // When calculating the screen bounds we ignore the transparent region since it may
        // result in an unwanted offset.
        inputInfos.push_back(layer->fillInputInfo(display));
    });

    mInputFlinger->setInputWindows(inputInfos,
                               mInputWindowCommands.syncInputWindows ? mSetInputWindowsListener
                                                                     : nullptr);
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

IMS中Binder案例 的相关文章

随机推荐

  • python爬虫报告范文及模板_python爬虫学习之路,为老婆爬下整站模板-第三章

    由于分析到只是7位置的变化 把以前读取列表的方法改了下 在方法里传值进来 页数我是直接写的999页 然后看到他们网站上如果是没有那一页会返回一个content box的div 里面显示还没有作品 我就查找这个div 如果有这个div存在就跳
  • NeRF 从入门到精通

    目录 NeRF简介 课程 教程 代码实践 商业应用 NeRF简介 NeRF 神经辐射场 是当前最为火热的研究领域之一 基于NeRF的三维视觉年度进展报告 效果非常惊艳 它要解决的问题就是给定一些拍摄的图 如何生成新的视角下的图 不同于传统的
  • Mac基于Gin、Docker-Compose、Mysql的入门搭建

    Mac基于Gin Docker Compose Mysql的入门搭建 在Mac装golang 在Goland建项目 安装Gin 粘贴3个go文件 配置docker 安装mysql 用DataGrip建表录入简单数据 配置Docker Com
  • 字符串类算法题:反转字符串中的单词(js版本)

    题目如下 LeetCode原题链接请点击这里 lesson1 chars js代码如下 解法一 12ms export default str gt 字符串分割成数组 return str split map item gt return
  • 关闭JDWP端口,或者JDWP端口不对公网开放

    查询出的端口是8000 我只需要把8000端口关闭就可以了 ubuntu 查看端口使用情况 使用netstat命令 查看所有服务端口 netstat ap 查看指定端口 可以结合命令grep命令 netstat ap grep 8000 若
  • 深度学习实战之线性回归

    1 线性回归 连续值的预测 目的使模型的预测值逼近于真实值 在训练模型中 函数参数w b往往是不可知的 所以需要对其进行求解 构造一个loss函数 使得误差函数取得最小值 得到的w b 即为模型要求的参数 求loss函数的最小值 通过梯度下
  • 异常中禁用e.printStackTrace()

    相信大家在开发代码的过程中都用过try catch语句 不知道有没有人写过这种语句 try catch Exception e e printStackTrace log error error e 或者 try catch Excepti
  • js时间对比的问题

    开发中 对于时间对比 大家都比较喜欢从页面获取时间之后 直接使用大于小于做判断 比如这样 javascript view plain copy if bgTime edTime bgTime gt edTime alert 开始时间不能晚于
  • 超好用的webssh(支持秘钥登录)

    webssh 项目地址 https github com billchurch WebSSH2 安装 webssh cd usr local git clone https github com billchurch WebSSH2 git
  • 调用其他文件的define_DEFINE_PROFILE用法介绍(1)

    01 概述 可以使用DEFINE PROFILE定义一个自定义边界配置文件或单元格区域条件 该条件随空间坐标或时间而变化 可以自定义的变量如下 速度 压力 温度 湍流动能 湍流耗散率 质量流量 目标质量流量作为流动时间的函数 物种质量分数
  • 新春特辑

    志在哪里 哪里就有成功 心在哪里 哪里就有风景 爱在哪里 哪里就有感动 在新年来临之际 互联互通社区衷心祝愿您 春节快乐 身体健康 心想事成 1 中国非结构化数据中台实践白皮书 2 2020中国服装行业数据中台研究报告 3 2020中国数据
  • Java嵌套if选择结构

    嵌套if选择结构本期用两个例题来讲解 例题1 学校举行运动会 百米赛跑成绩在12s内有资格进入决赛 否则淘汰 进入决赛再根据性别来区别进入男子组决赛和女子组决赛 public static void main String args Sca
  • 区块链学习3:区块链的共识机制

    前往老猿Python博文目录 共识机制主要用于解决分布式计算的根本问题数据的一致性 所谓共识 简单理解就是指参与方都达成一致 在区块链系统中 如何让每个节点通过一个规则将各自的数据保持一致是一个很核心的问题 这个问题的解决方案就是制定一套共
  • Python 写函数,传入一个参数n,返回n的阶乘

    def factorial n param n 参数 return 返回结果 if n lt 0 exit sum 1 for i in range 1 n 1 sum i print sum return factorial 8
  • 分享8个超神的Pycharm插件们,可以说是无敌的存在!

    分享几个YYDS的Pycharm插件 1statics staitcs可以作为KPI摸鱼好助手 120w次下载的这个插件 可以直接统计代码的具体情况 对工程里的每个代码文件进行统计代码量 空行量 注释量 代码行占比等进行清晰统计 下次就算功
  • centos7 nodejs 启动vue项目

    1 准备项目文件及目录 2 检查nodejs 环境 3 安装vue cli脚手架构建工具 命令 npm install g vue cli 4 切换项目目录 运行初始化命令 切换命令 cd projects DDSWeb 初始化命令 vue
  • STM32F1端口复用与重映射(学习心得)

    端口的复用 以USART1为例 PA9管脚的复用功能为 USART1 TX 串口发送端 PA10管脚的复用功能为USART1 RX 串口接收端 对端口复用的配置 GPIO端口的时钟使能 RCC APB2PeriphClockCmd RCC
  • C语言编程必将成为通用技能

    正文 为什么我们要学习编程 编程是当今时代不可或缺的核心技能 它不仅仅是程序员的专属领域 而是逐渐成为一种通用技能 被越来越多的人所需 想象一下 不久的将来 编程将变成人人都会的事情 而职业编程人员会逐渐减少 就像识字一样 编程将成为人们必
  • 用Java实现分页

    查询完全表之后 接下来要做的是查询总条数 和当前是第几页 总共有几页 包括数据 通过Java思想将封装为类 然后调用 pageBean java类可以当做通用的分页的类 Service作用是封装一类服务 比如说注册或者说登录 它是一类服务
  • IMS中Binder案例

    IMS中Binder案例 1 FWK层中AIDL形式 1 1 服务端实现Stub 1 2 客户端获取proxy 2 Native层中AIDL形式 2 1 服务端对应Bn端 2 2 客户端对应Bp端 android12 release 1 F