You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
210 lines
7.3 KiB
210 lines
7.3 KiB
/*
|
|
* 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 <hardware/google/pixel/pixelstats/pixelatoms.pb.h>
|
|
#include <pixelstats/StatsHelper.h>
|
|
|
|
#define LOG_TAG "pixelstats-vendor"
|
|
#include <log/log.h>
|
|
|
|
#include <inttypes.h>
|
|
#include <math.h>
|
|
|
|
using aidl::android::frameworks::stats::IStats;
|
|
using aidl::android::frameworks::stats::VendorAtom;
|
|
using aidl::android::frameworks::stats::VendorAtomValue;
|
|
using android::sp;
|
|
using android::chre::HostProtocolHost;
|
|
using android::chre::IChreMessageHandlers;
|
|
using android::chre::SocketClient;
|
|
using android::hardware::google::pixel::PixelAtoms::VendorPhysicalDropDetected;
|
|
|
|
// following convention of CHRE code.
|
|
namespace fbs = ::chre::fbs;
|
|
|
|
namespace android {
|
|
namespace hardware {
|
|
namespace google {
|
|
namespace pixel {
|
|
|
|
namespace { // anonymous namespace for file-local definitions
|
|
|
|
// The following two structs are 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;
|
|
};
|
|
|
|
struct __attribute__((__packed__)) DropEventPayloadV2 {
|
|
uint64_t free_fall_duration_ns;
|
|
float impact_accel_x;
|
|
float impact_accel_y;
|
|
float impact_accel_z;
|
|
};
|
|
|
|
// 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,
|
|
kDropEventDetectionV2 = 6,
|
|
};
|
|
|
|
void requestNanoappList(SocketClient *client) {
|
|
if (client != nullptr) {
|
|
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");
|
|
}
|
|
|
|
static VendorPhysicalDropDetected dropEventFromNanoappPayload(const struct DropEventPayload *p) {
|
|
ALOGI("Received drop detect message! Confidence %f Peak %f Duration %g",
|
|
p->confidence, p->accel_magnitude_peak, p->free_fall_duration_ns / 1e9);
|
|
|
|
uint8_t confidence = p->confidence * 100;
|
|
confidence = std::min<int>(confidence, 100);
|
|
confidence = std::max<int>(0, confidence);
|
|
int32_t accel_magnitude_peak_1000ths_g = p->accel_magnitude_peak * 1000.0;
|
|
int32_t free_fall_duration_ms = p->free_fall_duration_ns / 1000000;
|
|
|
|
VendorPhysicalDropDetected drop_info;
|
|
drop_info.set_confidence_pctg(confidence);
|
|
drop_info.set_accel_peak_thousandths_g(accel_magnitude_peak_1000ths_g);
|
|
drop_info.set_freefall_time_millis(free_fall_duration_ms);
|
|
return drop_info;
|
|
}
|
|
|
|
static VendorPhysicalDropDetected dropEventFromNanoappPayload(const struct DropEventPayloadV2 *p) {
|
|
ALOGI("Received drop detect message: "
|
|
"duration %g ms, impact acceleration: x = %f, y = %f, z = %f",
|
|
p->free_fall_duration_ns / 1e6,
|
|
p->impact_accel_x,
|
|
p->impact_accel_y,
|
|
p->impact_accel_z);
|
|
|
|
float impact_magnitude = sqrt(p->impact_accel_x * p->impact_accel_x +
|
|
p->impact_accel_y * p->impact_accel_y +
|
|
p->impact_accel_z * p->impact_accel_z);
|
|
/* Scale impact magnitude as percentage between [50, 100] m/s2. */
|
|
constexpr float min_confidence_magnitude = 50;
|
|
constexpr float max_confidence_magnitude = 100;
|
|
uint8_t confidence_percentage =
|
|
impact_magnitude < min_confidence_magnitude ? 0 :
|
|
impact_magnitude > max_confidence_magnitude ? 100 :
|
|
(impact_magnitude - min_confidence_magnitude) /
|
|
(max_confidence_magnitude - min_confidence_magnitude) * 100;
|
|
|
|
int32_t free_fall_duration_ms = static_cast<int32_t>(p->free_fall_duration_ns / 1000000);
|
|
|
|
VendorPhysicalDropDetected drop_info;
|
|
drop_info.set_confidence_pctg(confidence_percentage);
|
|
drop_info.set_accel_peak_thousandths_g(static_cast<int32_t>(impact_magnitude * 1000));
|
|
drop_info.set_freefall_time_millis(free_fall_duration_ms);
|
|
return drop_info;
|
|
}
|
|
|
|
static void reportDropEventToStatsd(const VendorPhysicalDropDetected &drop) {
|
|
const std::shared_ptr<IStats> stats_client = getStatsService();
|
|
if (!stats_client) {
|
|
ALOGE("Unable to get AIDL Stats service");
|
|
return;
|
|
}
|
|
|
|
reportPhysicalDropDetected(stats_client, drop);
|
|
}
|
|
|
|
/**
|
|
* listen for messages from the DropDetect nanoapp and report them to
|
|
* PixelStats.
|
|
*/
|
|
void DropDetect::handleNanoappMessage(const fbs::NanoappMessageT &message) {
|
|
if (message.app_id != kDropDetectAppId)
|
|
return;
|
|
|
|
if (message.message_type == kDropEventDetection &&
|
|
message.message.size() >= sizeof(struct DropEventPayload)) {
|
|
reportDropEventToStatsd(dropEventFromNanoappPayload(
|
|
reinterpret_cast<const struct DropEventPayload *>(&message.message[0])));
|
|
} else if (message.message_type == kDropEventDetectionV2 &&
|
|
message.message.size() >= sizeof(struct DropEventPayloadV2)) {
|
|
reportDropEventToStatsd(dropEventFromNanoappPayload(
|
|
reinterpret_cast<const struct DropEventPayloadV2 *>(&message.message[0])));
|
|
}
|
|
}
|
|
|
|
} // namespace pixel
|
|
} // namespace google
|
|
} // namespace hardware
|
|
} // namespace android
|