blob: 8e3e9bfb0a1588881db3521ee605de9efa55b078 [file] [log] [blame]
/*
* Copyright (C) 2016 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.
*/
#ifndef CHRE_CORE_NANOAPP_H_
#define CHRE_CORE_NANOAPP_H_
#include <cinttypes>
#include <cstdint>
#include <limits>
#include "chre/core/event.h"
#include "chre/core/event_ref_queue.h"
#include "chre/platform/heap_block_header.h"
#include "chre/platform/platform_nanoapp.h"
#include "chre/util/dynamic_vector.h"
#include "chre/util/fixed_size_vector.h"
#include "chre/util/system/debug_dump.h"
#include "chre/util/system/napp_permissions.h"
#include "chre/util/system/stats_container.h"
#include "chre_api/chre/event.h"
namespace chre {
/**
* A class that tracks the state of a Nanoapp including incoming events and
* event registrations.
*
* Inheritance is used to separate the common interface with common
* implementation part (chre::Nanoapp) from the common interface with
* platform-specific implementation part (chre::PlatformNanoapp) from the purely
* platform-specific part (chre::PlatformNanoappBase). However, this inheritance
* relationship does *not* imply polymorphism, and this object must only be
* referred to via the most-derived type, i.e. chre::Nanoapp.
*/
class Nanoapp : public PlatformNanoapp {
public:
/** @see chrePublishRpcServices */
static constexpr size_t kMaxRpcServices = UINT8_MAX;
static_assert(
std::numeric_limits<decltype(chreNanoappInfo::rpcServiceCount)>::max() >=
kMaxRpcServices,
"Revisit the constant");
Nanoapp();
/**
* Calls the start function of the nanoapp. For dynamically loaded nanoapps,
* this must also result in calling through to any of the nanoapp's static
* global constructors/init functions, etc., prior to invoking the
* nanoappStart.
*
* @return true if the app was able to start successfully
*
* @see nanoappStart
*/
bool start();
/**
* @return The unique identifier for this Nanoapp instance
*/
uint16_t getInstanceId() const {
return mInstanceId;
}
/**
* @return The current total number of bytes the nanoapp has allocated.
*/
size_t getTotalAllocatedBytes() const {
return mTotalAllocatedBytes;
}
/**
* @return The peak total number of bytes the nanoapp has allocated.
*/
size_t getPeakAllocatedBytes() const {
return mPeakAllocatedBytes;
}
/**
* Sets the total number of bytes the nanoapp has allocated. Also, modifies
* the peak allocated bytes if the current total is higher than the peak.
*
* @param The total number of bytes the nanoapp has allocated.
*/
void setTotalAllocatedBytes(size_t totalAllocatedBytes) {
mTotalAllocatedBytes = totalAllocatedBytes;
if (mTotalAllocatedBytes > mPeakAllocatedBytes) {
mPeakAllocatedBytes = mTotalAllocatedBytes;
}
}
/**
* @return true if the nanoapp should receive broadcast event
*/
bool isRegisteredForBroadcastEvent(const Event *event) const;
/**
* Updates the Nanoapp's registration so that it will receive broadcast events
* with the given event type.
*
* @param eventType The event type that the nanoapp will now be registered to
* receive
* @param groupIdMask A mask of group IDs to register the nanoapp for. If an
* event is sent that targets any of the group IDs in the mask, it will
* be delivered to the nanoapp.
*/
void registerForBroadcastEvent(
uint16_t eventType, uint16_t groupIdMask = kDefaultTargetGroupMask);
/**
* Updates the Nanoapp's registration so that it will not receive broadcast
* events with the given event type.
*
* @param eventType The event type that the nanoapp will be unregistered from
* assuming the group ID also matches a valid entry.
* @param groupIdMask The mask of group IDs that will be unregistered from.
*/
void unregisterForBroadcastEvent(
uint16_t eventType, uint16_t groupIdMask = kDefaultTargetGroupMask);
/**
* Configures whether nanoapp info events will be sent to the nanoapp.
* Nanoapps are not sent nanoapp start/stop events by default.
*
* @param enable true if events are to be sent, false otherwise.
*/
void configureNanoappInfoEvents(bool enable);
/**
* Configures whether host sleep events will be sent to the nanoapp. Nanoapps
* are not sent sleep/awake events by default.
*
* @param enable true if events are to be sent, false otherwise.
*/
void configureHostSleepEvents(bool enable);
/**
* Configures whether debug dump events will be sent to the nanoapp. Nanoapps
* are not sent debug dump events by default.
*
* @param enable true if events are to be sent, false otherwise.
*/
void configureDebugDumpEvent(bool enable);
/**
* Configures whether a user settings event will be sent to the nanoapp
* for a specified setting (@see CHRE_USER_SETTINGS)
* Nanoapps are not sent user settings events by default.
*
* @param setting The user setting that the nanoapp wishes to configure
* events for.
*
* @param enable true if events are to be sent, false otherwise.
*/
void configureUserSettingEvent(uint8_t setting, bool enable);
/**
* Sends an event to the nanoapp to be processed.
*
* @param event A pointer to the event to be processed
*/
void processEvent(Event *event);
/**
* Log info about a single host wakeup that this nanoapp triggered by storing
* the count of wakeups in mWakeupBuckets.
*/
void blameHostWakeup();
/*
* If buckets not full, then just pushes a 0 to back of buckets. If full, then
* shifts down all buckets from back to front and sets back to 0, losing the
* latest bucket value that was in front.
*
* @param numBuckets the number of buckets to cycle into to mWakeupBuckets
*/
void cycleWakeupBuckets(size_t numBuckets);
/**
* Prints state in a string buffer. Must only be called from the context of
* the main CHRE thread.
*
* @param debugDump The object that is printed into for debug dump logs.
*/
void logStateToBuffer(DebugDumpWrapper &debugDump) const;
/**
* @return true if the nanoapp is permitted to use the provided permission.
*/
bool permitPermissionUse(uint32_t permission) const;
/**
* Configures notification updates for a given host endpoint.
*
* @param hostEndpointId The ID of the host endpoint.
* @param enable true to enable notifications.
*
* @return true if the configuration is successful.
*/
bool configureHostEndpointNotifications(uint16_t hostEndpointId, bool enable);
/**
* Publishes RPC services for this nanoapp.
*
* @param services A pointer to the list of RPC services to publish.
* Can be null if numServices is 0.
* @param numServices The number of services to publish, i.e. the length of
* the services array.
*
* @return true if the publishing is successful.
*/
bool publishRpcServices(struct chreNanoappRpcService *services,
size_t numServices);
/**
* @return The list of RPC services published by this nanoapp.
*/
const DynamicVector<struct chreNanoappRpcService> &getRpcServices() const {
return mRpcServices;
}
/**
* Adds a block of memory to the linked list of headers.
*
* @see getFirstHeapBlock
* @see chreHeapAlloc
*/
void linkHeapBlock(HeapBlockHeader *header);
/**
* Removes a block of memory from the linked list of headers.
*
* @see getFirstHeapBlock
* @see chreHeapFree
*/
void unlinkHeapBlock(HeapBlockHeader *header);
/**
* @return A pointer to the first allocated heap block.
*/
HeapBlockHeader *getFirstHeapBlock() {
return mFirstHeader;
}
private:
uint16_t mInstanceId = kInvalidInstanceId;
//! The total number of wakeup counts for a nanoapp.
uint32_t mNumWakeupsSinceBoot = 0;
/**
* Head of the singly linked list of heap block headers.
*
* The list is used to free all the memory allocated by the nanoapp.
*
* @see MemoryManager
*/
HeapBlockHeader *mFirstHeader = nullptr;
//! The total memory allocated by the nanoapp in bytes.
size_t mTotalAllocatedBytes = 0;
//! The peak total number of bytes allocated by the nanoapp.
size_t mPeakAllocatedBytes = 0;
//! The number of buckets for wakeup logging, adjust along with
//! EventLoop::kIntervalWakupBucketInMins.
static constexpr size_t kMaxSizeWakeupBuckets = 4;
//! A fixed size buffer of buckets that keeps track of the number of host
//! wakeups over time intervals.
FixedSizeVector<uint16_t, kMaxSizeWakeupBuckets> mWakeupBuckets;
//! Collects process time in nanoseconds of each event
StatsContainer<uint64_t> mEventProcessTime;
//! Metadata needed for keeping track of the registered events for this
//! nanoapp.
struct EventRegistration {
EventRegistration(uint16_t eventType_, uint16_t groupIdMask_)
: eventType(eventType_), groupIdMask(groupIdMask_) {}
uint16_t eventType;
uint16_t groupIdMask;
};
//! The set of broadcast events that this app is registered for.
// TODO: Implement a set container and replace DynamicVector here. There may
// also be a better way of handling this (perhaps we map event type to apps
// who care about them).
DynamicVector<EventRegistration> mRegisteredEvents;
//! The registered host endpoints to receive notifications for.
DynamicVector<uint16_t> mRegisteredHostEndpoints;
//! The list of RPC services for this nanoapp.
DynamicVector<struct chreNanoappRpcService> mRpcServices;
//! Whether nanoappStart is being executed.
bool mIsInNanoappStart = false;
//! @return index of event registration if found. mRegisteredEvents.size() if
//! not.
size_t registrationIndex(uint16_t eventType) const;
/**
* A special function to deliver GNSS measurement events to nanoapps and
* handles version compatibility.
*
* @param event The pointer to the event
*/
void handleGnssMeasurementDataEvent(const Event *event);
bool isRegisteredForHostEndpointNotifications(uint16_t hostEndpointId) const {
return mRegisteredHostEndpoints.find(hostEndpointId) !=
mRegisteredHostEndpoints.size();
}
};
} // namespace chre
#endif // CHRE_CORE_NANOAPP_H_