RDK Resources
[*RDK Preferred*]
Code Management Facility
RDK Forums
[RDK Conferences]
RDK Support
Archives
Papers & Presentations Archive
Infoexpand | ||
---|---|---|
| LISA : Local Inventory & Storage Manger of DAC Apps | |
|
LISA component is part of RDK DAC framework on STB . Its role is to retrieve, store and maintain DAC bundles and local applications' metadata. LISA is keeping track of what packages are available locally and managing the local storage, both for downloadable bundles as well as persistent storage for the applications. LISA is an abbreviation from for Local Inventory & Storage Manager of DAC Apps and it offers an API for . Its responsibility is:
...
Lisa is implemented as Thunder out-of-process plugin. Can be run in a separate container
...
...
LISA is an alternative to the Packager Thunder Plugin used to retrieve ipkg packages, see current git repo location : https://github.com/rdkcentral/rdkservices/blob/master/Packager/doc/PackagerPlugin.md
...
Yocto recipe location : https://code.rdkcentral.com/r/plugins/gitiles/components/generic/rdk-oe/meta-cmf-video/+/refs/heads/rdk-next/recipes-extended/rdkservices/rdkservice-lisa.bb
License : Apachev2
API of LISA is available in https://github.com/rdkcentral/ThunderInterfaces/blob/R2/interfaces/ILISA.h
More details on API design of LISA is available here. However it was somewhat over-engineered compared to what we need as Minimum Viable Product (MVP) and hence not all api's from design were implemented.
In next section you see what is implemented as MVP and beyond
Not everything of full design has been implemented in LISA code. Focus has been mainly on Minimum Viable Product
Everything marked in italic is implemented so far, text in grey is not implemented
use getMetadata {"type":"application/LISA", "id":"lisa.dac.confg", "version":"0"} API to learn the recommended "dacBundlePlatformNameOverride" & "dacBundleFirmwareCompatibilityKey" for this platform and "configUrl" as kickstart Url to learn ASMS url
During integration (and not part of the design) we decided to define a specific app_id "lisa.dac.config" of type "application/LISA" in LISA that can be used by resident UI to learn the default platform parameters it should use towards DAC cloud when requesting bundle_url for the particular platform it is running on. This is to learn the "dacBundlePlatformNameOverride" & "dacBundleFirmwareCompatibilityKey" platform parameters. There is also "configUrl" parameter Resident UI will use as kick start URL from which it will learn ASMS environment URL to use. see code in Resident UI that uses this
...
DEMO video of e2e DAC flow. You can see actions from LISA in log screen most below.
https://drive.google.com/file/d/11QXXM9WBg8Sw76Eikg5FyodrpIfoBnkL/view
...
DAC_AWC_LISA.mp4
drive.google.com
The refapp "resident App" that comes with RDK reference image uses lisa for downloading DAC bundles. It is a consumer of LISA api.
Here are pointers to its code on where/how it uses LISA
https://github.com/LibertyGlobal/refapp/search?q=LISA
...
...
Search · LISA · LibertyGlobal/refapp
Share refapp javascript code with RDK community. Contribute to LibertyGlobal/refapp development by creating an account on GitHub.
github.com
Demo video of that refapp in action, using LISA to download/store the Youtube/Cobalt DAC-Rialto app and run it
https://drive.google.com/file/d/1ipINJ-LlZBYEJvRUugoruaYO2sjQiraO/view
...
...
cobalt-7218c-2.mp4
drive.google.com
LISA is able to handle the following data:
current git repo location : https://github.com/stagingrdkm/LISA
TO DO : intention is to move over to github/rdkcentral/LISA in near future
Yocto recipe location : https://code.rdkcentral.com/r/plugins/gitiles/components/generic/rdk-oe/meta-cmf-videoopensource/RDK_apps/+/refs/heads/rdk-next/recipes-extended/rdkservices/rdkservice-lisa.bb
License : Apachev2
Before implementation, at the design stage, the following API in json schema has been defined LISA API .
In later design phase additional lock/unlock api allowing external application manager to signal LISA that a specific app from LISA database is in active use by End user and hence should not be deleted/upgraded at this moment, see description in LISA API Extension (Locking mechanism)#APISchema
Actual Thunder interface definition/api in defined in dual COM RPC / JSON- RPC interface in https://github.com/rdkcentral/ThunderInterfaces/blob/R2/interfaces/ILISA.h with annotations to automatically autogenerate* the JSON RPC api at build time
Below is description of expected api behaviour in expected use cases.
API to be exposed in JSON-RPC over WebSocket
Generic format (see with https://www.jsonrpc.org/specification and https://github.com/rdkcentral/rdkservices/blob/master/SystemServices/README.md):
Code Block | ||||
---|---|---|---|---|
| ||||
{"jsonrpc":"2.0","id":{id},"method":"com.lgi.dac.lisa.1.methodName", "params":{payload}} |
{id} - An identifier established by the Client that MUST contain a String, Number, or NULL value if included. If it is not included it is assumed to be a notification.
{payload} - A Structured value that holds the parameter values to be used during the invocation of the method. This member MAY be omitted.
Download the application bundle tarball from the given URL, unpack files to dedicated directory, create the db entries and persistent storage on success. Asynchronous operation, handle should be used for tracking the request. The id of an app is unique within the database. That means only one kind of (mime)type can be combined and saved with a specific app id.
Request payload: {"type":"application/vnd.rdk-app.dac.native", "id":"<string>", "version":"<string>", "url":"<string>", "appName":"<string>", "category":"<string>"}
Result payload: {"handle":"<string>"}
...
...
Uninstall the application: remove application files and - optionally - persistent storage and db entry. Non-blocking operation, handle should be used for tracking the request.
Request payload: {"type":"application/vnd.rdk-app.dac.native", "id":"<string>", "version":"<string>", "uninstallType":"<string>"}
Result payload: {"handle":"<string>"}
...
...
...
6.1.0/accelerator-home-ui/src/api/LISAApi.js#75 (see Jira RDKUI-649 and RDKUI-620 )
Video Accelerator is the default UI on the RDKM Video Accelerator.
There is UI section which allows you to install DAC apps from DAC cloud. It use LISA API to support this use case (and to getlist of installed DAC app at init time)
see code where LISA API is being used
see video with an explanation of how to use that UI
The refapp "resident App" that comes with RDK reference image uses LISA for installing/deleting DAC bundles.
Here are pointers to its code on where/how it uses LISA
https://github.com/LibertyGlobal/refapp/search?q=LISA
DEMO video of app installation from DAC cloud using cli tool. You can see in shell on button the logs of LISA in action.
LISA provides logical tree/directory structure for its various type of data to store as visualized in diagram below.
The logical storages: [APPS] and [APPS_STORAGE] are configurable per platform as part of LISA thunder plugin config.
draw.io Diagram | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
files of App in App oci bundle are stored in [APPS] storage.
Paths:
Important, LISA's sqlite database of Apps and metadata can be located there eg : [APPS]/dac/db/{epoch}/apps.db
Apps persistent storage is located in [APPS_STORAGE].
Paths:
Apps' persistent storage: [APPS_STORAGE]/dac/{epoch}/{id}/
Epoch indicator {epoch} is used for easy invalidation of not supported or revoked format of apps on fundamental changes. May also be used for the antirollback (db authentication - TBD?)
LISA is able to handle the following data:
Before implementation, at the design stage, the following API in json schema has been defined LISA API .
In later design phase additional lock/unlock api allowing external application manager to signal LISA that a specific app from LISA database is in active use by End user and hence should not be deleted/upgraded at this moment, see description in LISA API Extension (Locking mechanism)#APISchema
Actual Thunder interface definition/api is in defined in dual COM RPC / JSON- RPC interface in https://github.com/rdkcentral/ThunderInterfaces/blob/R2/interfaces/ILISA.h with annotations to automatically autogenerate* the JSON RPC api at build time
In section below we provide more explanation with the API methods.
API is to be exposed in JSON-RPC over WebSocket like other JSON-RPC thunder services
For mat is of style :
Code Block | ||||
---|---|---|---|---|
| ||||
{"jsonrpc":"2.0","id":{id},"method":"com.lgi.dac.lisa.1.methodName", "params":{payload}} |
{id} - An identifier established by the Client that MUST contain a String, Number, or NULL value if included. If it is not included it is assumed to be a notification.
{payload} - A Structured value that holds the parameter values to be used during the invocation of the method. This member MAY be omitted.
In many of below methods you need to enter "type" <string> of application you want do the method operation for. The only use case we defined for now is installing DAC apps, for that use type as defined in ASMS environment you are working against (that is what resident UI will do). in RDK ASMS instance this is "application/dac.native". (Note that in LG ASMS OneMW instance type "application/vnd.rdk-app.dac.native" is used for DAC apps)
Download the application bundle tarball from the given URL, unpack files to dedicated directory, create the db entries and persistent storage on success. Asynchronous operation, handle should be used for tracking the request. The id of an app is unique within the database. That means only one kind of (mime)type can be combined and saved with a specific app id.
Download arbitrary application's resource, e.g. icon. Resource are stored per application id/version. Asynchronous operation, handle should be used for tracking the request. If the resource of given resKey already exists it is replaced by the newly downloaded resource. If the resKey is unique, but the requested resource file already exists on the filesystem, the file should be stored under a different, unique filename, created by appending a suffix to the existing filename.
Request payload: {"type":"application/vnd.rdk-app.dac.native", "id":"<string>", "version":"<string>", "resKey":"<string>", "url":"<string>"}
Result payload: {"handle":"<string>"}
...
...
...
Deletes the content of the database and/or persistent storage and/or all resources for the application. Synchronous operation, returns response on success or failure. Optional parameters type, id, version are used to filter the applications on which the reset will be performed. If they are not given, the reset operation affects all the data. Synchronous operation, returns a response on success or failure.
Request payload: {"type":"application/vnd.rdk-app.dac.native<string>", "id":"<string>", "version":"<string>", "resetTypeurl":"<string>", "appName":"<string>", "category":"<string>"}
As per above comment "type" in RDKM environment will be "application/dac.native"
Result Response payload: {"statushandle":"<string>"}
parameter and errors | values |
---|
errors |
|
|
|
Returns information on the storage usage. Depending on provided parameters: overall storage usage, application id storage or application id/version storage. Synchronous operation, returns a response on success or failure. Notes on implementation:
Request payload: {"type":"application/vnd.rdk-app.dac.native", "id":"<string>", "version":"<string>"}
Result payload: {"storage":"<storagePayload>"}
handle | handle to refer with the following requests |
Uninstall the application: remove application files and - optionally - persistent storage and db entry. Non-blocking operation, handle should be used for tracking the request.
Request payload: {"type":"<string>", "id":"<string>", "version":"<string>", "uninstallType":"<string>"}
Result payload: {"handle":"<string>"}
parameters and errors | values |
---|---|
uninstallType |
|
errors |
|
handle | handle to refer with the following requests |
Download arbitrary application's resource, e.g. icon. Resource are stored per application id/version. Asynchronous operation, handle should be used for tracking the request. If the resource of given resKey already exists it is replaced by the newly downloaded resource. If the resKey is unique, but the requested resource file already exists on the filesystem, the file should be stored under a different, unique filename, created by appending a suffix to the existing filename.
Request payload: {"type":"<string>", "id":"<string>", "version":"<string>", "resKey":"<string>", "url":"<string>"}
Result payload: {"handle":"<string>"}
parameters and errors | values |
---|---|
resKey |
|
errors |
|
|
handle | handle to refer with the following requests |
Deletes the content of the database and/or persistent storage and/or all resources for the application. Synchronous operation, returns response on success or failure. Optional parameters type, id, version are used to filter the applications on which the reset will be performed. If they are not given, the reset operation affects all the data. Synchronous operation, returns a response on success or failure.
Request payload: {"type":"application/vnd.rdk-app.dac.native", "id":"<string>", "
...
version":"<string>"
...
, "
...
resetType":
...
"
...
<string>"}
Response payload: {"
...
status"
...
:"<string>"
...
Returns a list of installed applications filtered using optional filtering criteria: type, id, version, appName, category. Synchronous operation, returns a response on success or failure.
Request payload: {"type":"application/vnd.rdk-app.dac.native", "id":"<string>", "version":"<string>","appName":"<string>","category":"<string>"}
Resultpayload: {"apps":"<appsPayload>"}
}
parameters and errors | values |
---|---|
version |
|
resetType |
|
errors |
|
Returns information on the storage usage. Depending on provided parameters: overall storage usage, application id storage or application id/version storage. Synchronous operation, returns a response on success or failure. Notes on implementation:
Request payload: {"type":"application/vnd.rdk-app.dac.native", "id":"<string>", "version":"<string>"}
Result payload: {"storage":"<storagePayload>"}
parameters and errors | values | ||
---|---|---|---|
type |
| ||
parameters and errors | values | ||
type |
| ||
id |
| ||
version |
| appName |
|
category |
| ||
| |||
errorsstatus |
| ||
appsPayloadstoragePayload | {"apps":["app":{"typepath":"<string>", "idquotaKB":"<string>", "installedusedKB":[{"version<string>":}, "<string>persistent", :{"appNamepath":"<string>", "categoryquotaKB":"<string>", "urlusedKB":"<string>"}]}]}
|
Set an arbitrary key: value metadata for a given application. The existing metadata object is replaced (overwritten) by the provided object. Synchronous operation, returns a response on success or failure.
Returns a list of installed applications filtered using optional filtering criteria: type, id, version, appName, category. Synchronous operation, returns a response on success or failure.
Request payload: {"type":"<string>Request payload: {"type":"application/vnd.rdk-app.dac.native", "id":"<string>", "version":"<string>","appName":"<string>","auxMetadatacategory":<auxMetadataPayload>"<string>"}
Result payloadResultpayload: {"apps":"<appsPayload>"}
parameters and errors | values |
---|---|
errors |
|
auxMetadataPayload | [{"<string>":"<string>"}] |
Get all metadata stored for given application version. Synchronous operation, returns a response on success or failure.
Request payload: {"type":"application/vnd.rdk-app.dac.native", "id":"<string>", "version":"<string>"}
Response payload: {"status":"<string>","metadata":}
...
type |
|
id |
|
version |
|
appName |
|
category |
|
status | |
parameters and errors | values |
---|---|
errors |
|
metadataPayloadappsPayload | {"appNameapps":["<string>app", :{"categorytype":"<string>", "urlid":"<string>", "resourcesinstalled":[{"<string>version":"<string>"}]}, "auxMetadataappName":<auxMetadataPayload>} "resources" - array referring downloaded resources; contains "resKey"<string>", "category":" file name" mappings |
Cancel previous asynchronous request.
<string>","url":"<string>"} |
...
Response payload: {"status":"<string>"}
...
...
]}]}
|
Set an arbitrary key+value metadata for a given application. The existing metadata key is replaced (overwritten) by the provided key/value pair. Synchronous operation, returns a response on success or failure.
Request payload: {"type":"application/vnd.rdk-app.dac.native", "id":"<string>", "version
Get estimated progress of an asynchronous operation.
Request payload: {"handle":"<string>"}
Response payload: {"status":"<string>", "progress":<number>"key":<string>,"value":<string>}
Result payload: {}
parameters and errors | values |
---|---|
handle |
|
status |
|
progress |
|
Notification sent on the completion of asynchronous operation.
errors |
|
Get all metadata stored for given application version. Synchronous operation, returns a response on success or failure.
Request payload: {"typepayload: {"handle":"<string>", "statusid":"<string>", "detailsversion":"<string>"}
...
...
...
Response payload: {"status":"<string>","metadata":}
parameters and errors | values |
---|---|
errors |
|
metadataPayload | {"appName":"<string>", "category":"<string>","url":"<string>","resources":[{"<string>":"<string>"}]},"auxMetadata":<auxMetadataPayload>}
|
Cancel previous asynchronous request.
Request payload: {"handle":"<string>"}
Response payload: {"status":"<string>"}
parameters and errors | values |
---|---|
handle |
|
errors |
|
Get estimated progress of an asynchronous operation.
Request payload: {"handle":"<string>"}
Response payload: {"status":"<string>", "progress":<number>}
parameters and errors | values |
---|---|
handle |
|
status |
|
progress |
|
Notification sent on the completion of asynchronous operation.
payload: {"handle":"<string>", "status":"<string>", "details":"<string>"}
parameters and errors | values |
---|---|
handle |
|
status |
|
details |
|
LISA is an alternative to the Packager Thunder Plugin used to retrieve ipkg packages, see https://github.com/rdkcentral/rdkservices/blob/master/Packager/doc/PackagerPlugin.md
Existing Packager API (RDK services github) | Proposed Packager API (DAC RDK wiki) | LISA API |
---|---|---|
install (package, version, architecture) | install (id, type, URL, token, listener) → (id, task, success) | install (type, id, version, URL, appName, category), → (status, handle) |
remove (id, listener) → (id, task, success) | uninstall (type, id, version, uninstallType), → (status, handle) | |
operationStatus→ (handle, status, details) | ||
cancel (task, listener) → (success) | cancel (handle) → (status) | |
isInstalled (id) → (success) | - | |
getInstallProgress (task) → ( percent) | getProgress (handle) → (status, percent) | |
getInstalled() → (applications) | getList (filter) → (array of {type, id, version, metadata}) | |
getPackageInfo(id) → (metadata) | getMetadata(type, id, version) → (metadata) | |
- | setMetadata(type, id, version, tag, metadata) | |
getAvaialbleSpace() → (space) | getStorageDetails() → (path, quota, size, persistentStoragePath, persistentStorageQuota, persistentStorageSize) | |
synchronize() | - |
Tracking of the download progress is implemented using:
draw.io Diagram | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
(is not IMPLEMENTED, was not required for MVP since bundles are encrypted and signed)
API to be implemented by the library:
draw.io Diagram | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
Note:
The 2 tables in the db schema (apps and installed_apps) are required to be able to correctly handle the case when the application is uninstalled, deleted because of corruption, deleted because of storage capacity issue, or not installed locally (launched from the cloud) but operator or user wants to keep persistent storage of given application intact (for later usage). In this case, an entry in apps table keeps tracking the persistent storage without introducing any other dirty hacks. This approach will also be useful for managing remote applications, for which we don't need to maintain the application's locally downloaded files, but persistent storage might be needed.
Code Block | ||||
---|---|---|---|---|
| ||||
-- enable support for foreign keys, available since sqlite version 3.6.19 (2009-10-14)
PRAGMA foreign_keys = ON;
-- table for application ids and persistent storage
CREATE TABLE IF NOT EXISTS apps(
idx INTEGER PRIMARY KEY, -- unique index for the application type/id
type TEXT NOT NULL, -- MIME type
app_id TEXT UNIQUE NOT NULL, -- unique id of app within given MIME type
data_path TEXT, -- path to app peristent storage, relative to [APPS_STORAGE]/{epoch}
created TEXT NOT NULL -- unix epoch timestamp of when the application entry was created
);
-- table for installed applications in specific versions
CREATE TABLE IF NOT EXISTS installed_apps (
idx INTEGER PRIMARY KEY, -- unique index for the application type/id/version
app_idx INTEGER NOT NULL, -- reference to apps table, index of the application type/id
version TEXT NOT NULL, -- version of the application
name TEXT NOT NULL, -- name of the application
category TEXT, -- category
url TEXT, -- URL from which the application was downloaded
app_path TEXT, -- path to app files, realtive to [APPS]/{epoch}
created TEXT NOT NULL, -- unix epoch timestamp of when the application was installed
resources TEXT, -- json object with downloaded resources metadata
metadata TEXT, -- json object with auxiliary resources metadata
FOREIGN KEY(app_idx) REFERENCES apps(idx),
UNIQUE(app_idx, version)
);
|
1. print tables
SELECT sql FROM sqlite_master WHERE name = 'apps';
SELECT sql FROM sqlite_master WHERE name = 'installed_apps';
2. insert app id
INSERT INTO apps VALUES(NULL, 'application/vnd.rdk-app.dac.native', 'com.lgi.app3', 'dac.native/com.lgi.app3/data', strftime('%s','now'));
3. get app_id of given app
SELECT idx,type,app_id FROM apps WHERE type = 'application/vnd.rdk-app.dac.native' AND app_id = 'com.lgi.app3';
4. insert new application version
INSERT INTO installed_apps VALUES(NULL, <app_idx>, '1.0.0', 'Super-app', 'Game', 'http://download.com/bundle1.tgz', 'dac.native/com.lgi.app3/1.0.0/app', strftime('%s','now'), NULL, NULL, NULL);
5. SELECT app version
SELECT DISTINCT apps.type,apps.app_id,installed_apps.version,installed_apps.metadata FROM installed_apps,apps WHERE apps.type='application/vnd.rdk-app.dac.native' AND apps.app_id='com.lgi.app3' AND installed_apps.version="1.0.0";
6. set meatdata for given app/version
SELECT DISTINCT installed_apps.idx,installed_apps.metadata FROM installed_apps,apps WHERE apps.type='application/vnd.rdk-app.dac.native' AND apps.app_id='com.lgi.app3' AND installed_apps.version="1.0.0";
UPDATE installed_apps SET metadata = '{[{"description","New nice application."},{"parental":"5"}]}' WHERE idx=<idx>;
draw.io Diagram | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
draw.io Diagram | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
draw.io Diagram | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
draw.io Diagram | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
draw.io Diagram | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
Code Block | ||||
---|---|---|---|---|
| ||||
{
"$schema": "plugin.schema.json",
"jsonrpc":"2.0",
"info": {
"title": "Local Inventory & Storage Manager of DAC Apps (LISA) Plugin",
"class": "Lisa",
"callsign": "org.rdk.dac.lisa",
"locator": "libWPEFrameworkLisa.so",
"status": "alpha",
"autostart": true,
"description": "The Local Inventory & Storage Manager of DAC Apps (LISA) plugin allows authenticated downloading and management of DAC bundles from a remote server. It also manages the persistent storage of the DAC applications.",
"version": "1.0"
},
"interface": {
"$ref": "{interfacedir}/lisa.json#"
},
"configuration": {
"type": "object",
"properties": {
"configuration": {
"type": "object",
"properties": {
"network": {
"type": "object",
"required": [
"timeout",
"default_retryIn"
],
"properties": {
"timeout": {
"type": "number",
"description": "Single resource downloading timeout in seconds"
},
"default_retryIn": {
"type": "number",
"description": "Default value of GET retry delay in seconds on HTTP/202, when no "Retry-After" header field is returned in the response."
}
}
},
"storages": {
"type": "object",
"required": [
"apps",
"apps_storage",
"apps_tmp"
],
"properties": {
"apps": {
"type": "string",
"description": "Path to the persistent storage for downloaded applications top dir"
},
"apps_storage": {
"type": "string",
"description": "Path to the persistent storage for downloaded applications persistent storage top dir"
},
"apps_tmp": {
"type": "string",
"description": "Path to the temporary storage for applications being downloaded"
}
}
}
},
"required": [
"timeout",
"storages"
]
}
}
}
}
|
Code Block | ||||
---|---|---|---|---|
| ||||
{
"$schema": "plugin.schema.json",
"jsonrpc":"2.0",
"info": {
"title": "Local Inventory & Storage Manager of DAC Apps (LISA) Plugin",
"class": "Lisa",
"callsign": "org.rdk.dac.lisa",
"locator": "libWPEFrameworkLisa.so",
"status": "alpha",
"autostart": true,
"description": [
"The Local Inventory & Storage Manager of DAC Apps (LISA) plugin allows authenticated downloading and management of DAC bundles from a remote server. It also manages the persistent storage of the DAC applications."
],
"version": "1.0"
},
"interface": {
"$ref": "{interfacedir}/lisa.json"
},
"configuration": {
"storages": {
"apps": "/mnt/apps",
"apps_storage": "/mnt/apps_storage",
"apps_tmp": "/mnt/apps_tmp"
},
"network": {
"timeout": 1800,
"default_retryIn": 300
}
}
} |
Tracking of the download progress is implemented using:
...
API to be implemented by the library:
...
Note:
The 2 tables in the db schema (apps and installed_apps) are required to be able to correctly handle the case when the application is uninstalled, deleted because of corruption, deleted because of storage capacity issue, or not installed locally (launched from the cloud) but operator or user wants to keep persistent storage of given application intact (for later usage). In this case, an entry in apps table keeps tracking the persistent storage without introducing any other dirty hacks. This approach will also be useful for managing remote applications, for which we don't need to maintain the application's locally downloaded files, but persistent storage might be needed.
Code Block | ||||
---|---|---|---|---|
| ||||
-- enable support for foreign keys, available since sqlite version 3.6.19 (2009-10-14)
PRAGMA foreign_keys = ON;
-- table for application ids and persistent storage
CREATE TABLE IF NOT EXISTS apps(
idx INTEGER PRIMARY KEY, -- unique index for the application type/id
type TEXT NOT NULL, -- MIME type
app_id TEXT UNIQUE NOT NULL, -- unique id of app within given MIME type
data_path TEXT, -- path to app peristent storage, relative to [APPS_STORAGE]/{epoch}
created TEXT NOT NULL -- unix epoch timestamp of when the application entry was created
);
-- table for installed applications in specific versions
CREATE TABLE IF NOT EXISTS installed_apps (
idx INTEGER PRIMARY KEY, -- unique index for the application type/id/version
app_idx INTEGER NOT NULL, -- reference to apps table, index of the application type/id
version TEXT NOT NULL, -- version of the application
name TEXT NOT NULL, -- name of the application
category TEXT, -- category
url TEXT, -- URL from which the application was downloaded
app_path TEXT, -- path to app files, realtive to [APPS]/{epoch}
created TEXT NOT NULL, -- unix epoch timestamp of when the application was installed
resources TEXT, -- json object with downloaded resources metadata
metadata TEXT, -- json object with auxiliary resources metadata
FOREIGN KEY(app_idx) REFERENCES apps(idx),
UNIQUE(app_idx, version)
);
|
1. print tables
SELECT sql FROM sqlite_master WHERE name = 'apps';
SELECT sql FROM sqlite_master WHERE name = 'installed_apps';
2. insert app id
INSERT INTO apps VALUES(NULL, 'application/vnd.rdk-app.dac.native', 'com.lgi.app3', 'dac.native/com.lgi.app3/data', strftime('%s','now'));
3. get app_id of given app
SELECT idx,type,app_id FROM apps WHERE type = 'application/vnd.rdk-app.dac.native' AND app_id = 'com.lgi.app3';
4. insert new application version
INSERT INTO installed_apps VALUES(NULL, <app_idx>, '1.0.0', 'Super-app', 'Game', 'http://download.com/bundle1.tgz', 'dac.native/com.lgi.app3/1.0.0/app', strftime('%s','now'), NULL, NULL, NULL);
5. SELECT app version
SELECT DISTINCT apps.type,apps.app_id,installed_apps.version,installed_apps.metadata FROM installed_apps,apps WHERE apps.type='application/vnd.rdk-app.dac.native' AND apps.app_id='com.lgi.app3' AND installed_apps.version="1.0.0";
6. set meatdata for given app/version
SELECT DISTINCT installed_apps.idx,installed_apps.metadata FROM installed_apps,apps WHERE apps.type='application/vnd.rdk-app.dac.native' AND apps.app_id='com.lgi.app3' AND installed_apps.version="1.0.0";
UPDATE installed_apps SET metadata = '{[{"description","New nice application."},{"parental":"5"}]}' WHERE idx=<idx>;
The logical storages: [APPS] and [APPS_STORAGE] should be defined per platform, to use concrete physical storages.
Epoch indicator {epoch} is used for easy invalidation of not supported or revoked format of apps on fundamental changes. May also be used for the antirollback (db authentication - TBD?)
Apps files are stored in [APPS] storage.
Paths:
Apps persistent storage is located in [APPS_STORAGE].
Paths:
Apps' persistent storage: [APPS_STORAGE]/dac/{epoch}/{id}/
...
...
...
...
...
LISA should be implemented as a Thunder plugin.
An implementation may be based on the Packager code.
Code Block | ||||
---|---|---|---|---|
| ||||
{
"$schema": "plugin.schema.json",
"jsonrpc":"2.0",
"info": {
"title": "Local Inventory & Storage Manager of DAC Apps (LISA) Plugin",
"class": "Lisa",
"callsign": "org.rdk.dac.lisa",
"locator": "libWPEFrameworkLisa.so",
"status": "alpha",
"autostart": true,
"description": "The Local Inventory & Storage Manager of DAC Apps (LISA) plugin allows authenticated downloading and management of DAC bundles from a remote server. It also manages the persistent storage of the DAC applications.",
"version": "1.0"
},
"interface": {
"$ref": "{interfacedir}/lisa.json#"
},
"configuration": {
"type": "object",
"properties": {
"configuration": {
"type": "object",
"properties": {
"network": {
"type": "object",
"required": [
"timeout",
"default_retryIn"
],
"properties": {
"timeout": {
"type": "number",
"description": "Single resource downloading timeout in seconds"
},
"default_retryIn": {
"type": "number",
"description": "Default value of GET retry delay in seconds on HTTP/202, when no "Retry-After" header field is returned in the response."
}
}
},
"storages": {
"type": "object",
"required": [
"apps",
"apps_storage",
"apps_tmp"
],
"properties": {
"apps": {
"type": "string",
"description": "Path to the persistent storage for downloaded applications top dir"
},
"apps_storage": {
"type": "string",
"description": "Path to the persistent storage for downloaded applications persistent storage top dir"
},
"apps_tmp": {
"type": "string",
"description": "Path to the temporary storage for applications being downloaded"
}
}
}
},
"required": [
"timeout",
"storages"
]
}
}
}
}
|
Code Block | ||||
---|---|---|---|---|
| ||||
{
"$schema": "plugin.schema.json",
"jsonrpc":"2.0",
"info": {
"title": "Local Inventory & Storage Manager of DAC Apps (LISA) Plugin",
"class": "Lisa",
"callsign": "org.rdk.dac.lisa",
"locator": "libWPEFrameworkLisa.so",
"status": "alpha",
"autostart": true,
"description": [
"The Local Inventory & Storage Manager of DAC Apps (LISA) plugin allows authenticated downloading and management of DAC bundles from a remote server. It also manages the persistent storage of the DAC applications."
],
"version": "1.0"
},
"interface": {
"$ref": "{interfacedir}/lisa.json"
},
"configuration": {
"storages": {
"apps": "/mnt/apps",
"apps_storage": "/mnt/apps_storage",
"apps_tmp": "/mnt/apps_tmp"
},
"network": {
"timeout": 1800,
"default_retryIn": 300
}
}
} |
Everything marked in italic is implemented so far
UI/resident app:
AWC/windows manager:
...