Android_Architecture_HAL--Framework Testing

说明:转载自Android官网https://source.android.com/devices/architecture/hal/framework-testing,方便国内查看。


HIDL Framework Backwards Compatibility Verification

HIDL HALs guarantee the Android core system (aka system.img or the framework) is backwards compatible. While Vendor Test Suite (VTS) tests ensure that HALs work as expected (e.g. 1.1 HAL tests are run on all 1.2 implementations), framework testing is needed to ensure that when a supported HAL (1.0, 1.1, or 1.2) is provided, the framework works properly with that HAL.

For details on HAL interface definition language (HIDL), refer to HIDL, HIDL versioning, and HIDL HAL Deprecation.

About HAL upgrades


There are two types of HAL upgrades: major and minor. Most systems include only one HAL implementation, but multiple implementations are supported. For example:

[email protected] # initial interface
[email protected] # minor version upgrade
[email protected] # another minor version upgrade
...
[email protected] # major version upgrade
...

The system partition typically includes a framework daemon (such as teleportd) that manages communication with a specific group of HAL implementations. Alternatively, systems might instead include a system library (such as android.hardware.configstore-utils) that implements convenient client behavior. In the example above, teleportd must work no matter what version of the HAL is installed on the device.

Google-maintained versions


If major version upgrades (1.0, 2.0, 3.0, etc.) exist, at least one Google-maintained device must maintain an implementation of each major version until that version is deprecated. If no Google-maintained device ships with a specific major version, Google continues to maintain an old implementation of that major version.

Such maintenance adds minor additional overhead because the old implementation (e.g. 1.2) can be kept and not used by default when a new implementation (e.g. 2.0) is created.

Testing minor version upgrades


Testing the backwards compatibility of minor versions in the framework requires a way to automatically generate minor version implementations. Given the restrictions around Google-maintained versions, hidl-gen will only (and can only) generate adapters that take a 1.(x+n) implementation and provide a 1.x implementation; it cannot generate a 1.0 implementation from a 2.0 implementation (by definition of a major version).

For example, to run 1.1 tests on a 1.2 implementation, you must be able to simulate having a 1.1 implementation. The 1.2 interfaces can automatically be used as 1.1 implementation with some slight differences in behavior (such as the framework manually checking what version something is or calling castFrom on it).

The basic idea is this:

  1. Install an x.(y+n) interface on an Android mobile device.
  2. Install and activate an x.y-target adapter.
  3. Test the device to verify it works as expected when running an older minor version.

These adapters completely hide the fact that the implementation is actually backed by a 1.2 interface and only provides the 1.1 interface (the adapter takes a 1.2 interface and makes it look like a 1.1 interface).

Example workflow

In this example, the Android device runs [email protected]::IFoo/default. To ensure a client works properly with [email protected]::IFoo/default:

  1. In a terminal, run the following:
$ [email protected]
$ INTERFACE=IAllocator
$ INSTANCE=ashmem
$ THREAD_COUNT=1 # can see current thread use on `lshal -i -e`
$ m -j $PACKAGE
$ /data/nativetest64/$PACKAGE/$PACKAGE $INTERFACE $INSTANCE $THREAD_COUNT
Trying to adapt down [email protected]/default
Press any key to disassociate adapter.
  1. Restart the client using adb shell stop (or start) or simply kill the process.
  2. After the test completes, disassociate the adapter.
  3. Restore system state by restarting the device OR by restarting the client.

Additional targets

hidl-gen automatically adds additional build targets for the adapters for every interface specified with hidl_interface in the build system. For package [email protected], there is an additional C++ target [email protected].

Note: No java adapter needs to be made because a C++ adapter can always be used to wrap a Java service.

An adapter for [email protected] takes as an input some implementation, a.b.c@x.(y+n)::ISomething/instance-name, and must register [email protected]::ISomething/instance-name which must also unregister the y+n implementation.

Given the following sample interface:

// IFoo.hal
package [email protected];
interface IFoo {
    doFoo(int32_t a) generates (int64_t b);
    doSubInterface() generates (IFoo a);
};

The code provided by [email protected] is similar to the sample below:

// autogenerated code
// in namespace a::b::c::V1_0::IFoo
struct MockFoo {
    // takes some subclass of V1_0. May be V1_1, V1_2, etc...
    MockFoo(V1_0::IFoo impl) mImpl(impl) {}

    Return<int64_t> doFoo(int32_t a) {
        return this->mImpl->doFoo(a);
    }

    Return<V1_0::ICallback> doSubInterface() {
        // getMockForBinder returns MockCallback instance
        // that corresponds to a particular binder object
        // It can't return a new object every time or
        // clients using interfacesSame will have
        // divergent behavior when using the mock.
        auto _hidl_out = this->mImpl->doSubInterface();
        return getMockForBinder(_hidl_out);
    }
};

Data values are forwarded exactly into and out of the auto-generated mock class, except for sub interfaces, which are returned. These interfaces must be wrapped in the corresponding most recent callback object.

发布了60 篇原创文章 · 获赞 27 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/xiaosaerjt/article/details/104535824