跨进程高级玩法方案2-学员分享

背景:

针对想要在native进程中如何访问systemserver中的display这个java服务

上一篇文章已经分享了相关的方案 binder跨进程高阶玩法-纯native客户端如何访问java服务端接口

这个方案优劣势如下: 优点:实现原理简单,可以只需要进行代码编写,组装好parcel然后调用transact方法既可以实现跨进程调用,完全不需要依赖其他aidl等模块

缺点:需要针对每个跨进程的接口进行详细的细分,特别是组装和拆装parcel对象,这个每个接口都不一样,而且也比较容易出错

那么基于上面的一个缺点导致的痛点问题,就有学员朋友提出了另一种使用aidl文件的方案来解决这个问题。

方案2实战实现

这里直接上相关的代码,大家可以就可以很容易看出他的方案核心

bash 复制代码
get_display_ids$ tree
.
├── aidl
│   └── android
│       └── hardware
│           └── display
│               ├── DisplayInfo.aidl
│               └── IDisplayManager.aidl
├── Android.bp
└── src
    ├── DisplayBase.cpp
    ├── DisplayBase.h
    └── main1.cpp

5 directories, 6 files

明显可以看到这里多了两个aidl文件,最熟悉的其实就是 IDisplayManager.aidl,这里是不是看到这个aidl文件,大家大概就可以看出这里实际上就是在native层面使用aidl文件编译生成的c++相关接口,不过这种方式我们前面也聊过因为IDisplayManager.aidl可能依赖较多,aidl单独编译需要引入的aidl也可能会很多,这种引入就会比较麻烦。具体可以看看aidl文件详细情况。

IDisplayManager.aidl

cpp 复制代码
package android.hardware.display;

import android.hardware.display.DisplayInfo;

/** @hide */
interface IDisplayManager {
    @UnsupportedAppUsage
    DisplayInfo getDisplayInfo(int displayId);
    int[] getDisplayIds(boolean includeDisabled);
}

DisplayInfo.aidl --这里可以看出的它主要是依赖"DisplayBase.h"这个头文件来声明相关的结构

cpp 复制代码
package android.hardware.display;

parcelable DisplayInfo cpp_header "DisplayBase.h";

大家明显可以看到这里的IDisplayManager.aidl文件被缩减成了只有两个方法,其实这个IDisplayManager.aidl文件属于原生系统的阉割版本,但是因为我们的需求就是获取的getDisplayIds,DisplayInfo.aidl是因为第一个接口getDisplayInfo需要的一个依赖,所以这个阉割的aidl也是完全可以满足的。

详细源码: Android.bp

cpp 复制代码
filegroup {
    name: "libdms_client_aidl",
    srcs: [
        "aidl/**/*.aidl"
    ],
    path: "aidl"
}

cc_library {
    name: "libdms_client",
    srcs: [ 
        "src/DisplayBase.cpp",
        ":libdms_client_aidl"
    ],
    aidl: {
        export_aidl_headers: true,
        local_include_dirs: ["aidl"],
    },
    export_include_dirs: [
        "src",
    ],
    shared_libs: [
        "libbinder",
        "liblog",
        "libutils",
    ],
}

cc_binary {
    name: "get_display_ids",
    srcs: [ "src/main1.cpp"],
    shared_libs: [
        "libbinder",
        "liblog",
        "libutils",
        "libdms_client",
    ],
}

这里注意一下编译会有两个目标,一个是libdms_client.so和get_display_ids这个可执行文件。

main1.cpp这个是主要的调用

cpp 复制代码
#include <android/hardware/display/IDisplayManager.h>
#include <binder/IServiceManager.h>
#include <binder/Status.h>
#include <utils/String16.h>
#include <utils/Errors.h>
#include <binder/IInterface.h>
#include <stdio.h>
#include <vector>

using namespace android;

int main() {
    printf("get_display_ids\n");
    auto sm = defaultServiceManager();
    if (sm && sm->checkService(String16("display"))) {
        printf("display service is found\n");
        auto binder = sm->getService(String16("display"));
        auto display = interface_cast<android::hardware::display::IDisplayManager>(binder);
        std::vector<int32_t> ids;
        auto res = display->getDisplayIds(true, &ids);
        if (res.isOk()) {
            printf("ids.size=%d\n", (int)ids.size());
            for (int i =0;i <  (int)ids.size();i++) {
                printf("id[%d]=%d\n",i, ids[i]);
            }
        }
        for(int i = 0;i < ids.size();i++) {
              android::hardware::display::DisplayInfo displayInfo;
		res = display->getDisplayInfo(ids[i], &displayInfo);
		if (res.isOk()) {
		    printf("layerStack=%d\n", displayInfo.layerStack);
		    printf("flags=%d\n", displayInfo.flags);
		    printf("type=%d\n", displayInfo.type);
		    printf("displayId=%d\n", displayInfo.displayId);
		    printf("dispalyGroupId=%d\n", displayInfo.displayGroupId);
		    printf("physicalDisplayId=%d\n", (int)(displayInfo.physicalDisplayId & 0xFF));
		}
		printf("################################################################### \n");
        }
  
    }
    return 0;
}

DisplayBase.h

cpp 复制代码
#include <binder/Parcelable.h>
#include <binder/Parcel.h>
#include <utils/String16.h>


namespace android {
namespace hardware {
namespace display {

struct DisplayInfo : public android::Parcelable {
    int layerStack;
    int flags;
    int type;
    int displayId;
    int displayGroupId;
    //DisplayAddress address;
    int64_t physicalDisplayId;
    //DeviceProductInfo deviceProductInfo;
    String16 deviceProductInfoName;
    String16 manufacturerPnpId;
    String16 productId;
    int32_t modelYear;
    int32_t week;
    int32_t year;
    String16 name;
    int width;
    int height;

    status_t writeToParcel(Parcel * parcel) const;
    status_t readFromParcel(const Parcel * source);
};

}
}
}

DisplayBase.cpp --主要是针对DisplayInfo对象进行parcel包相关的拆装工作

cpp 复制代码
#include "DisplayBase.h"

namespace android {
namespace hardware {
namespace display {
status_t DisplayInfo::writeToParcel(Parcel * parcel) const {
    parcel->writeInt32(layerStack);
    return OK;
}

status_t DisplayInfo::readFromParcel(const Parcel * source) {
    //status_t res = OK;
    layerStack = source->readInt32();
    flags = source->readInt32();
    type = source->readInt32();
    displayId = source->readInt32();
    displayGroupId = source->readInt32();
    physicalDisplayId = source->readInt64();
    deviceProductInfoName = source->readString16();
    manufacturerPnpId = source->readString16();
    productId = source->readString16();
    modelYear = source->readInt32();
    week = source->readInt32();
    year = source->readInt32();
    name = source->readString16();
    width = source->readInt32();
    height = source->readInt32();
    return OK;
}

}// display
}// hardware
}// android

实战结果:

cpp 复制代码
NX563J:/ # get_display_ids                                                                                                                                                                                        
get_display_ids
display service is found
ids.size=2
id[0]=0
id[1]=2 
layerStack=0
flags=16515
type=1
displayId=0
dispalyGroupId=0
physicalDisplayId=36
################################################################### 
layerStack=2
flags=136
type=4
displayId=2
dispalyGroupId=0
physicalDisplayId=255
################################################################### 

可以看到这里的displayId也是正常获取了,一共2个display分别id如下: id[0]=0 id[1]=2

但是大家是否有发现,使用getDisplayInfo接口其实获取的数据是有问题的,明显就是physicalDisplayId=36是不对的,这里就就相当于留给大家的作业了,大家看看是啥问题,把他修改好后,找马哥确认一下修改方案是ok。

相关推荐
用户81274828151202 小时前
漏学Input知识系列之“偷”走了其他窗口的事件pilferPointers
前端
用户81274828151202 小时前
安卓14自由窗口圆角处理之绘制圆角轮廓线
前端
用户81274828151202 小时前
安卓java端service如何在native进程进行访问-跨进程通讯高端知识
前端
Shirley~~2 小时前
Web Audio API
前端
TEC_INO2 小时前
STM32_11:DMA
java·前端·stm32
鹏北海2 小时前
qiankun微前端通信与路由方案总结
前端·微服务·架构
韩曙亮2 小时前
【Web APIs】浏览器本地存储 ② ( window.sessionStorage 本地存储常用 API 简介 | 代码示例 )
开发语言·前端·javascript·localstorage·sessionstorage·web apis·浏览器本地存储
time_rg2 小时前
深入理解react——2. Concurrent Mode
前端·react.js
0_12 小时前
封装了一个vue版本 Pag组件
前端·javascript·vue.js