手机驱动开发_全网首发!GPU 驱动自升级原理详解

背景

GPU 驱动自升级,是在以下两个痛点下催生出来的:

1.换机频率降低,手机的生命周期越来越长    智能手机已经不再是一个增量市场,变成一个存量市场。消费者换机频率逐年降低,手机生命周期变长。生命周期变长了以后,那么如何更好地维护老机型就变成一个难题2.开发者需要升级 ROM 才能用到 GPU driver 的新功能    一直以来,游戏开发者想要升级到最新的 GPU 驱动的渠道跟普通的用户一样,只能靠 OEM 厂商的推送系统更新,他们没有一个渠道能够直接拿到最新的 GPU 驱动,因此无法第一时间对驱动的新特性进行适配。如何建立一个渠道能够让游戏开发者能够及时获取到最新的 GPU 驱动也是一个难题

有痛点就会有需求,GPU 驱动自升级就是针对这两个痛点提出的解决方案。

不过,这个方案要落地还会遇到很多实际问题:首先,GPU 驱动跟整个操作系统依赖极大,影响的模块很多,如 Display,Camera,Media 等,稍有不慎整个系统就会不稳定甚至 crash。

同时,这个功能要真正落地,还涉及到多方:GPU 驱动来自 SoC 厂商;Android 的 OEM 厂商等。每一方里涉及到厂商的又十分众多。因此在确定方案的时候需要保证能够有足够的兼容性。

以上这么多难题注定了这个方案从提出到落地,需要花很长的时间,走很长的路。

而事实也是如此,从 2017 年开始,Android O 提出了 Project Treble,引入了 VNDK 和 linker namespace,那时候其实已经在对这个方案进行技术铺垫了;再到 2018 年的 Android P,谷歌在 framework 加了很多 dummy code,此时整个方案的框架已经基本完成;再到 2019 年的 Android Q,这个方案作为 Q 的核心功能跟大家见面了。而小米十周年旗舰——小米 10/小米 10 Pro 也成为国内第一款落地 GPU 驱动自升级功能的 Android 智能手机。

在 GPU 驱动自升级方案中,可升级的 GPU 驱动分为两种,一种称为 Game Driver,面向的普通用户,主要是针对游戏这种十分依赖 GPU 的场景进行特殊优化,稳定的 driver;另一种称为 Prerelease Driver,面向游戏开发者,目的是让游戏开发者能够提前获取到包含新特性的,不稳定的驱动,进行提前的适配和利用。这两种驱动分别封装在两个 apk,分别通过两个 property 来分区:ro.gfx.driver.0 指定的是 Game Driver 的包名,ro.gfx.driver.1 指定的是 Prerelease Driver 的包名。

需要说明的是,虽然称为 apk,但是实际上更多地可以理解为是两个盛放 driver 的容器,apk 本身不具备任何的代码,而之所以要将其打包为 apk,更多的是为了利用 Android 的签名机制以及利用 PMS 能够对所有安装的 apk 进行统一的管理。

将 apk 解包以后可以放在整个包的结构如下:

├── AndroidManifest.xml├── assets│   ├── sphal_libraries.txt│   └── whitelist.txt├── lib│   ├── arm64-v8a│   └── armeabi-v7a└── res

分别说明一下各个结构的作用:

•sphal_libraries.txt    能够被 gfx driver 访问的, sphal 中的库列表,后面会详细讲解•whitelist.txt    使用 Game Driver 的包名白名单•lib    driver 本体,分为 32 位和 64 位,根据应用的 abi 选择加载对应的 driver

Game Driver 和 Prerelease Driver (后面统称为 updated driver)这两个 apk 的结构是一样的,只不过 lib 文件夹里面的驱动不一样而已。

updated driver 配置流程

这部分讲讲在 app 启动的时候,是怎么给 app 挑选对应的 GPU driver 的。

app 在启动的过程中,经过下面的流转(详细的流程省略,非本文主题):

ActivityThread::handleBindApplication()   \__ActivityThread::setupGraphicsSupport()        \__GraphicsEnvironment.setup()

最终走到核心代码:

public void setup(Context context, Bundle coreSettings) {
       final PackageManager pm = context.getPackageManager();    final String packageName = context.getPackageName();    ....    if (!chooseDriver(context, coreSettings, pm, packageName)) {
            setGpuStats(SYSTEM_DRIVER_NAME, SYSTEM_DRIVER_VERSION_NAME, SYSTEM_DRIVER_VERSION_CODE,                SystemProperties.getLong(PROPERTY_GFX_DRIVER_BUILD_TIME, 0), packageName,                getVulkanVersion(pm));    }}

核心函数 chooseDriver()

private static boolean chooseDriver(        Context context, Bundle coreSettings, PackageManager pm, String packageName) {
        // PART 1    final String driverPackageName = chooseDriverInternal(context, coreSettings);    if (driverPackageName == null) {
            return false;    }    ......}

chooseDriverInternal()

chooseDriverInternal(),这个函数的主要作用是,根据系统的配置,为当前启动的 app 判断是否需要加载 Game/Prerelease Driver,如果需要那么返回对应的 driver apk 的包名;如果不需要,那么返回 null,表明当前启动的 app 只需要加载 system gpu driver。判断的逻辑:

private static String chooseDriverInternal(Context context, Bundle coreSettings) {
        // 判断 game driver 的 property 是否配置了    final String gameDriver = SystemProperties.get(PROPERTY_GFX_DRIVER);    final boolean hasGameDriver = gameDriver != null && !gameDriver.isEmpty();    // 判断 prerelease driver 的 property 是否配置了    final String prereleaseDriver = SystemProperties.get(PROPERTY_GFX_DRIVER_PRERELEASE);    final boolean hasPrereleaseDriver = prereleaseDriver != null && !prereleaseDriver.isEmpty();    // 两个 property 都没有配置,前面提到这两个 property 代表的是两个包名    // 如果都没有配置,那么说明这项功能没有使能,使用 system gpu driver    if (!hasGameDriver && !hasPrereleaseDriver) {
            if (DEBUG) Log.v(TAG, "Neither Game Driver nor prerelease driver is supported.");        return null;    }    // To minimize risk of driver updates crippling the device beyond user repair, never use an    // updated driver for privileged or non-updated system apps. Presumably pre-installed apps    // were tested thoroughly with the pre-installed driver.    // 不是所有的 app 都可以使用这个功能的,如果当前是预装应用,那么也不会对其使用该功能    final ApplicationInfo ai = context.getApplicationInfo();    if (ai.isPrivilegedApp() || (ai.isSystemApp() && !ai.isUpdatedSystemApp())) {
            if (DEBUG) Log.v(TAG, "Ignoring driver package for privileged/non-updated system app.");        return null;    }    // 接下来看下面的流程图:
34d9621446630820119f851ed17a29e2.png
chooseDriverInternal

在判断完当前的 app 需要使用的 driver 类型以后,返回到 chooseDriver()

chooseDriver()

private static boolean chooseDriver(        Context context, Bundle coreSettings, PackageManager pm, String packageName) {
        final String driverPackageName = chooseDriverInternal(context, coreSettings);    if (driverPackageName == null) {
            return false;    }    // PART 2    final PackageInfo driverPackageInfo;    // 容纳 game driver 的 apk 必须是一个 system app,否则会直接跳过    try {
            driverPackageInfo = pm.getPackageInfo(driverPackageName,                PackageManager.MATCH_SYSTEM_ONLY | PackageManager.GET_META_DATA);    } catch (PackageManager.NameNotFoundException e) {
            Log.w(TAG, "driver package '" + driverPackageName + "' not installed");        return false;    }    // Android O 及以后,谷歌提出了 Project Triple,其中包括 VNDK,规定了 GPU driver 必须是在 sphal 的 linker space    // 因此 driver apk 的 targetSdkVersion 必须大于等于 O    // O drivers are restricted to the sphal linker namespace, so don't try to use    // packages unless they declare they're compatible with that restriction.    final ApplicationInfo driverAppInfo = driverPackageInfo.applicationInf
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值