diff options
Diffstat (limited to 'en/devices/architecture/hidl/versioning.html')
-rw-r--r-- | en/devices/architecture/hidl/versioning.html | 655 |
1 files changed, 655 insertions, 0 deletions
diff --git a/en/devices/architecture/hidl/versioning.html b/en/devices/architecture/hidl/versioning.html new file mode 100644 index 00000000..aed6f9fe --- /dev/null +++ b/en/devices/architecture/hidl/versioning.html @@ -0,0 +1,655 @@ +<html devsite> + <head> + <title>Versioning</title> + <meta name="project_path" value="/_project.yaml" /> + <meta name="book_path" value="/_book.yaml" /> + </head> + <body> + <!-- + Copyright 2017 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<p>HIDL requires every interface written in HIDL be versioned. After a HAL +interface is published, it is frozen and any further changes must be made to a +new version of that interface. While a given published interface may not be +modified, it can be extended by another interface.</p> + +<h2 id=code-structure>HIDL code structure</h2> + +<p> +<a href="/reference/hidl/index.html">HIDL code is organized</a> in user-defined +types, interfaces, and packages:</p> + +<ul> +<li><strong>User-defined types (UDTs)</strong>. HIDL provides access to a set of +primitive data types that can be used to compose more complex types via +structures, unions, and enumerations</a>. UDTs are passed to methods of +interfaces, and can be defined at the level of a package (common to all +interfaces) or locally to an interface.</li> +<li><strong>Interfaces</strong>. As a basic building block of HIDL, an interface +consists of UDT and method declarations. Interfaces can also inherit from +another interface.</li> +<li><strong>Packages</strong>. Organizes related HIDL interfaces and the data +types on which they operate. A package is identified by a name and a version and +includes the following: +<ul> + <li>Data-type definition file called <code>types.hal</code>.</li> + <li>Zero or more interfaces, each in their own <code>.hal</code> file.</li> +</ul> +</li> +</ul> + +<p>The data-type definition file <code>types.hal</code> contains only UDTs (all +package-level UDTs are kept in a single file). Representations in the target +language are available to all interfaces in the package.</p> + +<h2 id=philosophy>Versioning philosophy</h2> +<p>A HIDL package (such as <code>android.hardware.nfc</code>), after being +published for a given version (such as <code>1.0</code>), is immutable; it +cannot be changed. Modifications to the interfaces in the package or any +changes to its UDTs can take place only in <em>another</em> package.</p> + +<p>In HIDL, versioning applies at the package level, not at the interface level, +and all interfaces and UDTs in a package share the same version. Package +versions follow <a href="http://semver.org/" class="external">semantic +versioning</a> without the patch level and build-metadata components. Within a +given package, a <strong>minor version</strong> bump implies the new version of +the package is backwards-compatible with the old package and a <strong>major +version</strong> bump implies the new version of the package is not +backwards-compatible with the old package.</p> + +<p>Conceptually, a package can relate to another package in one of several ways: +</p> + +<ul> +<li><strong>Not at all</strong>.</li> +<li><strong>Package-level backwards-compatible extensibility</strong>. This +occurs for new minor-version uprevs (next incremented revision) of a package; +the new package has the same name and major version as the old package, but a +higher minor version. Functionally, the new package is a superset of the old +package, meaning: +<ul> + <li>Top-level interfaces of the parent package are present in the new package, + though the interfaces may have new methods, new interface-local UDTs (the + interface-level extension described below), and new UDTs in + <code>types.hal</code>.</li> + <li>New interfaces may also be added to the new package.</li> + <li>All data types of the parent package are present in the new package and + can be handled by the (possibly reimplemented) methods from the old package. + </li> + <li>New data types may also be added for use by either new methods of uprev'ed + existing interfaces, or by new interfaces.</li> +</ul> +</li> + +<li><strong>Interface-level backwards-compatible extensibility</strong>. The new +package can also extend the original package by consisting of logically separate +interfaces that simply provide additional functionality, and not the core one. +For this purpose, the following may be desirable: +<ul> + <li>Interfaces in the new package need recourse to the data types of the old + package.</li> + <li>Interfaces in new package may extend interfaces of one or more old + packages.</li> +</ul> +</li> +<li><strong>Extend the original backwards-incompatibility</strong>. This is a +major-version uprev of the package and there need not be any correlation between +the two. To the extent that there is, it can be expressed with a combination of +types from the older version of the package, and inheritance of a subset of +old-package interfaces.</li> +</ul> + +<h2 id=code-layout>HIDL code layout</h2> +<p>HIDL includes core and vendor packages.</p> + +<p>Core HIDL interfaces are those specified by Google. The packages they belong +to start with <code>android.hardware.</code> and are named by subsystem, +potentially with nested levels of naming. For example, the NFC package is named +<code>android.hardware.nfc</code> and the camera package is +<code>android.hardware.camera</code>. In general, a core package has the name +<code>android.hardware.</code>[<code>name1</code>].[<code>name2</code>]…. +HIDL packages have a version in addition to their name. For example, the package +<code>android.hardware.camera</code> may be at version <code>3.4</code>; this is +important, as the version of a package affects its placement in the source tree. +</p> + +<p>All core packages are placed under <code>hardware/interfaces/</code> in the +build system. The package +<code>android.hardware.</code>[<code>name1</code>].[<code>name2</code>]… +at version <code>$m.$n</code> is under +<code>hardware/interfaces/name1/name2/</code>…<code>/$m.$n/</code>; package +<code>android.hardware.camera</code> version <code>3.4</code> is in directory +<code>hardware/interfaces/camera/3.4/.</code> A hard-coded mapping exists +between the package prefix <code>android.hardware.</code> and the path +<code>hardware/interfaces/</code>.</p> + +<p>Non-core (vendor) packages are those produced by the SoC vendor or ODM. The +prefix for non-core packages is <code>vendor.$(VENDOR).hardware.</code> where +<code>$(VENDOR)</code>refers to an SoC vendor or OEM/ODM. This maps to the path +<code>vendor/$(VENDOR)/interfaces</code> in the tree (this mapping is also +hard-coded).</p> + +<h2 id=fqn>Fully-qualified user-defined-type names</h2> +<p>In HIDL, every UDT has a fully-qualified name that consists of the UDT name, +the package name where the UDT is defined, and the package version. The +fully-qualified name is used only when instances of the type are declared and +not where the type itself is defined. For example, assume package +<code>android.hardware.nfc,</code> version <code>1.0</code> defines a struct +named <code>NfcData</code>. At the site of the declaration (whether in +<code>types.hal</code> or within an interface's declaration), the declaration +simply states:</p> + +<pre class="prettyprint"> +struct NfcData { + vec<uint8_t> data; +}; +</pre> + +<p>When declaring an instance of this type (whether within a data structure or +as a method parameter), use the fully-qualified type name:</p> + +<pre class="prettyprint">android.hardware.nfc@1.0::NfcData</pre> + +<p>The general syntax is +<code><var>PACKAGE</var>@<var>VERSION</var>::<var>UDT</var></code>, where:</p> + +<ul> +<li><code><var>PACKAGE</var></code> is the dot-separated name of a HIDL package +(e.g., <code>android.hardware.nfc</code>).</li> +<li><code><var>VERSION</var></code> is the dot-separated major.minor-version +format of the package (e.g., <code>1.0</code>).</li> +<li><code><var>UDT</var></code> is the the dot-separated name of a HIDL UDT. +Since HIDL supports nested UDTs and HIDL interfaces can contain UDTs (a type of +nested declaration), dots are used to access the names.</li> +</ul> + +<p>For example, if the following nested declaration was defined in the common +types file in package <code>android.hardware.example</code> version +<code>1.0</code>:</p> + +<pre class="prettyprint"> +// types.hal +package android.hardware.example@1.0; +struct Foo { + struct Bar { + // … + }; + Bar cheers; +}; +</pre> + +<p>The fully-qualified name for <code>Bar</code> is +<code>android.hardware.example@1.0::Foo.Bar</code>. If, in addition to being in +the above package, the nested declaration were in an interface called +<code>IQuux</code>:</p> + +<pre class="prettyprint"> +// IQuux.hal +package android.hardware.example@1.0; +interface IQuux { + struct Foo { + struct Bar { + // … + }; + Bar cheers; + }; + doSomething(Foo f) generates (Foo.Bar fb); +}; +</pre> + +<p>The fully-qualified name for <code>Bar</code> is +<code>android.hardware.example@1.0::IQuux.Foo.Bar</code>.</p> + +<p>In both cases, <code>Bar</code> can be referred to as <code>Bar</code> only +within the scope of the declaration of <code>Foo</code>. At the package or +interface level, you must refer to <code>Bar</code> via <code>Foo</code>: +<code>Foo.Bar</code>, as in the declaration of method <code>doSomething</code> +above. Alternatively, you could declare the method more verbosely as:</p> + +<pre class="prettyprint"> +// IQuux.hal +doSomething(android.hardware.example@1.0::IQuux.Foo f) generates (android.hardware.example@1.0::IQuux.Foo.Bar fb); +</pre> + +<h2 id=enumeration>Fully-qualified enumeration values</h2> +<p>If a UDT is an enum type, then each value of the enum type has a +fully-qualified name that starts with the fully-qualified name of the enum type, +followed by a colon, then followed by the name of the enum value. For example, +assume package <code>android.hardware.nfc,</code> version <code>1.0</code> +defines an enum type <code>NfcStatus</code>:</p> + +<pre class="prettyprint"> +enum NfcStatus { + STATUS_OK, + STATUS_FAILED +}; +</pre> + +<p>When referring to <code>STATUS_OK</code>, the fully qualified name is:</p> + +<pre class="prettyprint">android.hardware.nfc@1.0::NfcStatus:STATUS_OK</pre> + +<p>The general syntax is +<code><var>PACKAGE</var>@<var>VERSION</var>::<var>UDT</var>:<var>VALUE</var></code>, +where: + +<ul> +<li><code><var>PACKAGE</var>@<var>VERSION</var>::<var>UDT</var></code> is the +exact same fully qualified name for the enum type.</li> +<li><code><var>VALUE</var></code> is the value's name.</li> +</ul> + +<h2 id=auto-interference>Auto-inference rules</h2> +<p>A fully-qualified UDT name does not need to be specified. A UDT name can +safely omit the following:</p> +<ul> +<li>The package, e.g. <code>@1.0::IFoo.Type</code></li> +<li>Both package and version, e.g. <code>IFoo.Type</code></li> +</ul> + +<aside class="caution"><strong>Caution:</strong> UDT names missing a version but +specifying a package present are not allowed.</aside> + +<p>HIDL attempts to complete the name using auto-interference rules (lower rule +number means higher priority).</p> + +<h3 id=rule1>Rule 1</h3> +<p>If no package and version is provided, a local name lookup is attempted. +Example:</p> + +<pre class="prettyprint"> +interface Nfc { + typedef string NfcErrorMessage; + send(NfcData d) generates (@1.0::NfcStatus s, NfcErrorMessage m); +}; +</pre> + +<p><code>NfcErrorMessage</code> is looked up locally, and the <code>typedef</code> +above it is found. <code>NfcData</code> is also looked up locally, but as it is +not defined locally, rule 2 and 3 are used. <code>@1.0::NfcStatus</code> +provides a version, so rule 1 does not apply.</p> + +<h3 id=rule2>Rule 2</h3> +<p>If rule 1 fails and a component of the fully-qualified name is missing +(package, version, or package and version), the component is autofilled with +information from the current package. The HIDL compiler then looks in the +current file (and all imports) to find the autofilled fully-qualified name. +Using the example above, assume the declaration of <code>ExtendedNfcData</code> +was made in the same package (<code>android.hardware.nfc</code>) at the same +version (<code>1.0</code>) as <code>NfcData</code>, as follows:</p> + +<pre class="prettyprint"> +struct ExtendedNfcData { + NfcData base; + // … additional members +}; +</pre> + +<p>The HIDL compiler fills out the package name and version name from the +current package to produce the fully-qualified UDT name +<code>android.hardware.nfc@1.0::NfcData</code>. As the name exists in the +current package (assuming it is imported properly), it is used for the +declaration.</p> + +<p>A name in the current package is imported only if one of the following is +true:</p> +<ul> +<li>It is imported explicitly with an <code>import</code> statement.</li> +<li>It is defined in <code>types.hal</code> in the current package</li> +</ul> + +<p>The same process is followed if <code>NfcData</code> was qualified by only +the version number:</p> + +<pre class="prettyprint"> +struct ExtendedNfcData { + // autofill the current package name (android.hardware.nfc) + @1.0::NfcData base; + // … additional members +}; +</pre> + +<h3 id=rule3>Rule 3</h3> +<p>If rule 2 fails to produce a match (the UDT is not defined in the current +package), the HIDL compiler scans for a match within all imported packages. +Using the above example, assume <code>ExtendedNfcData</code> is declared in +version <code>1.1</code> of package <code>android.hardware.nfc</code>, +<code>1.1</code> imports <code>1.0</code> as it should (see +<a href="#package-ext">Package-Level Extensions</a>), and the definition +specifies only the UDT name:</p> + +<pre class="prettyprint"> +struct ExtendedNfcData { + NfcData base; + // … additional members +}; +</pre> + +<p>The compiler looks for any UDT named <code>NfcData</code> and finds one in +<code>android.hardware.nfc</code> at version <code>1.0</code>, resulting in a +fully-qualified UDT of <code>android.hardware.nfc@1.0::NfcData</code>. If more +than one match is found for a given partially-qualified UDT, the HIDL compiler +throws an error.</p> + +<h3 id=rule-example>Example</h3> +<p>Using rule 2, an imported type defined in the current package is favored over +an imported type from another package:</p> + +<pre class="prettyprint"> +// hardware/interfaces/foo/1.0/types.hal +package android.hardware.foo@1.0; +struct S {}; + +// hardware/interfaces/foo/1.0/IFooCallback.hal +package android.hardware.foo@1.0; +interface IFooCallback {}; + +// hardware/interfaces/bar/1.0/types.hal +package android.hardware.bar@1.0; +typedef string S; + +// hardware/interfaces/bar/1.0/IFooCallback.hal +package android.hardware.bar@1.0; +interface IFooCallback {}; + +// hardware/interfaces/bar/1.0/IBar.hal +package android.hardware.bar@1.0; +import android.hardware.foo@1.0; +interface IBar { + baz1(S s); // android.hardware.bar@1.0::S + baz2(IFooCallback s); // android.hardware.foo@1.0::IFooCallback +}; +</pre> + +<ul> +<li><strong><code>S</code></strong> is interpolated as +<code>android.hardware.bar@1.0::S</code>, and is found in +<code>bar/1.0/types.hal</code> (because <code>types.hal</code> is automatically +imported).</li> +<li><strong><code>IFooCallback</code></strong> is interpolated as +<code>android.hardware.bar@1.0::IFooCallback</code> using rule 2, but it +cannot be found because <code>bar/1.0/IFooCallback.hal</code> is not imported +automatically (as <code>types.hal</code> is). Thus, rule 3 resolves it to +<code>android.hardware.foo@1.0::IFooCallback</code> instead, which is imported +via <code>import android.hardware.foo@1.0;</code>).</li> +</ul> + +<h2 id=types>types.hal</h2> +<p>Every HIDL package contains a <code>types.hal</code> file with UDTs share +among all interfaces participating in that package. HIDL types are always +public; regardless of whether a UDT is declared in <code>types.hal</code> or +within an interface declaration, these types are accessible outside of the scope +where they are defined. <code>types.hal</code> is not meant to describe the +public API of a package, but rather to host UDTs used by all interfaces within +the package. Due to the nature of HIDL, all UDTs are a part of the interface. +</p> + +<p><code>types.hal</code> consists of UDTs and <code>import</code> statements. +Because <code>types.hal</code> is made available to every interface of the +package (it is an implicit import), these <code>import</code> statements are +package-level by definition. UDTs in <code>types.hal</code> may also incorporate +UDTs and interfaces thus imported.</p> + +<p>For example, for an <code>IFoo.hal</code>:</p> + +<pre class="prettyprint"> +package android.hardware.foo@1.0; +// whole package import +import android.hardware.bar@1.0; +// types only import +import android.hardware.baz@1.0::types; +// partial imports +import android.hardware.qux@1.0::IQux.Quux; +// partial imports +import android.hardware.quuz@1.0::Quuz; +</pre> + +<p>The following are imported:</p> +<ul> +<li><code>android.hidl.base@1.0::IBase</code> (implicitly)</li> +<li><code>android.hardware.foo@1.0::types</code> (implicitly)</li> +<li>Everything in <code>android.hardware.bar@1.0</code> (including all +interfaces and its <code>types.hal</code>)</li> +<li><code>types.hal</code> from <code>android.hardware.baz@1.0::types</code> +(interfaces in <code>android.hardware.baz@1.0</code> are not imported)</li> +<li><code>IQux.hal</code> and <code>types.hal</code> from +<code>android.hardware.qux@1.0</code></li> +<li><code>Quuz</code> from <code>android.hardware.quuz@1.0</code> (assuming +<code>Quuz</code> is defined in <code>types.hal</code>, the entire +<code>types.hal</code> file is parsed, but types other than <code>Quuz</code> +are not imported).</li> +</ul> + +<h2 id=interface-version>Interface-level versioning</h2> +<p>Each interface within a package resides in its own file. The package the +interface belongs to is declared at the top of the interface using the +<code>package</code> statement. Following the package declaration, zero or more +interface-level imports (partial or whole-package) may be listed. For example: +</p> + +<pre class="prettyprint">package android.hardware.nfc@1.0;</pre> + +<p>In HIDL, interfaces can inherit from other interfaces using the +<code>extends</code> keyword. For an interface to extend another interface, it +must have access to it via an <code>import</code> statement. The name of the +interface being extended (the base interface) follows the rules for type-name +qualification explained above. An interface may inherit only from one interface; +HIDL does not support multiple inheritance.</p> + +<p>The uprev versioning examples below use the following package:</p> + +<pre class="prettyprint"> +// types.hal +package android.hardware.example@1.0 +struct Foo { + struct Bar { + vec<uint32_t> val; + }; +}; + +// IQuux.hal +package android.hardware.example@1.0 +interface IQuux { + fromFooToBar(Foo f) generates (Foo.Bar b); +} +</pre> + +<h3 id=rules>Uprev rules</h3> +<p>To define a package <code>package@major.minor</code>, either A or all of B +must be true:</p> + +<table> +<tr> +<th width="10%">Rule A</th> +<td>"Is a start minor version": All previous minor versions, +<code>package@major.0</code>, <code>package@major.1</code>, …, +<code>package@major.(minor-1)</code> must not be defined. +</td> +</tr> +</table> + +<strong>OR</strong> + +<table> +<tr> +<th width="10%">Rule B</th> +<td><p>All of the following is true:</p> + +<ol> +<li>"Previous minor version is valid": <code>package@major.(minor-1)</code> +must be defined and follow the same rule A (none of +<code>package@major.0</code> through <code>package@major.(major-2)</code> +are defined) or rule B (if it is an uprev from <code>@major.(major-2)</code>); +<br><br> +AND +<br><br> +</li> +<li>"Inherit at least one interface with the same name": There exists an +interface <code>package@major.minor::IFoo</code> that extends +<code>package@major.(minor-1)::IFoo</code>; +<br><br> +AND +<br><br> +</li> +<li>"No inherited interface with a different name": There must not exist +<code>package@major.minor::IBar</code> that extends +<code>package@major.(minor-1)::IBaz</code>, where <code>IBar</code> and +<code>IBaz</code> are two different names. If there is an interface with the +same name, <code>package@major.minor::IBar</code> must extend +<code>package@major.(minor-k)::IBar</code> such that no IBar exists with a +smaller k.</li> +</ol> +</td> +</tr> +</table> + +<p>Because of rule A:</p> +<ul> +<li>The package can start with any minor version number (for example, +<code>android.hardware.biometrics.fingerprint</code> starts at +<code>@2.1</code>.)</li> +<li>The requirement "<code>android.hardware.foo@1.0</code> is not defined" means +the directory <code>hardware/interfaces/foo/1.0</code> should not even exist. +</li> +</ul> + +<p>However, rule A does not affect a package with the same package name but a +different <em>major</em> version (for example, +<code>android.hardware.camera.device</code> has both <code>@1.0</code> and +<code>@3.2</code> defined; <code>@3.2</code> doesn't need to interact with +<code>@1.0</code>.) Hence, <code>@3.2::IExtFoo</code> can extend +<code>@1.0::IFoo</code>.</p> + +<p>Provided the package name is different, +<code>package@major.minor::IBar</code> may extend from an interface with a +different name (for example, <code>android.hardware.bar@1.0::IBar</code> can +extend <code>android.hardware.baz@2.2::IBaz</code>). If an interface does not +explicitly declare a super type with the <code>extend</code> keyword, it will +extend <code>android.hidl.base@1.0::IBase</code> (except <code>IBase</code> +itself).</p> + +<p>B.2 and B.3 must be followed at the same time. For example, even if +<code>android.hardware.foo@1.1::IFoo</code> extends +<code>android.hardware.foo@1.0::IFoo</code> to pass rule B.2, if an +<code>android.hardware.foo@1.1::IExtBar</code> extends +<code>android.hardware.foo@1.0::IBar</code>, this is still not a valid uprev. +</p> + +<h3 id=uprev>Upreving interfaces</h3> +<p>To uprev <code>android.hardware.example@1.0</code> (defined above) to +<code>@1.1</code>:</p> + +<pre class="prettyprint"> +// types.hal +package android.hardware.example@1.1; +<strong>import android.hardware.example@1.0;</strong> + +// IQuux.hal +package android.hardware.example@1.1 +interface IQuux <strong>extends @1.0::IQuux</strong> { + <strong>fromBarToFoo(Foo.Bar b) generates (Foo f);</strong> +} +</pre> + +<p>This is a package-level <code>import</code> of version <code>1.0</code> of +<code>android.hardware.example</code> in <code>types.hal</code>. While no new +UDTs are added in version <code>1.1</code> of the package, references to UDTs in +version <code>1.0</code> are still needed, hence the package-level import +in <code>types.hal</code>. (The same effect could have been achieved with an +interface-level import in <code>IQuux.hal</code>.)</p> + +<p>In <code>extends @1.0::IQuux</code> in the declaration of +<code>IQuux</code>, we specified the version of <code>IQuux</code> that is being +inherited (disambiguation is required because <code>IQuux</code> is used to +declare an interface and to inherit from an interface). As declarations are +simply names that inherit all package and version attributes at the site of the +declaration, the disambiguation must be in the name of the base interface; we +could have used the fully-qualified UDT as well, but that would have been +redundant.</p> + +<p>The new interface <code>IQuux</code> does not re-declare method +<code>fromFooToBar()</code> it inherits from <code>@1.0::IQuux</code>; it simply +lists the new method it adds <code>fromBarToFoo()</code>. In HIDL, inherited +methods may <strong>not</strong> be declared again in the child interfaces, so +for <code>IQuux</code> it would not be an option to declare +<code>fromFooToBar()</code> explicitly.</p> + +<aside class="key-point"><strong>Key Point:</strong> In HIDL, every inherited +method from a base class must be explicitly implemented in the inheriting class. +If a method implementation needs to fall back to that of the base, the fallback +must be in the implementation.</aside> + +<h3 id=conventions>Uprev conventions</h3> +<p>Sometimes interface names must rename the extending interface. We recommend +that enum extensions, structs, and unions have the same name as what they extend +unless they are sufficiently different to warrant a new name. Examples:</p> + +<pre class="prettyprint"> +// in parent hal file +enum Brightness : uint32_t { NONE, WHITE }; + +// in child hal file extending the existing set with additional similar values +enum Brightness : @1.0::Brightness { AUTOMATIC }; + +// extending the existing set with values that require a new, more descriptive name: +enum Color : @1.0::Brightness { HW_GREEN, RAINBOW }; +</pre> + +<p>Unless a method warrants a new name, it should be named similarly to what it +is extending. For example, the method <code>foo_1_1</code> in +<code>@1.1::IFoo</code> may replace the functionality of the <code>foo</code> +method in <code>@1.0::IFoo</code>.</p> + +<h2 id=package-ext>Package-level versioning</h2> +<p>HIDL versioning occurs at the package level; after a package is published, it +is immutable (its set of interfaces and UDTs cannot be changed). Packages can +relate to each other in several ways, all of which are expressible via a +combination of interface-level inheritance and building of UDTs by composition. +</p> + +<p>However, one type of relationship is strictly-defined and must be enforced: +<em>Package-level backwards-compatible inheritance</em>. In this scenario, the +<em>parent</em> package is the package being inherited from and the +<em>child</em> package is the one extending the parent. Package-level +backwards-compatible inheritance rules are as follows:</p> + +<ol> +<li>All interfaces of the parent package are inherited from by interfaces in the +child package.</li> +<li>All data types of the parent package are present in the new package and can +be handled by the (possibly reimplemented) methods from the old package.</li> +<li>New interfaces may also be added the new package (no restrictions about +relationships to other interfaces in other packages).</li> +<li>New data types may also be added for use by either new methods of uprev'ed +existing interfaces, or by new interfaces.</li> +</ol> + +<p>These rules can be implemented using HIDL interface-level inheritance and UDT +composition, but require meta-level knowledge to know these relationships +constitute a backwards-compatible package extension. This knowledge is inferred +as follows:</p> + +<aside class="key-point"><strong>Key Point:</strong> For package +<code>package</code> at version <code>major.minor</code>, if a +<code>package</code> exists at <code>major.(minor-1)</code>, then +<code>package@major.minor</code> is a minor uprev, and must follow the rules for +backwards-compatibility.</aside> + +<p>If a package meets this requirement, <code>hidl-gen</code> enforces +backwards-compatibility rules.</p> + + </body> +</html> |