/* * Copyright 2024 Google LLC * * 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. */ #pragma once #include "api_types.h" #include #include #include "system/status_codes.h" #include "util/attributes.h" #include "util/list.h" #include "util/time/time.h" //! The BlobDB API is a single consistent API to a number of key/value stores on the watch. //! It is used in conjunction with the BlobDB endpoint. //! Key/Value stores that are meant to be used with the endpoint need to implement this API //! by implementing each of the Impl functions (see below). //! A BlobDB is not guaranteed to persist across reboots, but it is guaranteed to //! have executed a command when it returns a success code. //! If you want to route commands to your BlobDB implementation API, you need //! to add it to the \ref BlobDBId enum and to the BlobDBs list (\ref s_blob_dbs) in api.c typedef enum PACKED { BlobDBIdTest = 0x00, BlobDBIdPins = 0x01, BlobDBIdApps = 0x02, BlobDBIdReminders = 0x03, BlobDBIdNotifs = 0x04, BlobDBIdWeather = 0x05, BlobDBIdiOSNotifPref = 0x06, BlobDBIdPrefs = 0x07, BlobDBIdContacts = 0x08, BlobDBIdWatchAppPrefs = 0x09, BlobDBIdHealth = 0x0A, BlobDBIdAppGlance = 0x0B, NumBlobDBs, } BlobDBId; _Static_assert(sizeof(BlobDBId) == 1, "BlobDBId is larger than 1 byte"); //! A linked list of blob DB items that need to be synced typedef struct { ListNode node; time_t last_updated; int key_len; //!< length of the key, in bytes uint8_t key[]; //!< key_len-size byte array of key data } BlobDBDirtyItem; //! A Blob DB's initialization routine. //! This function will be called at boot when all blob dbs are init-ed typedef void (*BlobDBInitImpl)(void); //! Implements the insert API. Note that this function should be blocking. //! \param key a pointer to the key data //! \param key_len the lenght of the key, in bytes //! \param val a pointer to the value data //! \param val_len the length of the value, in bytes //! \returns S_SUCCESS if the key/val pair was succesfully inserted //! and an error code otherwise (See \ref StatusCode) typedef status_t (*BlobDBInsertImpl) (const uint8_t *key, int key_len, const uint8_t *val, int val_len); //! Implements the get length API. //! \param key a pointer to the key data //! \param key_len the lenght of the key, in bytes //! \returns the length in bytes of the value for key on success //! and an error code otherwise (See \ref StatusCode) typedef int (*BlobDBGetLenImpl) (const uint8_t *key, int key_len); //! Implements the read API. Note that this function should be blocking. //! \param key a pointer to the key data //! \param key_len the lenght of the key, in bytes //! \param[out] val_out a pointer to a buffer of size val_len //! \param val_len the length of the value to be copied, in bytes //! \returns S_SUCCESS if the value for key was succesfully read, //! and an error code otherwise (See \ref StatusCode) typedef status_t (*BlobDBReadImpl) (const uint8_t *key, int key_len, uint8_t *val_out, int val_len); //! Implements the delete API. Note that this function should be blocking. //! \param key a pointer to the key data //! \param key_len the lenght of the key, in bytes //! \returns S_SUCCESS if the key/val pair was succesfully deleted //! and an error code otherwise (See \ref StatusCode) typedef status_t (*BlobDBDeleteImpl) (const uint8_t *key, int key_len); //! Implements the flush API. Note that this function should be blocking. //! \returns S_SUCCESS if all key/val pairs were succesfully deleted //! and an error code otherwise (See \ref StatusCode) typedef status_t (*BlobDBFlushImpl)(void); //! Implements the IsDirty API. //! \param[out] is_dirty_out reference to a boolean that will be set depending on the DB state //! \note if the function does not return S_SUCCESS, the state of the boolean is undefined. //! \returns S_SUCCESS if the query succeeded, an error code otherwise typedef status_t (*BlobDBIsDirtyImpl)(bool *is_dirty_out); //! Implements the GetDirtyList API. //! \return a linked list of \ref BlobDBDirtyItem with a node per out-of-sync item. //! \note There is no limit how large this list can get. Handle OOM scenarios gracefully! typedef BlobDBDirtyItem *(*BlobDBGetDirtyListImpl)(void); //! Implements the MarkSynced API. //! \param key a pointer to the key data //! \param key_len the lenght of the key, in bytes //! \returns S_SUCCESS if the item was marked synced, an error code otherwise typedef status_t (*BlobDBMarkSyncedImpl)(const uint8_t *key, int key_len); //! Emits a Blob DB event. //! \param type The type of event to emit //! \param db_id the ID of the blob DB //! \param key a pointer to the key data //! \param key_len the length of the key, in bytes void blob_db_event_put(BlobDBEventType type, BlobDBId db_id, const uint8_t *key, int key_len); //! Call the BlobDBInitImpl for all the databases void blob_db_init_dbs(void); //! Call the BlobDBIsDirtyImpl for each database, and fill the 'ids' list //! with all the dirty DB ids //! \param[out] ids an array of BlobDbIds of size NumBlobDBs or more. //! \param[out] num_ids an array of BlobDbIds of size NumBlobDBs or more. //! \note The unused entries will be set to 0. void blob_db_get_dirty_dbs(uint8_t *ids, uint8_t *num_ids); //! Insert a key/val pair in a blob DB. //! See \ref BlobDBReadImpl //! \param db_id the ID of the blob DB //! \param key a pointer to the key data //! \param key_len the lenght of the key, in bytes status_t blob_db_insert(BlobDBId db_id, const uint8_t *key, int key_len, const uint8_t *val, int val_len); //! Get the length of the value in a blob DB for a given key. //! See \ref BlobDBGetLenImpl //! \param db_id the ID of the blob DB //! \param key a pointer to the key data //! \param key_len the lenght of the key, in bytes int blob_db_get_len(BlobDBId db_id, const uint8_t *key, int key_len); //! Get the value of length val_len for a given key //! \param db_id the ID of the blob DB //! See \ref BlobDBReadImpl status_t blob_db_read(BlobDBId db_id, const uint8_t *key, int key_len, uint8_t *val_out, int val_len); //! Delete the key/val pair in a blob DB for a given key //! \param db_id the ID of the blob DB //! See \ref BlobDBDeleteImpl status_t blob_db_delete(BlobDBId db_id, const uint8_t *key, int key_len); //! Delete all key/val pairs in a blob DB. //! \param db_id the ID of the blob DB //! See \ref BlobDBFlushImpl status_t blob_db_flush(BlobDBId db_id); //! Get the list of items in a given blob DB that have yet to be synced. //! Items originating from the phone are always marked as synced. //! \note Use the APIs in sync.h to initiate a sync. //! \param db_id the ID of the blob DB //! \see BlobDBGetDirtyListImpl BlobDBDirtyItem *blob_db_get_dirty_list(BlobDBId db_id); //! Mark an item in a blob DB as having been synced //! \note This API is used upon receiving an ACK from the phone during sync //! \param db_id the ID of the blob DB //! \see BlobDBMarkSyncedImpl status_t blob_db_mark_synced(BlobDBId db_id, uint8_t *key, int key_len);