1 /*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 #include <pixelstats/DropDetect.h>
17
18 #include <chre/util/nanoapp/app_id.h>
19 #include <chre_host/host_protocol_host.h>
20 #include <chre_host/socket_client.h>
21
22 #include <android/frameworks/stats/1.0/IStats.h>
23 #define LOG_TAG "pixelstats-vendor"
24 #include <log/log.h>
25
26 #include <inttypes.h>
27
28 using android::sp;
29 using android::chre::HostProtocolHost;
30 using android::chre::IChreMessageHandlers;
31 using android::chre::SocketClient;
32 using android::frameworks::stats::V1_0::IStats;
33 using android::frameworks::stats::V1_0::PhysicalDropDetected;
34
35 // following convention of CHRE code.
36 namespace fbs = ::chre::fbs;
37
38 namespace android {
39 namespace hardware {
40 namespace google {
41 namespace pixel {
42
43 namespace { // anonymous namespace for file-local definitions
44
45 // This struct is defined in nanoapps/drop/messaging.h
46 // by the DropDetect nanoapp.
47 struct __attribute__((__packed__)) DropEventPayload {
48 float confidence;
49 float accel_magnitude_peak;
50 int32_t free_fall_duration_ns;
51 };
52
53 // This enum is defined in nanoapps/drop/messaging.h
54 // by the DropDetect nanoapp.
55 enum DropConstants {
56 kDropEnableRequest = 1,
57 kDropEnableNotification = 2,
58 kDropDisableRequest = 3,
59 kDropDisableNotification = 4,
60 kDropEventDetection = 5,
61 };
62
requestNanoappList(SocketClient & client)63 void requestNanoappList(SocketClient &client) {
64 flatbuffers::FlatBufferBuilder builder(64);
65 HostProtocolHost::encodeNanoappListRequest(builder);
66
67 if (!client.sendMessage(builder.GetBufferPointer(), builder.GetSize())) {
68 ALOGE("Failed to send NanoappList request");
69 }
70 }
71
72 } // namespace
73
DropDetect(const uint64_t drop_detect_app_id)74 DropDetect::DropDetect(const uint64_t drop_detect_app_id) : kDropDetectAppId(drop_detect_app_id) {}
75
start(const uint64_t drop_detect_app_id,const char * const chre_socket)76 sp<DropDetect> DropDetect::start(const uint64_t drop_detect_app_id, const char *const chre_socket) {
77 sp<DropDetect> dropDetect = new DropDetect(drop_detect_app_id);
78 if (!dropDetect->connectInBackground(chre_socket, dropDetect)) {
79 ALOGE("Couldn't connect to CHRE socket");
80 return nullptr;
81 }
82 return dropDetect;
83 }
84
onConnected()85 void DropDetect::onConnected() {
86 requestNanoappList(*this);
87 }
88
89 /**
90 * Decode unix socket msgs to CHRE messages, and call the appropriate
91 * callback depending on the CHRE message.
92 */
onMessageReceived(const void * data,size_t length)93 void DropDetect::onMessageReceived(const void *data, size_t length) {
94 if (!HostProtocolHost::decodeMessageFromChre(data, length, *this)) {
95 ALOGE("Failed to decode message");
96 }
97 }
98
99 /**
100 * Handle the response of a NanoappList request.
101 * Ensure that the Drop Detect nanoapp is running.
102 */
handleNanoappListResponse(const fbs::NanoappListResponseT & response)103 void DropDetect::handleNanoappListResponse(const fbs::NanoappListResponseT &response) {
104 for (const std::unique_ptr<fbs::NanoappListEntryT> &nanoapp : response.nanoapps) {
105 if (nanoapp->app_id == kDropDetectAppId) {
106 if (!nanoapp->enabled)
107 ALOGE("Drop Detect app not enabled");
108 else
109 ALOGI("Drop Detect enabled");
110 return;
111 }
112 }
113 ALOGE("Drop Detect app not found");
114 }
115
116 /**
117 * listen for messages from the DropDetect nanoapp and report them to
118 * PixelStats.
119 */
handleNanoappMessage(const fbs::NanoappMessageT & message)120 void DropDetect::handleNanoappMessage(const fbs::NanoappMessageT &message) {
121 struct DropEventPayload *message_struct;
122
123 if (message.app_id != kDropDetectAppId || message.message_type != kDropEventDetection ||
124 message.message.size() < sizeof(struct DropEventPayload))
125 return;
126 message_struct = (struct DropEventPayload *)&message.message[0];
127 ALOGI("Received drop detect message! Confidence %f Peak %f Duration %g",
128 message_struct->confidence, message_struct->accel_magnitude_peak,
129 message_struct->free_fall_duration_ns / 1e9);
130 uint8_t confidence = message_struct->confidence * 100;
131 confidence = std::min<int>(confidence, 100);
132 confidence = std::max<int>(0, confidence);
133
134 int32_t accel_magnitude_peak_1000ths_g = message_struct->accel_magnitude_peak * 1000.0;
135 int32_t free_fall_duration_ms = message_struct->free_fall_duration_ns / 1000000;
136
137 sp<IStats> stats_client = IStats::tryGetService();
138 if (stats_client) {
139 PhysicalDropDetected drop = {confidence, accel_magnitude_peak_1000ths_g,
140 free_fall_duration_ms};
141 Return<void> ret = stats_client->reportPhysicalDropDetected(drop);
142 if (!ret.isOk())
143 ALOGE("Unable to report physical drop to Stats service");
144 } else
145 ALOGE("Unable to connect to Stats service");
146 }
147
148 } // namespace pixel
149 } // namespace google
150 } // namespace hardware
151 } // namespace android
152