| /* |
| * 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 |