blob: 5d51b7601fa2c85e9f2ffda2c080b72bbbd2dce0 [file] [log] [blame]
/*
* Copyright (C) 2018 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.
*/
#include <pixelstats/DropDetect.h>
#include <chre/util/nanoapp/app_id.h>
#include <chre_host/host_protocol_host.h>
#include <chre_host/socket_client.h>
#include <android/frameworks/stats/1.0/IStats.h>
#define LOG_TAG "pixelstats-vendor"
#include <log/log.h>
#include <inttypes.h>
using android::sp;
using android::chre::HostProtocolHost;
using android::chre::IChreMessageHandlers;
using android::chre::SocketClient;
using android::frameworks::stats::V1_0::IStats;
using android::frameworks::stats::V1_0::PhysicalDropDetected;
// following convention of CHRE code.
namespace fbs = ::chre::fbs;
namespace android {
namespace hardware {
namespace google {
namespace pixel {
namespace { // anonymous namespace for file-local definitions
// This struct is defined in nanoapps/drop/messaging.h
// by the DropDetect nanoapp.
struct __attribute__((__packed__)) DropEventPayload {
float confidence;
float accel_magnitude_peak;
int32_t free_fall_duration_ns;
};
// This enum is defined in nanoapps/drop/messaging.h
// by the DropDetect nanoapp.
enum DropConstants {
kDropEnableRequest = 1,
kDropEnableNotification = 2,
kDropDisableRequest = 3,
kDropDisableNotification = 4,
kDropEventDetection = 5,
};
void requestNanoappList(SocketClient &client) {
flatbuffers::FlatBufferBuilder builder(64);
HostProtocolHost::encodeNanoappListRequest(builder);
if (!client.sendMessage(builder.GetBufferPointer(), builder.GetSize())) {
ALOGE("Failed to send NanoappList request");
}
}
} // namespace
DropDetect::DropDetect(const uint64_t drop_detect_app_id) : kDropDetectAppId(drop_detect_app_id) {}
sp<DropDetect> DropDetect::start(const uint64_t drop_detect_app_id, const char *const chre_socket) {
sp<DropDetect> dropDetect = new DropDetect(drop_detect_app_id);
if (!dropDetect->connectInBackground(chre_socket, dropDetect)) {
ALOGE("Couldn't connect to CHRE socket");
return nullptr;
}
return dropDetect;
}
void DropDetect::onConnected() {
requestNanoappList(*this);
}
/**
* Decode unix socket msgs to CHRE messages, and call the appropriate
* callback depending on the CHRE message.
*/
void DropDetect::onMessageReceived(const void *data, size_t length) {
if (!HostProtocolHost::decodeMessageFromChre(data, length, *this)) {
ALOGE("Failed to decode message");
}
}
/**
* Handle the response of a NanoappList request.
* Ensure that the Drop Detect nanoapp is running.
*/
void DropDetect::handleNanoappListResponse(const fbs::NanoappListResponseT &response) {
for (const std::unique_ptr<fbs::NanoappListEntryT> &nanoapp : response.nanoapps) {
if (nanoapp->app_id == kDropDetectAppId) {
if (!nanoapp->enabled)
ALOGE("Drop Detect app not enabled");
else
ALOGI("Drop Detect enabled");
return;
}
}
ALOGE("Drop Detect app not found");
}
/**
* listen for messages from the DropDetect nanoapp and report them to
* PixelStats.
*/
void DropDetect::handleNanoappMessage(const fbs::NanoappMessageT &message) {
struct DropEventPayload *message_struct;
if (message.app_id != kDropDetectAppId || message.message_type != kDropEventDetection ||
message.message.size() < sizeof(struct DropEventPayload))
return;
message_struct = (struct DropEventPayload *)&message.message[0];
ALOGI("Received drop detect message! Confidence %f Peak %f Duration %g",
message_struct->confidence, message_struct->accel_magnitude_peak,
message_struct->free_fall_duration_ns / 1e9);
uint8_t confidence = message_struct->confidence * 100;
confidence = std::min<int>(confidence, 100);
confidence = std::max<int>(0, confidence);
int32_t accel_magnitude_peak_1000ths_g = message_struct->accel_magnitude_peak * 1000.0;
int32_t free_fall_duration_ms = message_struct->free_fall_duration_ns / 1000000;
sp<IStats> stats_client = IStats::tryGetService();
if (stats_client) {
PhysicalDropDetected drop = {confidence, accel_magnitude_peak_1000ths_g,
free_fall_duration_ms};
Return<void> ret = stats_client->reportPhysicalDropDetected(drop);
if (!ret.isOk())
ALOGE("Unable to report physical drop to Stats service");
} else
ALOGE("Unable to connect to Stats service");
}
} // namespace pixel
} // namespace google
} // namespace hardware
} // namespace android