
{"id":13000,"date":"2026-08-03T07:31:39","date_gmt":"2026-08-03T07:31:39","guid":{"rendered":"https:\/\/developer.rdkcentral.com\/documentation\/?page_id=13000"},"modified":"2026-08-03T07:32:42","modified_gmt":"2026-08-03T07:32:42","slug":"libpackage","status":"publish","type":"page","link":"https:\/\/developer.rdkcentral.com\/documentation\/documentation\/rdk_video_documentation\/components\/libpackage\/","title":{"rendered":"libpackage"},"content":{"rendered":"\n<p><code>Libpackage<\/code> is a shared library that implements the <code>IPackageImpl<\/code> interface, providing the package management abstraction layer for DAC (Downloadable Application Container) applications in RDK. It handles the complete lifecycle of DAC application packages in the RALF (<code>.ralf<\/code>) format: installation to persistent storage, dependency resolution, cryptographic signature verification, on-demand mounting, and removal.<\/p>\n\n\n\n<p>The library sits between the app management layer above \u2014 which drives install, launch, and remove workflows \u2014 and the <code>libralf<\/code> package-format library below, which provides the underlying mechanics for opening, verifying, and mounting RALF package archives. <code>libpackage<\/code> adds the coordination logic on top: resolving and recursively handling package dependencies, managing mount reference counts, serialising mount metadata as JSON for consumers, and building the certificate verification bundle from the device certificate store.<\/p>\n\n\n\n<p>At the device level, <code>libpackage<\/code> enables an app management stack that installs and runs containerised DAC applications directly from signed RALF packages. Packages are stored persistently on the filesystem, re-discovered at each library initialisation, and mounted on-demand into isolated directories under <code>\/tmp\/mounts\/<\/code> so that the app runtime can locate and execute application content. Dependency packages are resolved and co-mounted in the same operation, ensuring all shared assets are available before the application is launched.<\/p>\n\n\n\n<p>At the module level, <code>libpackage<\/code> exposes six operations through the <code>IPackageImpl<\/code> interface: <code>Initialize<\/code>, <code>Install<\/code>, <code>Uninstall<\/code>, <code>Lock<\/code>, <code>Unlock<\/code>, and <code>GetFileMetadata<\/code>. These map directly to the stages of a DAC application lifecycle, and the library is obtained via the <code>IPackageImpl::instance()<\/code> factory, which returns the <code>RalfPackageImpl<\/code> implementation.<\/p>\n\n\n\n<div class=\"wp-block-merpress-mermaidjs diagram-source-mermaid\"><pre class=\"mermaid\">flowchart LR\n\n%% Styles\nclassDef Apps stroke:#00B9F1,fill:#E6F7FD,stroke-width:2px;\nclassDef RDKMW stroke:#75D701,fill:#F1FFE6,stroke-width:2px;\nclassDef VL stroke:#808080,fill:#F2F2F2,stroke-width:2px;\n\n%% Apps Layer\n    subgraph Apps[\"Apps &amp; Runtimes\"]\n        RDKUI[\"UI\"]\n        FBApps[\"Firebolt Apps\"]\n        WPE_RT[\"WPE Runtime\"]\n    end\n\n%% Middleware\n    subgraph RDKMW[\"RDK Core Middleware\"]\n        AM[\"App Manager\"]\n        libpkg[\"libpackage\"]\n        Westeros[\"Westeros\"]\n        Thunder[\"WPEFramework (Thunder)\"]\n    end\n\n%% Vendor Layer\n    subgraph VL[\"Vendor Layer\"]\n        ralflib[\"libralf\"]\n        PkgStore[\"Package Storage\"]\n    end\n\n    Apps -->|\"Firebolt APIs\"| RDKMW\n    AM -->|\"IPackageImpl API\"| libpkg\n    libpkg -->|\"Package open \/ verify \/ mount\"| ralflib\n    libpkg -->|\"R\/W package files\"| PkgStore\n    ralflib --> PkgStore\n\n    class RDKUI,FBApps,WPE_RT Apps\n    class AM,libpkg,Westeros,Thunder RDKMW\n    class ralflib,PkgStore VL<\/pre><\/div>\n\n\n\n<p><strong>Key Features &amp; Responsibilities:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Package Installation<\/strong>: Accepts a RALF package file locator, performs full cryptographic verification against the device certificate bundle, resolves declared dependencies against the set of already-installed packages, and copies the package to the persistent installation path under <code>DAC_APP_PATH<\/code>.<\/li>\n\n\n\n<li><strong>Dependency Resolution<\/strong>: Before installing or locking a package, reads the package&#8217;s embedded metadata to enumerate declared dependencies and verifies that each dependency is already installed in a version that satisfies the declared version constraint.<\/li>\n\n\n\n<li><strong>Certificate-Based Package Verification<\/strong>: Loads all certificate files from <code>RDK_PACKAGE_CERT_PATH<\/code> at initialisation to build a <code>VerificationBundle<\/code>, which is subsequently used by <code>libralf<\/code> to verify package signatures on every open and mount operation.<\/li>\n\n\n\n<li><strong>Package Locking (Mount Management)<\/strong>: Mounts a requested package and all of its transitive dependencies into dedicated directories under <code>\/tmp\/mounts\/<\/code>. Maintains a reference count per mounted package so that shared dependency packages are not prematurely unmounted when they are in use by more than one application.<\/li>\n\n\n\n<li><strong>Mount Metadata Serialisation<\/strong>: After a successful lock, serialises the list of all mounted packages \u2014 including their mount paths and config JSON paths \u2014 into a temporary JSON file, which is returned via <code>ConfigMetaData.ralfPkgPath<\/code> for use by the runtime.<\/li>\n\n\n\n<li><strong>Package Unlocking<\/strong>: Decrements the mount reference count for each package in the dependency tree and unmounts those packages whose count reaches zero.<\/li>\n\n\n\n<li><strong>Installed Package Discovery<\/strong>: On <code>Initialize()<\/code>, scans <code>DAC_APP_PATH<\/code> recursively to discover all packages already present on the filesystem and populates the initial installed-package list and configuration metadata for the caller.<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Design<\/h2>\n\n\n\n<p><code>libpackage<\/code> is designed as a single-class shared library that implements a well-defined interface contract (<code>IPackageImpl<\/code>) driven by the app management layer above. The design separates the public API surface \u2014 <code>Initialize<\/code>, <code>Install<\/code>, <code>Uninstall<\/code>, <code>Lock<\/code>, <code>Unlock<\/code>, and <code>GetFileMetadata<\/code> \u2014 from the private coordination logic in <code>RalfPackageImpl<\/code>, which handles certificate loading, dependency graph traversal, mount lifecycle, and JSON metadata serialisation. All operations guard against use before initialisation by checking <code>mIsInitialized<\/code> at entry, ensuring that callers receive a deterministic <code>FAILED<\/code> result rather than undefined behaviour if the initialisation sequence is incomplete.<\/p>\n\n\n\n<p>Dependency handling uses a recursive descent strategy: the <code>lockPackage()<\/code> function resolves and mounts each dependency before mounting the package itself, matching the order in which the package metadata enumerates dependencies. Mount reference counting in <code>mMountedPackages<\/code> \u2014 a <code>std::map<\/code> keyed on <code>packageId + \"_\" + version<\/code> \u2014 ensures that a dependency shared by multiple applications is mounted once and only unmounted when the last consumer releases it. This design avoids redundant mounts while still allowing independent lock and unlock calls from multiple callers.<\/p>\n\n\n\n<p>The northbound interaction with the app management layer is entirely through the <code>IPackageImpl<\/code> interface. The <code>IPackageImpl::instance()<\/code> factory in <code>RalfPackageHandler.cpp<\/code> constructs a <code>RalfPackageImpl<\/code> instance, which is returned as a <code>std::shared_ptr&lt;IPackageImpl&gt;<\/code>. This keeps the caller decoupled from the concrete implementation class.<\/p>\n\n\n\n<p>The southbound interaction is with the <code>libralf<\/code> library, which handles the RALF archive format. <code>libpackage<\/code> calls <code>ralf::Package::open()<\/code> to parse and validate a package file against the verification bundle, <code>ralf::Package::verify()<\/code> for full signature verification, <code>ralf::Package::mount()<\/code> to mount the archive filesystem, and <code>ralf::Package::metaData()<\/code> to read embedded metadata including dependencies and permissions. <code>libpackage<\/code> holds the resulting <code>ralf::PackageMount<\/code> objects inside the <code>MountedPackageInfo<\/code> structure to ensure they remain live for the duration of the lock.<\/p>\n\n\n\n<p>Communication with the app management layer is entirely through the <code>IPackageImpl<\/code> interface via direct in-process function calls. JSON serialisation via <code>jsoncpp<\/code> is scoped to writing mount metadata to the temporary file whose path is returned to the caller via <code>ConfigMetaData.ralfPkgPath<\/code>.<\/p>\n\n\n\n<p>Package files are stored persistently on the filesystem at <code>DAC_APP_PATH\/{packageId}\/{version}\/package.ralf<\/code>. Mount points are created transiently under <code>\/tmp\/mounts\/{packageId}_{version}\/rootfs\/<\/code> and are unmounted on <code>Unlock()<\/code> (the mount directories themselves are not removed by <code>libpackage<\/code>). Configuration metadata files (<code>config.json<\/code>) are written alongside each mount point and are re-used on subsequent lock requests to avoid redundant extraction from the archive.<\/p>\n\n\n\n<div class=\"wp-block-merpress-mermaidjs diagram-source-mermaid\"><pre class=\"mermaid\">graph TD\n\n    subgraph Boundary[\"libpackage (Shared Library \u2014 C++)\"]\n        IFACE[\"IPackageImpl Interface\\nInitialize \u00b7 Install \u00b7 Uninstall\\nLock \u00b7 Unlock \u00b7 GetFileMetadata\"]\n        CertLoader[\"Certificate Loader\\ninitializeVerificationBundle\"]\n        DepCheck[\"Dependency Checker\\ncheckPackageDependencies\"]\n        MountMgr[\"Mount Manager\\nlockPackage \u00b7 unmountDependentPackages\\nmMountedPackages map\"]\n        JsonSer[\"JSON Serialiser\\nserializeToJson \u00b7 dumpPackageInfo\"]\n    end\n\n    ExtRalf[\"libralf\"]\n    ExtJson[\"jsoncpp\"]\n    FS[(\"Filesystem\\nDAC_APP_PATH \/ \/tmp\/mounts\/ \/ RDK_PACKAGE_CERT_PATH\")]\n\n    IFACE --> CertLoader\n    IFACE --> DepCheck\n    IFACE --> MountMgr\n    IFACE --> JsonSer\n    CertLoader -->|\"Certificate::loadFromFile()\"| ExtRalf\n    DepCheck -->|\"Package::metaData() \/ VersionConstraint\"| ExtRalf\n    MountMgr -->|\"Package::open() \/ verify() \/ mount()\"| ExtRalf\n    JsonSer -->|\"toStyledString()\"| ExtJson\n    CertLoader --> FS\n    MountMgr --> FS\n    JsonSer --> FS<\/pre><\/div>\n\n\n\n<h4 class=\"wp-block-heading\">Threading Model<\/h4>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Threading Architecture<\/strong>: Single-threaded. All operations execute synchronously on the calling thread.<\/li>\n\n\n\n<li><strong>Main Thread<\/strong>: All <code>IPackageImpl<\/code> operations \u2014 including recursive dependency traversal in <code>lockPackage()<\/code> and filesystem enumeration in <code>Initialize()<\/code> \u2014 run to completion on the caller&#8217;s thread before returning.<\/li>\n\n\n\n<li><strong>Synchronization<\/strong>: All operations are synchronous. Thread safety for concurrent access to the same instance is the caller&#8217;s responsibility.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Prerequisites and Dependencies<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">Platform and Integration Requirements<\/h4>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Build Dependencies<\/strong>: <code>packager-headers<\/code> (provides the <code>IPackageImpl<\/code> interface and associated types); <code>ralf-utils<\/code> (provides the <code>libralf<\/code> package format library); <code>jsoncpp<\/code> (JSON value construction and serialisation).<\/li>\n\n\n\n<li><strong>Device Services \/ HAL<\/strong>: <code>libralf<\/code> is the package-format library acting as the abstraction layer below <code>libpackage<\/code>. The full API surface used is: <code>ralf::Package::open()<\/code> (parse and validate a package file with certificate expiry check), <code>ralf::Package::verify()<\/code> (full cryptographic signature verification), <code>ralf::Package::mount()<\/code> (mount the RALF archive rootfs into a directory), <code>ralf::Package::metaData()<\/code> (read embedded package metadata including dependencies, type, and application info), <code>ralf::PackageMount::isMounted()<\/code> \/ <code>ralf::PackageMount::unmount()<\/code> (mount lifecycle control), <code>ralf::Certificate::loadFromFile()<\/code> (load a certificate from a PEM\/DER file), <code>ralf::VersionNumber::fromString()<\/code> (parse a version string), <code>ralf::VersionConstraint::isSatisfiedBy()<\/code> (evaluate whether an installed version satisfies a declared constraint).<\/li>\n\n\n\n<li><strong>Configuration Files<\/strong>: Certificate files located in <code>RDK_PACKAGE_CERT_PATH<\/code> (default <code>\/etc\/rdk\/certs<\/code>) are loaded during <code>Initialize()<\/code> to build the package signature verification bundle.<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">Component State Flow<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">Initialization to Active State<\/h4>\n\n\n\n<p><code>libpackage<\/code> begins in an uninitialised state immediately after the <code>RalfPackageImpl<\/code> instance is created via <code>IPackageImpl::instance()<\/code>. The <code>Initialize()<\/code> call drives the library through its setup sequence: it first resolves the UID and GID of the designated package-management user via <code>getpwnam()<\/code>, then builds the verification bundle by loading all certificate files found in <code>RDK_PACKAGE_CERT_PATH<\/code>. If either step fails, <code>Initialize()<\/code> returns <code>FAILED<\/code> and <code>mIsInitialized<\/code> remains <code>false<\/code>. When <code>DAC_APP_PATH<\/code> does not yet exist it is created; if it already exists, all <code>package.ralf<\/code> files are discovered recursively and the caller&#8217;s <code>ConfigMetadataArray<\/code> is populated with their identifiers, versions, and user\/group ownership. On success, <code>mIsInitialized<\/code> is set to <code>true<\/code>.<\/p>\n\n\n\n<p>The component transitions through the following states: <strong>Uninitialised<\/strong> (instance created, no operations permitted) \u2192 <strong>Initialising<\/strong> (user info lookup, certificate loading, package discovery) \u2192 <strong>Active<\/strong> (all six <code>IPackageImpl<\/code> operations available) \u2192 <strong>Torn Down<\/strong> (instance destroyed, all <code>PackageMount<\/code> RAII objects released).<\/p>\n\n\n\n<div class=\"wp-block-merpress-mermaidjs diagram-source-mermaid\"><pre class=\"mermaid\">sequenceDiagram\n    participant AM as App Manager\n    participant LP as libpackage (RalfPackageImpl)\n    participant FS as Filesystem\n    participant RL as libralf\n\n    AM->>LP: IPackageImpl::instance()\n    AM->>LP: Initialize(configStr, configMetadata)\n\n    LP->>FS: getpwnam(\"ralf\") \u2014 resolve UID\/GID\n    FS-->>LP: UID \/ GID\n\n    LP->>FS: Iterate RDK_PACKAGE_CERT_PATH\n    loop Per certificate file\n        LP->>RL: Certificate::loadFromFile(certPath)\n        RL-->>LP: Certificate added to VerificationBundle\n    end\n\n    LP->>FS: Check \/ create DAC_APP_PATH\n    LP->>FS: Recursive scan for package.ralf files\n    FS-->>LP: Installed package paths\n\n    LP-->>AM: Initialize() returns SUCCESS\n    note over LP: mIsInitialized = true<\/pre><\/div>\n\n\n\n<h4 class=\"wp-block-heading\">Runtime State Changes<\/h4>\n\n\n\n<p>Once active, <code>libpackage<\/code> responds exclusively to direct API calls. Its internal state evolves only through those calls: the <code>mInstalledPackages<\/code> list grows on <code>Install()<\/code>. <code>Uninstall()<\/code> removes package files from <code>DAC_APP_PATH<\/code> but does not currently remove entries from <code>mInstalledPackages<\/code>, and the <code>mMountedPackages<\/code> map grows on <code>Lock()<\/code> and shrinks on <code>Unlock()<\/code>.<\/p>\n\n\n\n<p><strong>State Change Triggers:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>Install()<\/code> called with a valid, verified package causes the package to be added to <code>mInstalledPackages<\/code> and its file to be copied to <code>DAC_APP_PATH<\/code>.<\/li>\n\n\n\n<li><code>Lock()<\/code> called for an already-mounted package increments that package&#8217;s mount count rather than performing a new mount, ensuring idempotent behaviour for repeated lock calls for the same app.<\/li>\n\n\n\n<li><code>Uninstall()<\/code> removes the package files from <code>DAC_APP_PATH<\/code>. When a package has active mounts, <code>Unlock()<\/code> should be called prior to <code>Uninstall()<\/code> to cleanly release the mount.<\/li>\n<\/ul>\n\n\n\n<p><strong>Context Switching Scenarios:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>A second call to <code>Initialize()<\/code> on the same instance triggers the full setup sequence again, reloading user\/group and certificate information.<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">Call Flows<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">Initialization Call Flow<\/h4>\n\n\n\n<div class=\"wp-block-merpress-mermaidjs diagram-source-mermaid\"><pre class=\"mermaid\">sequenceDiagram\n    participant AM as App Manager\n    participant LP as libpackage (RalfPackageImpl)\n    participant FS as Filesystem\n    participant RL as libralf\n\n    AM->>LP: Initialize(configStr, configMetadata)\n    LP->>FS: getpwnam(\"ralf\")\n    FS-->>LP: UID \/ GID resolved\n    LP->>FS: Iterate certificate directory (RDK_PACKAGE_CERT_PATH)\n    loop Per certificate file\n        LP->>RL: Certificate::loadFromFile()\n        RL-->>LP: Certificate loaded into VerificationBundle\n    end\n    LP->>FS: Check \/ create DAC_APP_PATH\n    LP->>FS: Recursive scan for package.ralf\n    loop Per installed package\n        LP->>LP: Extract appId and version from directory path\n        LP->>AM: Populate configMetadata entry\n    end\n    LP-->>AM: Result::SUCCESS<\/pre><\/div>\n\n\n\n<h4 class=\"wp-block-heading\">Request Processing Call Flow<\/h4>\n\n\n\n<p>The Lock operation is the most representative call flow, as it combines package opening, dependency resolution, recursive mounting, config extraction, and JSON serialisation into a single synchronous operation.<\/p>\n\n\n\n<p>When <code>Lock()<\/code> is called, the package file is opened and validated against the certificate bundle without performing full signature verification (full verification is deferred to explicit <code>verify()<\/code> calls at install time and during the lock mount step). The <code>lockPackage()<\/code> function then recurses into each declared dependency \u2014 opening, mounting, and reference-counting each \u2014 before mounting the requested package itself. On completion, the full list of mounted packages and their metadata paths is serialised to a temporary JSON file, whose path is returned via <code>configMetadata.ralfPkgPath<\/code>.<\/p>\n\n\n\n<div class=\"wp-block-merpress-mermaidjs diagram-source-mermaid\"><pre class=\"mermaid\">sequenceDiagram\n    participant AM as App Manager\n    participant LP as libpackage (RalfPackageImpl)\n    participant RL as libralf\n    participant FS as Filesystem\n\n    AM->>LP: Lock(packageId, version, unpackedPath, configMetadata, additionalLocks)\n    LP->>FS: Locate DAC_APP_PATH\/packageId\/version\/package.ralf\n    LP->>RL: Package::open(packagePath, verificationBundle)\n    RL-->>LP: Package object\n\n    LP->>LP: lockPackage() \u2014 read metadata, get dependencies\n    loop Per dependency (recursive)\n        LP->>LP: identifyDependencyVersion()\n        LP->>RL: Package::open(depPackagePath, verificationBundle)\n        LP->>RL: Package::verify()\n        RL-->>LP: Verification result\n        LP->>FS: Create mount directory (\/tmp\/mounts\/depId_ver\/rootfs)\n        LP->>RL: Package::mount(mountPath)\n        RL-->>LP: PackageMount object\n        LP->>FS: Write config.json to mount directory\n        LP->>LP: Store in mMountedPackages (or increment mountCount)\n    end\n\n    LP->>RL: Package::verify() \u2014 main package\n    LP->>RL: Package::mount(mountPath)\n    RL-->>LP: PackageMount object\n    LP->>FS: Write config.json\n    LP->>FS: Serialize mount list to temp JSON (pkgId_ver_metadata.json)\n    LP-->>AM: Lock() returns SUCCESS + unpackedPath + configMetadata.ralfPkgPath<\/pre><\/div>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Internal Modules<\/h2>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Module \/ Class<\/th><th>Description<\/th><th>Key Files<\/th><\/tr><\/thead><tbody><tr><td><code>RalfPackageImpl<\/code><\/td><td>Primary implementation class. Implements all six <code>IPackageImpl<\/code> operations. Owns the verification bundle, the installed-package list, and the mounted-package map. Receives package file paths and serialised configuration strings from the app management layer.<\/td><td><code>RalfPackageHandler.cpp<\/code>, <code>RalfPackageImpl.h<\/code><\/td><\/tr><tr><td><code>IPackageImpl::instance()<\/code><\/td><td>Factory function that constructs and returns a <code>std::shared_ptr&lt;IPackageImpl&gt;<\/code> pointing to a new <code>RalfPackageImpl<\/code>. Acts as the sole entry point for callers obtaining a library instance.<\/td><td><code>RalfPackageHandler.cpp<\/code><\/td><\/tr><tr><td><code>MountedPackageInfo<\/code><\/td><td>Internal bookkeeping structure. Holds the <code>ralf::PackageMount<\/code> RAII object, the path to the extracted <code>config.json<\/code>, and a reference count for tracking how many concurrent locks hold a given package mounted.<\/td><td><code>RalfPackageImpl.h<\/code><\/td><\/tr><tr><td><code>RalfPackageInfo<\/code><\/td><td>Plain data structure used during a lock operation to accumulate the mount path and metadata JSON path for each package in the dependency tree before they are serialised to the output JSON file.<\/td><td><code>RalfPackageImpl.h<\/code><\/td><\/tr><tr><td><code>PackageImplTestApp<\/code><\/td><td>Interactive command-line test utility that exercises all <code>IPackageImpl<\/code> operations. Built only when <code>BUILD_TEST_APP=ON<\/code>. Not included in the production library.<\/td><td><code>PackageImplTestApp.cpp<\/code><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Component Interactions<\/h2>\n\n\n\n<p>All interactions are in-process: the app management layer invokes library operations through the <code>IPackageImpl<\/code> interface, and <code>libpackage<\/code> in turn calls <code>libralf<\/code> and <code>jsoncpp<\/code> as direct shared-library dependencies.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Interaction Matrix<\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Target Component \/ Layer<\/th><th>Interaction Purpose<\/th><th>Key APIs<\/th><\/tr><\/thead><tbody><tr><td><strong>Libraries<\/strong><\/td><td><\/td><td><\/td><\/tr><tr><td><code>libralf<\/code><\/td><td>Open, verify, mount, and read metadata from RALF package archives; load X.509 certificates for the verification bundle<\/td><td><code>Package::open()<\/code>, <code>Package::verify()<\/code>, <code>Package::mount()<\/code>, <code>Package::metaData()<\/code>, <code>PackageMount::isMounted()<\/code>, <code>PackageMount::unmount()<\/code>, <code>Certificate::loadFromFile()<\/code>, <code>VersionNumber::fromString()<\/code>, <code>VersionConstraint::isSatisfiedBy()<\/code><\/td><\/tr><tr><td><code>jsoncpp<\/code><\/td><td>Serialise the list of mounted packages (mount paths and metadata paths) to a JSON file<\/td><td><code>Json::Value<\/code>, <code>Json::arrayValue<\/code>, <code>Value::toStyledString()<\/code><\/td><\/tr><tr><td><strong>Filesystem<\/strong><\/td><td><\/td><td><\/td><\/tr><tr><td><code>DAC_APP_PATH<\/code><\/td><td>Persistent storage for installed RALF package files; enumerated on <code>Initialize()<\/code><\/td><td><code>std::filesystem::copy_file()<\/code>, <code>create_directories()<\/code>, <code>remove_all()<\/code>, <code>recursive_directory_iterator()<\/code><\/td><\/tr><tr><td><code>\/tmp\/mounts\/<\/code><\/td><td>Transient mount points for locked packages and their dependencies<\/td><td><code>std::filesystem::create_directories()<\/code><\/td><\/tr><tr><td><code>RDK_PACKAGE_CERT_PATH<\/code><\/td><td>Certificate store read at initialisation to build the <code>VerificationBundle<\/code><\/td><td><code>std::filesystem::directory_iterator()<\/code>, <code>Certificate::loadFromFile()<\/code><\/td><\/tr><tr><td><strong>POSIX System<\/strong><\/td><td><\/td><td><\/td><\/tr><tr><td>User\/group lookup<\/td><td>Resolve the UID and GID of the package-management user to set ownership on installed and mounted package directories<\/td><td><code>getpwnam()<\/code><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">IPC Flow Patterns<\/h3>\n\n\n\n<p>The app management layer accesses <code>libpackage<\/code> through direct in-process function calls via the <code>IPackageImpl<\/code> interface obtained from <code>IPackageImpl::instance()<\/code>.<\/p>\n\n\n\n<p><strong>Primary Request \/ Response Flow:<\/strong><\/p>\n\n\n\n<p>All operations follow a synchronous call-and-return pattern. The app management layer calls an <code>IPackageImpl<\/code> method, which executes synchronously (including any <code>libralf<\/code> calls and filesystem operations) and returns a <code>Result<\/code> enum (<code>SUCCESS<\/code> or <code>FAILED<\/code>) directly to the caller.<\/p>\n\n\n\n<div class=\"wp-block-merpress-mermaidjs diagram-source-mermaid\"><pre class=\"mermaid\">sequenceDiagram\n    participant AM as App Manager\n    participant LP as libpackage (RalfPackageImpl)\n    participant RL as libralf\n    participant FS as Filesystem\n\n    AM->>LP: IPackageImpl method call (Install \/ Lock \/ Unlock \/ Uninstall \/ GetFileMetadata)\n    LP->>RL: libralf API call (open \/ verify \/ mount \/ metaData)\n    RL-->>LP: Result\n    LP->>FS: Filesystem operation (read \/ write \/ copy \/ remove)\n    FS-->>LP: Result\n    LP-->>AM: Result::SUCCESS or Result::FAILED<\/pre><\/div>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Implementation Details<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Major HAL APIs Integration<\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>HAL \/ Library API<\/th><th>Purpose<\/th><th>Implementation File<\/th><\/tr><\/thead><tbody><tr><td><code>ralf::Package::open()<\/code><\/td><td>Parse a <code>.ralf<\/code> package archive, validate its certificate against the verification bundle (with expiry check), and return a <code>Package<\/code> object<\/td><td><code>RalfPackageHandler.cpp<\/code><\/td><\/tr><tr><td><code>ralf::Package::verify()<\/code><\/td><td>Perform full cryptographic signature verification on an opened package<\/td><td><code>RalfPackageHandler.cpp<\/code><\/td><\/tr><tr><td><code>ralf::Package::mount()<\/code><\/td><td>Mount the package&#8217;s rootfs archive into a specified directory path<\/td><td><code>RalfPackageHandler.cpp<\/code><\/td><\/tr><tr><td><code>ralf::Package::metaData()<\/code><\/td><td>Read the embedded <code>PackageMetaData<\/code> from the package, which includes declared dependencies, package type, and application permissions<\/td><td><code>RalfPackageHandler.cpp<\/code><\/td><\/tr><tr><td><code>ralf::Package::auxMetaDataFile()<\/code><\/td><td>Extract the embedded auxiliary metadata file matching a given MIME type (<code>application\/vnd.rdk.package.config.v1+json<\/code>)<\/td><td><code>RalfPackageHandler.cpp<\/code><\/td><\/tr><tr><td><code>ralf::PackageMount::isMounted()<\/code><\/td><td>Query whether a <code>PackageMount<\/code> instance&#8217;s filesystem mount is still active<\/td><td><code>RalfPackageHandler.cpp<\/code><\/td><\/tr><tr><td><code>ralf::PackageMount::unmount()<\/code><\/td><td>Tear down the filesystem mount associated with a <code>PackageMount<\/code> instance<\/td><td><code>RalfPackageHandler.cpp<\/code><\/td><\/tr><tr><td><code>ralf::Certificate::loadFromFile()<\/code><\/td><td>Load an X.509 certificate from a filesystem path and return it for addition to the <code>VerificationBundle<\/code><\/td><td><code>RalfPackageHandler.cpp<\/code><\/td><\/tr><tr><td><code>ralf::VersionNumber::fromString()<\/code><\/td><td>Parse a version string into a structured <code>VersionNumber<\/code> for comparison<\/td><td><code>RalfPackageHandler.cpp<\/code><\/td><\/tr><tr><td><code>ralf::VersionConstraint::isSatisfiedBy()<\/code><\/td><td>Evaluate whether an installed package&#8217;s version number satisfies a dependency&#8217;s declared version constraint<\/td><td><code>RalfPackageHandler.cpp<\/code><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Key Implementation Logic<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>State \/ Lifecycle Management<\/strong>: The <code>mIsInitialized<\/code> boolean in <code>RalfPackageImpl<\/code> acts as the sole lifecycle guard. All five non-<code>Initialize<\/code> operations check it at entry and return <code>Result::FAILED<\/code> immediately if <code>false<\/code>. State transition logic is confined to <code>Initialize()<\/code> in <code>RalfPackageHandler.cpp<\/code>.<\/li>\n\n\n\n<li>Core implementation: <code>RalfPackageHandler.cpp<\/code><\/li>\n\n\n\n<li><strong>Error Handling Strategy<\/strong>: Errors from <code>libralf<\/code> (returned as <code>ralf::Result<\/code> types with embedded <code>ralf::Error<\/code>) are checked at each call site via the <code>bool<\/code> conversion of the result object. On failure, the specific error message is extracted via <code>.error().what()<\/code> and logged to <code>std::cerr<\/code> with the <code>[libPackage]<\/code> prefix before returning <code>Result::FAILED<\/code> or <code>false<\/code> to the caller. Filesystem errors from <code>std::filesystem<\/code> operations are caught as <code>std::filesystem::filesystem_error<\/code> exceptions in <code>Install()<\/code> and <code>Uninstall()<\/code> and translated to <code>Result::FAILED<\/code>. No retry logic is present; all failures are terminal for that operation.<\/li>\n\n\n\n<li><strong>Logging &amp; Diagnostics<\/strong>: All log output is written to <code>std::cout<\/code> (informational) or <code>std::cerr<\/code> (errors and warnings) using the <code>[libPackage]<\/code> prefix. The build revision string injected via the <code>BUILD_REFERENCE<\/code> compile-time define is logged to <code>std::cout<\/code> at construction time. Dependency check operations are additionally tagged with <code>[DEPENDENCY_CHECK]<\/code>, and mount failures with <code>[RALFMOUNT]<\/code>, to aid log filtering.<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Configuration<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Key Configuration Parameters<\/h3>\n\n\n\n<p>All configuration parameters are compile-time constants injected as preprocessor definitions. They cannot be changed at runtime without rebuilding the library.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Parameter<\/th><th>Type<\/th><th>Default<\/th><th>Description<\/th><\/tr><\/thead><tbody><tr><td><code>DAC_APP_PATH<\/code><\/td><td>string (filesystem path)<\/td><td><code>\/opt\/media\/apps\/<\/code><\/td><td>Root directory under which DAC application packages are installed. Created if absent on <code>Initialize()<\/code>.<\/td><\/tr><tr><td><code>RDK_PACKAGE_CERT_PATH<\/code><\/td><td>string (filesystem path)<\/td><td><code>\/etc\/rdk\/certs<\/code><\/td><td>Directory from which signing certificates are loaded to build the package <code>VerificationBundle<\/code> used for all package open and verification operations.<\/td><\/tr><tr><td><code>DISABLE_DEPENDENCY_CHECK<\/code><\/td><td>bool (compile flag)<\/td><td><code>false<\/code> (check enabled)<\/td><td>When defined, sets <code>RalfPackageImpl::enableDependencyCheck<\/code> to <code>false<\/code>, causing <code>Install()<\/code> and <code>Lock()<\/code> to skip dependency resolution against the installed-package list.<\/td><\/tr><tr><td><code>BUILD_REFERENCE<\/code><\/td><td>string<\/td><td><code>\"undefined\"<\/code><\/td><td>Build revision identifier (populated from <code>SRCREV<\/code> by the Yocto recipe). Logged to <code>std::cout<\/code> at library construction time.<\/td><\/tr><tr><td><code>BUILD_TEST_APP<\/code><\/td><td>bool (cmake option)<\/td><td><code>OFF<\/code><\/td><td>When <code>ON<\/code>, the <code>PackageImplTestApp<\/code> interactive test executable is compiled and installed. Has no effect on the production <code>libPackage<\/code> shared library.<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Configuration Persistence<\/h3>\n\n\n\n<p>Installed DAC application package files are persisted on the filesystem under <code>DAC_APP_PATH\/{packageId}\/{version}\/package.ralf<\/code> and are re-discovered on each call to <code>Initialize()<\/code>. Mount directories under <code>\/tmp\/mounts\/<\/code> and temporary JSON metadata files written during <code>Lock()<\/code> are transient and re-created on each lock operation.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Libpackage is a shared library that implements the IPackageImpl interface, providing the package management abstraction [&hellip;]<\/p>\n","protected":false},"author":659,"featured_media":0,"parent":9844,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_bbp_topic_count":0,"_bbp_reply_count":0,"_bbp_total_topic_count":0,"_bbp_total_reply_count":0,"_bbp_voice_count":0,"_bbp_anonymous_reply_count":0,"_bbp_topic_count_hidden":0,"_bbp_reply_count_hidden":0,"_bbp_forum_subforum_count":0,"footnotes":""},"class_list":["post-13000","page","type-page","status-publish","hentry"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v24.9 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>libpackage - RDK Documentation Portal | Documentation<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/developer.rdkcentral.com\/documentation\/documentation\/rdk_video_documentation\/components\/libpackage\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"libpackage - RDK Documentation Portal | Documentation\" \/>\n<meta property=\"og:description\" content=\"Libpackage is a shared library that implements the IPackageImpl interface, providing the package management abstraction [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/developer.rdkcentral.com\/documentation\/documentation\/rdk_video_documentation\/components\/libpackage\/\" \/>\n<meta property=\"og:site_name\" content=\"RDK Documentation Portal | Documentation\" \/>\n<meta property=\"article:modified_time\" content=\"2026-08-03T07:32:42+00:00\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data1\" content=\"10 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/developer.rdkcentral.com\/documentation\/documentation\/rdk_video_documentation\/components\/libpackage\/\",\"url\":\"https:\/\/developer.rdkcentral.com\/documentation\/documentation\/rdk_video_documentation\/components\/libpackage\/\",\"name\":\"libpackage - RDK Documentation Portal | Documentation\",\"isPartOf\":{\"@id\":\"https:\/\/developer.rdkcentral.com\/documentation\/#website\"},\"datePublished\":\"2026-08-03T07:31:39+00:00\",\"dateModified\":\"2026-08-03T07:32:42+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/developer.rdkcentral.com\/documentation\/documentation\/rdk_video_documentation\/components\/libpackage\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/developer.rdkcentral.com\/documentation\/documentation\/rdk_video_documentation\/components\/libpackage\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/developer.rdkcentral.com\/documentation\/documentation\/rdk_video_documentation\/components\/libpackage\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/developer.rdkcentral.com\/documentation\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Documentation\",\"item\":\"https:\/\/developer.rdkcentral.com\/documentation\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"RDK Video\",\"item\":\"https:\/\/developer.rdkcentral.com\/documentation\/documentation\/rdk_video_documentation\/\"},{\"@type\":\"ListItem\",\"position\":4,\"name\":\"Components\",\"item\":\"https:\/\/developer.rdkcentral.com\/documentation\/documentation\/rdk_video_documentation\/components\/\"},{\"@type\":\"ListItem\",\"position\":5,\"name\":\"libpackage\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/developer.rdkcentral.com\/documentation\/#website\",\"url\":\"https:\/\/developer.rdkcentral.com\/documentation\/\",\"name\":\"RDK Documentation Portal | Documentation\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/developer.rdkcentral.com\/documentation\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"libpackage - RDK Documentation Portal | Documentation","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/developer.rdkcentral.com\/documentation\/documentation\/rdk_video_documentation\/components\/libpackage\/","og_locale":"en_US","og_type":"article","og_title":"libpackage - RDK Documentation Portal | Documentation","og_description":"Libpackage is a shared library that implements the IPackageImpl interface, providing the package management abstraction [&hellip;]","og_url":"https:\/\/developer.rdkcentral.com\/documentation\/documentation\/rdk_video_documentation\/components\/libpackage\/","og_site_name":"RDK Documentation Portal | Documentation","article_modified_time":"2026-08-03T07:32:42+00:00","twitter_card":"summary_large_image","twitter_misc":{"Est. reading time":"10 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/developer.rdkcentral.com\/documentation\/documentation\/rdk_video_documentation\/components\/libpackage\/","url":"https:\/\/developer.rdkcentral.com\/documentation\/documentation\/rdk_video_documentation\/components\/libpackage\/","name":"libpackage - RDK Documentation Portal | Documentation","isPartOf":{"@id":"https:\/\/developer.rdkcentral.com\/documentation\/#website"},"datePublished":"2026-08-03T07:31:39+00:00","dateModified":"2026-08-03T07:32:42+00:00","breadcrumb":{"@id":"https:\/\/developer.rdkcentral.com\/documentation\/documentation\/rdk_video_documentation\/components\/libpackage\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/developer.rdkcentral.com\/documentation\/documentation\/rdk_video_documentation\/components\/libpackage\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/developer.rdkcentral.com\/documentation\/documentation\/rdk_video_documentation\/components\/libpackage\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/developer.rdkcentral.com\/documentation\/"},{"@type":"ListItem","position":2,"name":"Documentation","item":"https:\/\/developer.rdkcentral.com\/documentation\/"},{"@type":"ListItem","position":3,"name":"RDK Video","item":"https:\/\/developer.rdkcentral.com\/documentation\/documentation\/rdk_video_documentation\/"},{"@type":"ListItem","position":4,"name":"Components","item":"https:\/\/developer.rdkcentral.com\/documentation\/documentation\/rdk_video_documentation\/components\/"},{"@type":"ListItem","position":5,"name":"libpackage"}]},{"@type":"WebSite","@id":"https:\/\/developer.rdkcentral.com\/documentation\/#website","url":"https:\/\/developer.rdkcentral.com\/documentation\/","name":"RDK Documentation Portal | Documentation","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/developer.rdkcentral.com\/documentation\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"}]}},"_links":{"self":[{"href":"https:\/\/developer.rdkcentral.com\/documentation\/wp-json\/wp\/v2\/pages\/13000","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/developer.rdkcentral.com\/documentation\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/developer.rdkcentral.com\/documentation\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/developer.rdkcentral.com\/documentation\/wp-json\/wp\/v2\/users\/659"}],"replies":[{"embeddable":true,"href":"https:\/\/developer.rdkcentral.com\/documentation\/wp-json\/wp\/v2\/comments?post=13000"}],"version-history":[{"count":1,"href":"https:\/\/developer.rdkcentral.com\/documentation\/wp-json\/wp\/v2\/pages\/13000\/revisions"}],"predecessor-version":[{"id":13001,"href":"https:\/\/developer.rdkcentral.com\/documentation\/wp-json\/wp\/v2\/pages\/13000\/revisions\/13001"}],"up":[{"embeddable":true,"href":"https:\/\/developer.rdkcentral.com\/documentation\/wp-json\/wp\/v2\/pages\/9844"}],"wp:attachment":[{"href":"https:\/\/developer.rdkcentral.com\/documentation\/wp-json\/wp\/v2\/media?parent=13000"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}