10ea406920af8313875866f13c9104129c08b2d76Jeff Tinker/*
20ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * Copyright (C) 2017 The Android Open Source Project
30ea406920af8313875866f13c9104129c08b2d76Jeff Tinker *
40ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * Licensed under the Apache License, Version 2.0 (the "License");
50ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * you may not use this file except in compliance with the License.
60ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * You may obtain a copy of the License at
70ea406920af8313875866f13c9104129c08b2d76Jeff Tinker *
80ea406920af8313875866f13c9104129c08b2d76Jeff Tinker *      http://www.apache.org/licenses/LICENSE-2.0
90ea406920af8313875866f13c9104129c08b2d76Jeff Tinker *
100ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * Unless required by applicable law or agreed to in writing, software
110ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * distributed under the License is distributed on an "AS IS" BASIS,
120ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * See the License for the specific language governing permissions and
140ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * limitations under the License.
150ea406920af8313875866f13c9104129c08b2d76Jeff Tinker */
160ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
170ea406920af8313875866f13c9104129c08b2d76Jeff Tinker#ifndef DRM_HAL_VENDOR_MODULE_API_H
180ea406920af8313875866f13c9104129c08b2d76Jeff Tinker#define DRM_HAL_VENDOR_MODULE_API_H
190ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
200ea406920af8313875866f13c9104129c08b2d76Jeff Tinker#include <stdint.h>
210ea406920af8313875866f13c9104129c08b2d76Jeff Tinker#include <map>
220ea406920af8313875866f13c9104129c08b2d76Jeff Tinker#include <string>
230ea406920af8313875866f13c9104129c08b2d76Jeff Tinker#include <vector>
240ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
250ea406920af8313875866f13c9104129c08b2d76Jeff Tinker/**
260ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * The DRM and Crypto HALs interact with vendor-provided HAL implementations
270ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * that have DRM-specific capabilities. Since the VTS tests cannot contain
280ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * DRM-specific functionality, supporting modules are required to enable VTS
290ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * to validate HAL implementations in a generic way.  If the vendor-specific
300ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * VTS module is not provided for a given drm HAL implementation, only very
310ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * small subset of functionality can be verified.
320ea406920af8313875866f13c9104129c08b2d76Jeff Tinker *
330ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * As an example, a DRM HAL implementation interacts with a DRM-specific
340ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * license server to obtain licenses for decrypting content.  The DRM HAL
350ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * implementation generates a key request message, delivers it to the server
360ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * and receives a key response message which is then loaded into the HAL. Once
370ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * the keys are loaded, the Crypto HAL decryption functionality and performance
380ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * and other associated APIs can be tested by the common VTS test suite.
390ea406920af8313875866f13c9104129c08b2d76Jeff Tinker *
400ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * Vendor-specific VTS modules are shared libraries used by the DRM VTS test.
410ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * They provide a set of functions to support VTS testing of the DRM HAL module.
420ea406920af8313875866f13c9104129c08b2d76Jeff Tinker *
430ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * The modules are placed in a common location on the file system. The VTS test
440ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * scans through all vendor-provided support libraries and runs the VTS test
450ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * suite on each library that is found.
460ea406920af8313875866f13c9104129c08b2d76Jeff Tinker *
470ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * The vendor-specific module exposes an extern “C” vendorModuleFactory()
480ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * function that returns a DrmHalVTSVendorModule instance. DrmHalVTSVendorModule
490ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * instances are versioned, where each version is represented by subclass of
500ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * DrmHalVTSVendorModule that corresponds to the API version. For example, a
510ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * vendor-specific module that implements version 1 of the API would return a
520ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * DrmHalVTSVendorModule_V1 from the vendorModuleFactory() function.
530ea406920af8313875866f13c9104129c08b2d76Jeff Tinker */
540ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
550ea406920af8313875866f13c9104129c08b2d76Jeff Tinkerclass DrmHalVTSVendorModule;
560ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
570ea406920af8313875866f13c9104129c08b2d76Jeff Tinkerextern "C" {
580ea406920af8313875866f13c9104129c08b2d76Jeff Tinker/**
590ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * The factory method for creating DrmHalVTSVendorModule instances. The returned
600ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * instance will be a subclass of DrmHalVTSVendorModule that corresponds to the
610ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * supported API version.
620ea406920af8313875866f13c9104129c08b2d76Jeff Tinker */
630ea406920af8313875866f13c9104129c08b2d76Jeff TinkerDrmHalVTSVendorModule* vendorModuleFactory();
640ea406920af8313875866f13c9104129c08b2d76Jeff Tinker};
650ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
660ea406920af8313875866f13c9104129c08b2d76Jeff Tinkerclass DrmHalVTSVendorModule {
670ea406920af8313875866f13c9104129c08b2d76Jeff Tinker   public:
68be310b2b77fbde99af326263a9ee6995225c4284Jeff Tinker    DrmHalVTSVendorModule() : installed(true) {}
690ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    virtual ~DrmHalVTSVendorModule() {}
700ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
710ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    /**
720ea406920af8313875866f13c9104129c08b2d76Jeff Tinker     * Return the vendor-specific module API version. The version is an integer
730ea406920af8313875866f13c9104129c08b2d76Jeff Tinker     * value with initial version 1. The API version indicates which subclass
740ea406920af8313875866f13c9104129c08b2d76Jeff Tinker     * version DrmHalVTSVendorModule this instance is.
750ea406920af8313875866f13c9104129c08b2d76Jeff Tinker     */
76f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    virtual uint32_t getAPIVersion() const = 0;
770ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
780ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    /**
790ea406920af8313875866f13c9104129c08b2d76Jeff Tinker     * Return the UUID for the DRM HAL implementation. Protection System
800ea406920af8313875866f13c9104129c08b2d76Jeff Tinker     * Specific
810ea406920af8313875866f13c9104129c08b2d76Jeff Tinker     * UUID (see http://dashif.org/identifiers/protection/)
820ea406920af8313875866f13c9104129c08b2d76Jeff Tinker     */
83f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    virtual std::vector<uint8_t> getUUID() const = 0;
840ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
850ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    /**
860ea406920af8313875866f13c9104129c08b2d76Jeff Tinker     * Return the service name for the DRM HAL implementation. If the hal is a
870ea406920af8313875866f13c9104129c08b2d76Jeff Tinker     * legacy
880ea406920af8313875866f13c9104129c08b2d76Jeff Tinker     * drm plugin, i.e. not running as a HIDL service, return the empty string.
890ea406920af8313875866f13c9104129c08b2d76Jeff Tinker     */
90f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    virtual std::string getServiceName() const = 0;
910ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
92be310b2b77fbde99af326263a9ee6995225c4284Jeff Tinker    /**
93be310b2b77fbde99af326263a9ee6995225c4284Jeff Tinker     * Set a flag in the vendor module to indicate whether or not the drm
94be310b2b77fbde99af326263a9ee6995225c4284Jeff Tinker     * scheme corresponding to this module is installed on the device.
95be310b2b77fbde99af326263a9ee6995225c4284Jeff Tinker     */
96be310b2b77fbde99af326263a9ee6995225c4284Jeff Tinker    void setInstalled(bool flag) {installed = flag;}
97be310b2b77fbde99af326263a9ee6995225c4284Jeff Tinker    bool isInstalled() const {return installed;}
98be310b2b77fbde99af326263a9ee6995225c4284Jeff Tinker
990ea406920af8313875866f13c9104129c08b2d76Jeff Tinker   private:
100be310b2b77fbde99af326263a9ee6995225c4284Jeff Tinker    bool installed;
1010ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    DrmHalVTSVendorModule(const DrmHalVTSVendorModule&) = delete;
1020ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    void operator=(const DrmHalVTSVendorModule&) = delete;
1030ea406920af8313875866f13c9104129c08b2d76Jeff Tinker};
1040ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
1050ea406920af8313875866f13c9104129c08b2d76Jeff Tinker/**
1060ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * API Version 1.  This is the baseline version that supports a minimal set
1070ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * of VTS tests.
1080ea406920af8313875866f13c9104129c08b2d76Jeff Tinker */
1090ea406920af8313875866f13c9104129c08b2d76Jeff Tinkerclass DrmHalVTSVendorModule_V1 : public DrmHalVTSVendorModule {
1100ea406920af8313875866f13c9104129c08b2d76Jeff Tinker   public:
1110ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    DrmHalVTSVendorModule_V1() {}
1120ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    virtual ~DrmHalVTSVendorModule_V1() {}
1130ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
114f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    virtual uint32_t getAPIVersion() const { return 1; }
1150ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
1160ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    /**
1170ea406920af8313875866f13c9104129c08b2d76Jeff Tinker     * Handle a provisioning request. This function will be called if the HAL
1180ea406920af8313875866f13c9104129c08b2d76Jeff Tinker     * module's getProvisionRequest returns a provision request.  The vendor
1190ea406920af8313875866f13c9104129c08b2d76Jeff Tinker     * module should process the provisioning request, either by sending it
1200ea406920af8313875866f13c9104129c08b2d76Jeff Tinker     * to a provisioning server, or generating a mock response.  The resulting
1210ea406920af8313875866f13c9104129c08b2d76Jeff Tinker     * provisioning response is returned to the VTS test.
1220ea406920af8313875866f13c9104129c08b2d76Jeff Tinker     *
1230ea406920af8313875866f13c9104129c08b2d76Jeff Tinker     * @param provisioningRequest the provisioning request recieved from
1240ea406920af8313875866f13c9104129c08b2d76Jeff Tinker     * the DRM HAL
1250ea406920af8313875866f13c9104129c08b2d76Jeff Tinker     * @param url the default url the HAL implementation provided with the
1260ea406920af8313875866f13c9104129c08b2d76Jeff Tinker     * provisioning request
1270ea406920af8313875866f13c9104129c08b2d76Jeff Tinker     * @return the generated provisioning response
1280ea406920af8313875866f13c9104129c08b2d76Jeff Tinker     */
1290ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    virtual std::vector<uint8_t> handleProvisioningRequest(
1300ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            const std::vector<uint8_t>& provisioningRequest,
1310ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            const std::string& url) = 0;
1320ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
1330ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    /**
1340ea406920af8313875866f13c9104129c08b2d76Jeff Tinker     * Content configuration specifies content-specific parameters associated
1350ea406920af8313875866f13c9104129c08b2d76Jeff Tinker     * with a key request/response transaction. It allows the VTS test to
1360ea406920af8313875866f13c9104129c08b2d76Jeff Tinker     * request keys and use them to perform decryption.
1370ea406920af8313875866f13c9104129c08b2d76Jeff Tinker     */
1380ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    struct ContentConfiguration {
1390ea406920af8313875866f13c9104129c08b2d76Jeff Tinker        /**
1400ea406920af8313875866f13c9104129c08b2d76Jeff Tinker         * Assign a name for this configuration that will be referred to
1410ea406920af8313875866f13c9104129c08b2d76Jeff Tinker         * in log messages.
1420ea406920af8313875866f13c9104129c08b2d76Jeff Tinker         */
1430ea406920af8313875866f13c9104129c08b2d76Jeff Tinker        const std::string name;
1440ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
1450ea406920af8313875866f13c9104129c08b2d76Jeff Tinker        /**
1460ea406920af8313875866f13c9104129c08b2d76Jeff Tinker         * Server to use when requesting a key response.  This url will be
1470ea406920af8313875866f13c9104129c08b2d76Jeff Tinker         * passed as a parameter to the vendor vts module along with the
1480ea406920af8313875866f13c9104129c08b2d76Jeff Tinker         * key request to perform the key request transaction.
1490ea406920af8313875866f13c9104129c08b2d76Jeff Tinker         */
1500ea406920af8313875866f13c9104129c08b2d76Jeff Tinker        const std::string serverUrl;
1510ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
1520ea406920af8313875866f13c9104129c08b2d76Jeff Tinker        /**
1530ea406920af8313875866f13c9104129c08b2d76Jeff Tinker         * Initialization data provided to getKeyRequest, e.g. PSSH for CENC
1540ea406920af8313875866f13c9104129c08b2d76Jeff Tinker         * content
1550ea406920af8313875866f13c9104129c08b2d76Jeff Tinker         */
1560ea406920af8313875866f13c9104129c08b2d76Jeff Tinker        const std::vector<uint8_t> initData;
1570ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
1580ea406920af8313875866f13c9104129c08b2d76Jeff Tinker        /**
1590ea406920af8313875866f13c9104129c08b2d76Jeff Tinker         *  Mime type provided to getKeyRequest, e.g. "video/mp4", or "cenc"
1600ea406920af8313875866f13c9104129c08b2d76Jeff Tinker         */
1610ea406920af8313875866f13c9104129c08b2d76Jeff Tinker        const std::string mimeType;
1620ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
1630ea406920af8313875866f13c9104129c08b2d76Jeff Tinker        /**
1640ea406920af8313875866f13c9104129c08b2d76Jeff Tinker         * Optional parameters to be associated with the key request
1650ea406920af8313875866f13c9104129c08b2d76Jeff Tinker         */
1660ea406920af8313875866f13c9104129c08b2d76Jeff Tinker        const std::map<std::string, std::string> optionalParameters;
1670ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
1680ea406920af8313875866f13c9104129c08b2d76Jeff Tinker        /**
1696799c3a5c597813154e20837c58703eba7996dfeRyan Campbell         *  Define license policy attributes for the content configuration.
1706799c3a5c597813154e20837c58703eba7996dfeRyan Campbell         *  These attributes can affect which tests are able to be applied.
1716799c3a5c597813154e20837c58703eba7996dfeRyan Campbell         */
1726799c3a5c597813154e20837c58703eba7996dfeRyan Campbell        struct Policy {
1736799c3a5c597813154e20837c58703eba7996dfeRyan Campbell            /**
1746799c3a5c597813154e20837c58703eba7996dfeRyan Campbell             * Indicate if the license policy allows offline playback.
1756799c3a5c597813154e20837c58703eba7996dfeRyan Campbell             * Content configurated with this policy supports KeyType::OFFLINE
1766799c3a5c597813154e20837c58703eba7996dfeRyan Campbell             * key requests/responses. A vendor module should provide at least
1776799c3a5c597813154e20837c58703eba7996dfeRyan Campbell             * one content configuration where allowOffline is true if the drm
1786799c3a5c597813154e20837c58703eba7996dfeRyan Campbell             * scheme supports offline content.
1796799c3a5c597813154e20837c58703eba7996dfeRyan Campbell             */
1806799c3a5c597813154e20837c58703eba7996dfeRyan Campbell            bool allowOffline;
1816799c3a5c597813154e20837c58703eba7996dfeRyan Campbell        } policy;
1826799c3a5c597813154e20837c58703eba7996dfeRyan Campbell
1836799c3a5c597813154e20837c58703eba7996dfeRyan Campbell        /**
1840ea406920af8313875866f13c9104129c08b2d76Jeff Tinker         * The keys that will be available once the keys are loaded
1850ea406920af8313875866f13c9104129c08b2d76Jeff Tinker         */
1860ea406920af8313875866f13c9104129c08b2d76Jeff Tinker        struct Key {
1870ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            /**
1880ea406920af8313875866f13c9104129c08b2d76Jeff Tinker             * Indicate if the key content is configured to require secure
1896799c3a5c597813154e20837c58703eba7996dfeRyan Campbell             * buffers, where the output buffers are protected and cannot be
1906799c3a5c597813154e20837c58703eba7996dfeRyan Campbell             * accessed by the non-secure cpu. A vendor module should provide
1916799c3a5c597813154e20837c58703eba7996dfeRyan Campbell             * at least one content configurations where isSecure is false, to
1926799c3a5c597813154e20837c58703eba7996dfeRyan Campbell             * allow decrypt result verification tests to be run.
1930ea406920af8313875866f13c9104129c08b2d76Jeff Tinker             */
1940ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            bool isSecure;
1950ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
1960ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            /**
1970ea406920af8313875866f13c9104129c08b2d76Jeff Tinker             * A key ID identifies a key to use for decryption
1980ea406920af8313875866f13c9104129c08b2d76Jeff Tinker             */
1990ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            const std::vector<uint8_t> keyId;
2000ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
2010ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            /**
202f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker             * The clear content key is provided to generate expected values for
203f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker             * validating decryption.
2040ea406920af8313875866f13c9104129c08b2d76Jeff Tinker             */
205f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker            const std::vector<uint8_t> clearContentKey;
2060ea406920af8313875866f13c9104129c08b2d76Jeff Tinker        };
2070ea406920af8313875866f13c9104129c08b2d76Jeff Tinker        std::vector<Key> keys;
2080ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    };
2090ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
2100ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    /**
2110ea406920af8313875866f13c9104129c08b2d76Jeff Tinker     * Return a list of content configurations that can be exercised by the
2120ea406920af8313875866f13c9104129c08b2d76Jeff Tinker     * VTS test.
2130ea406920af8313875866f13c9104129c08b2d76Jeff Tinker     */
214f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    virtual std::vector<ContentConfiguration>
215f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker            getContentConfigurations() const = 0;
2160ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
2170ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    /**
2180ea406920af8313875866f13c9104129c08b2d76Jeff Tinker     * Handle a key request. This function will be called if the HAL
2190ea406920af8313875866f13c9104129c08b2d76Jeff Tinker     * module's getKeyRequest returns a key request.  The vendor
2200ea406920af8313875866f13c9104129c08b2d76Jeff Tinker     * module should process the key request, either by sending it
2210ea406920af8313875866f13c9104129c08b2d76Jeff Tinker     * to a license server, or by generating a mock response.  The resulting
2220ea406920af8313875866f13c9104129c08b2d76Jeff Tinker     * key response is returned to the VTS test.
2230ea406920af8313875866f13c9104129c08b2d76Jeff Tinker     *
2240ea406920af8313875866f13c9104129c08b2d76Jeff Tinker     * @param keyRequest the key request recieved from the DRM HAL
2250ea406920af8313875866f13c9104129c08b2d76Jeff Tinker     * @param serverUrl the url of the key server that was supplied
2260ea406920af8313875866f13c9104129c08b2d76Jeff Tinker     * by the ContentConfiguration
2270ea406920af8313875866f13c9104129c08b2d76Jeff Tinker     * @return the generated key response
2280ea406920af8313875866f13c9104129c08b2d76Jeff Tinker     */
2290ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    virtual std::vector<uint8_t> handleKeyRequest(
2300ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            const std::vector<uint8_t>& keyRequest,
2310ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            const std::string& serverUrl) = 0;
2320ea406920af8313875866f13c9104129c08b2d76Jeff Tinker};
2330ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
2340ea406920af8313875866f13c9104129c08b2d76Jeff Tinker#endif  // DRM_HAL_VENDOR_MODULE_API_H
235