1 /*
2  * Copyright (C) 2015 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 
17 #define LOG_TAG "ActivityRecognitionHAL"
18 //#define LOG_NDEBUG  0
19 #include <utils/Log.h>
20 
21 #include "activity.h"
22 
23 #include <media/stagefright/foundation/ADebug.h>
24 
25 using namespace android;
26 
27 static const int kVersionMajor = 1;
28 static const int kVersionMinor = 0;
29 
30 static const int ACTIVITY_TYPE_TILTING_INDEX = 6;
31 
32 static const char *const kActivityList[] = {
33     ACTIVITY_TYPE_IN_VEHICLE,
34     ACTIVITY_TYPE_ON_BICYCLE,
35     ACTIVITY_TYPE_WALKING,
36     ACTIVITY_TYPE_RUNNING,
37     ACTIVITY_TYPE_STILL,
38     "com.google.android.contexthub.ar.inconsistent",
39     ACTIVITY_TYPE_TILTING
40 };
41 
ActivityContext(const struct hw_module_t * module)42 ActivityContext::ActivityContext(const struct hw_module_t *module)
43     : mHubConnection(HubConnection::getInstance()),
44       mHubAlive(true),
45       mCallback(NULL),
46       mPrevActivity(-1),
47       mInitExitDone(false) {
48     memset(&device, 0, sizeof(device));
49 
50     device.common.tag = HARDWARE_DEVICE_TAG;
51     device.common.version = ACTIVITY_RECOGNITION_API_VERSION_0_1;
52     device.common.module = const_cast<hw_module_t *>(module);
53     device.common.close = CloseWrapper;
54     device.register_activity_callback = RegisterActivityCallbackWrapper;
55     device.enable_activity_event = EnableActivityEventWrapper;
56     device.disable_activity_event = DisableActivityEventWrapper;
57     device.flush = FlushWrapper;
58 
59     if (mHubConnection->initCheck() != (status_t)OK) {
60         mHubAlive = false;
61     } else {
62         if (mHubConnection->getAliveCheck() != (status_t)OK) {
63             mHubAlive = false;
64         } else {
65             mHubConnection->setActivityCallback(
66                     this, &ActivityContext::HubCallbackWrapper);
67 
68             mHubConnection->queueActivate(COMMS_SENSOR_ACTIVITY, false /* enable */);
69         }
70     }
71 }
72 
~ActivityContext()73 ActivityContext::~ActivityContext() {
74     mHubConnection->setActivityCallback(NULL, NULL);
75 }
76 
close()77 int ActivityContext::close() {
78     ALOGI("close");
79 
80     delete this;
81 
82     return 0;
83 }
84 
onActivityEvent(uint64_t when_us,bool is_flush,float x,float,float)85 void ActivityContext::onActivityEvent(
86         uint64_t when_us, bool is_flush, float x, float, float) {
87     Mutex::Autolock autoLock(mLock);
88 
89     if (!mCallback) {
90         return;
91     }
92 
93     if (is_flush) {
94         activity_event_t ev;
95         memset(&ev, 0, sizeof(ev));
96 
97         ev.event_type = ACTIVITY_EVENT_FLUSH_COMPLETE;
98         ev.activity = 0;
99         ev.timestamp = 0ll;
100 
101         (*mCallback->activity_callback)(mCallback, &ev, 1);
102         return;
103     }
104 
105     int activityRaw = (int)x;
106 
107     ALOGV("activityRaw = %d", activityRaw);
108 
109     if (mPrevActivity >= 0 && mPrevActivity == activityRaw) {
110         // same old, same old...
111         return;
112     }
113 
114     activity_event_t ev[8];
115     memset(&ev, 0, 8*sizeof(activity_event_t));
116     int num_events = 0;
117 
118     // exit all other activities when first enabled.
119     if (!mInitExitDone) {
120         mInitExitDone = true;
121 
122         int numActivities = sizeof(kActivityList) / sizeof(kActivityList[0]);
123         for (int i = 0; i < numActivities; ++i) {
124             if ((i == activityRaw) || !isEnabled(i, ACTIVITY_EVENT_EXIT)) {
125                 continue;
126             }
127 
128             activity_event_t *curr_ev = &ev[num_events];
129             curr_ev->event_type = ACTIVITY_EVENT_EXIT;
130             curr_ev->activity = i;
131             curr_ev->timestamp = when_us * 1000ll;  // timestamp is in ns.
132             curr_ev->reserved[0] = curr_ev->reserved[1] = curr_ev->reserved[2] = curr_ev->reserved[3] = 0;
133             num_events++;
134         }
135     }
136 
137     // tilt activities do not change the current activity type, but have a
138     // simultaneous enter and exit event type
139     if (activityRaw == ACTIVITY_TYPE_TILTING_INDEX) {
140         if (isEnabled(activityRaw, ACTIVITY_EVENT_ENTER)) {
141             activity_event_t *curr_ev = &ev[num_events];
142             curr_ev->event_type = ACTIVITY_EVENT_ENTER;
143             curr_ev->activity = activityRaw;
144             curr_ev->timestamp = when_us * 1000ll;  // timestamp is in ns.
145             curr_ev->reserved[0] = curr_ev->reserved[1] = curr_ev->reserved[2] = curr_ev->reserved[3] = 0;
146             num_events++;
147         }
148 
149         if (isEnabled(activityRaw, ACTIVITY_EVENT_EXIT)) {
150             activity_event_t *curr_ev = &ev[num_events];
151             curr_ev->event_type = ACTIVITY_EVENT_EXIT;
152             curr_ev->activity = activityRaw;
153             curr_ev->timestamp = when_us * 1000ll;  // timestamp is in ns.
154             curr_ev->reserved[0] = curr_ev->reserved[1] = curr_ev->reserved[2] = curr_ev->reserved[3] = 0;
155             num_events++;
156         }
157     } else {
158         if ((mPrevActivity >= 0) &&
159             (isEnabled(mPrevActivity, ACTIVITY_EVENT_EXIT))) {
160             activity_event_t *curr_ev = &ev[num_events];
161             curr_ev->event_type = ACTIVITY_EVENT_EXIT;
162             curr_ev->activity = mPrevActivity;
163             curr_ev->timestamp = when_us * 1000ll;  // timestamp is in ns.
164             curr_ev->reserved[0] = curr_ev->reserved[1] = curr_ev->reserved[2] = curr_ev->reserved[3] = 0;
165             num_events++;
166         }
167 
168         if (isEnabled(activityRaw, ACTIVITY_EVENT_ENTER)) {
169             activity_event_t *curr_ev = &ev[num_events];
170             curr_ev->event_type = ACTIVITY_EVENT_ENTER;
171             curr_ev->activity = activityRaw;
172             curr_ev->timestamp = when_us * 1000ll;  // timestamp is in ns.
173             curr_ev->reserved[0] = curr_ev->reserved[1] = curr_ev->reserved[2] = curr_ev->reserved[3] = 0;
174             num_events++;
175         }
176 
177         mPrevActivity = activityRaw;
178     }
179 
180     if (num_events > 0) {
181         (*mCallback->activity_callback)(mCallback, ev, num_events);
182     }
183 }
184 
registerActivityCallback(const activity_recognition_callback_procs_t * callback)185 void ActivityContext::registerActivityCallback(
186         const activity_recognition_callback_procs_t *callback) {
187     ALOGI("registerActivityCallback");
188 
189     Mutex::Autolock autoLock(mLock);
190     mCallback = callback;
191 }
192 
enableActivityEvent(uint32_t activity_handle,uint32_t event_type,int64_t max_batch_report_latency_ns)193 int ActivityContext::enableActivityEvent(
194         uint32_t activity_handle,
195         uint32_t event_type,
196         int64_t max_batch_report_latency_ns) {
197     ALOGI("enableActivityEvent");
198 
199     bool wasEnabled = !mMaxBatchReportLatencyNs.isEmpty();
200     int64_t prev_latency = calculateReportLatencyNs();
201 
202     ALOGD_IF(DEBUG_ACTIVITY_RECOGNITION, "ACTVT type = %u, latency = %d sec", (unsigned) event_type,
203           (int)(max_batch_report_latency_ns/1000000000ull));
204 
205     mMaxBatchReportLatencyNs.add(
206             ((uint64_t)activity_handle << 32) | event_type,
207             max_batch_report_latency_ns);
208 
209     if (!wasEnabled) {
210         mPrevActivity = -1;
211         mInitExitDone = false;
212 
213         mHubConnection->queueBatch(
214             COMMS_SENSOR_ACTIVITY, SENSOR_FLAG_ON_CHANGE_MODE, 1000000, max_batch_report_latency_ns);
215         mHubConnection->queueActivate(COMMS_SENSOR_ACTIVITY, true /* enable */);
216     } else if (max_batch_report_latency_ns != prev_latency) {
217         mHubConnection->queueBatch(
218             COMMS_SENSOR_ACTIVITY, SENSOR_FLAG_ON_CHANGE_MODE, 1000000, max_batch_report_latency_ns);
219     }
220 
221     return 0;
222 }
223 
calculateReportLatencyNs()224 int64_t ActivityContext::calculateReportLatencyNs() {
225     int64_t ret = INT64_MAX;
226 
227     for (size_t i = 0 ; i < mMaxBatchReportLatencyNs.size(); ++i) {
228         if (mMaxBatchReportLatencyNs[i] <ret) {
229             ret = mMaxBatchReportLatencyNs[i];
230         }
231     }
232     return ret;
233 }
234 
disableActivityEvent(uint32_t activity_handle,uint32_t event_type)235 int ActivityContext::disableActivityEvent(
236         uint32_t activity_handle, uint32_t event_type) {
237     ALOGI("disableActivityEvent");
238 
239     bool wasEnabled = !mMaxBatchReportLatencyNs.isEmpty();
240 
241     mMaxBatchReportLatencyNs.removeItem(
242             ((uint64_t)activity_handle << 32) | event_type);
243 
244     bool isEnabled = !mMaxBatchReportLatencyNs.isEmpty();
245 
246     if (wasEnabled && !isEnabled) {
247         mHubConnection->queueActivate(COMMS_SENSOR_ACTIVITY, false /* enable */);
248     }
249 
250     return 0;
251 }
252 
isEnabled(uint32_t activity_handle,uint32_t event_type) const253 bool ActivityContext::isEnabled(
254         uint32_t activity_handle, uint32_t event_type) const {
255     return mMaxBatchReportLatencyNs.indexOfKey(
256             ((uint64_t)activity_handle << 32) | event_type) >= 0;
257 }
258 
flush()259 int ActivityContext::flush() {
260     mHubConnection->queueFlush(COMMS_SENSOR_ACTIVITY);
261     return 0;
262 }
263 
264 // static
CloseWrapper(struct hw_device_t * dev)265 int ActivityContext::CloseWrapper(struct hw_device_t *dev) {
266     return reinterpret_cast<ActivityContext *>(dev)->close();
267 }
268 
269 // static
RegisterActivityCallbackWrapper(const struct activity_recognition_device * dev,const activity_recognition_callback_procs_t * callback)270 void ActivityContext::RegisterActivityCallbackWrapper(
271         const struct activity_recognition_device *dev,
272         const activity_recognition_callback_procs_t *callback) {
273     const_cast<ActivityContext *>(
274             reinterpret_cast<const ActivityContext *>(dev))
275         ->registerActivityCallback(callback);
276 }
277 
278 // static
EnableActivityEventWrapper(const struct activity_recognition_device * dev,uint32_t activity_handle,uint32_t event_type,int64_t max_batch_report_latency_ns)279 int ActivityContext::EnableActivityEventWrapper(
280         const struct activity_recognition_device *dev,
281         uint32_t activity_handle,
282         uint32_t event_type,
283         int64_t max_batch_report_latency_ns) {
284     return const_cast<ActivityContext *>(
285             reinterpret_cast<const ActivityContext *>(dev))
286         ->enableActivityEvent(
287             activity_handle, event_type, max_batch_report_latency_ns);
288 }
289 
290 // static
DisableActivityEventWrapper(const struct activity_recognition_device * dev,uint32_t activity_handle,uint32_t event_type)291 int ActivityContext::DisableActivityEventWrapper(
292         const struct activity_recognition_device *dev,
293         uint32_t activity_handle,
294         uint32_t event_type) {
295     return const_cast<ActivityContext *>(
296             reinterpret_cast<const ActivityContext *>(dev))
297         ->disableActivityEvent(activity_handle, event_type);
298 }
299 
300 // static
FlushWrapper(const struct activity_recognition_device * dev)301 int ActivityContext::FlushWrapper(
302         const struct activity_recognition_device *dev) {
303     return const_cast<ActivityContext *>(
304             reinterpret_cast<const ActivityContext *>(dev))->flush();
305 }
306 
307 // static
HubCallbackWrapper(void * me,uint64_t time_ms,bool is_flush,float x,float y,float z)308 void ActivityContext::HubCallbackWrapper(
309         void *me, uint64_t time_ms, bool is_flush, float x, float y, float z) {
310     static_cast<ActivityContext *>(me)->onActivityEvent(time_ms, is_flush, x, y, z);
311 }
312 
getHubAlive()313 bool ActivityContext::getHubAlive() {
314     return mHubAlive;
315 }
316 
317 ////////////////////////////////////////////////////////////////////////////////
318 
319 static bool gHubAlive = false;
320 
open_activity(const struct hw_module_t * module,const char *,struct hw_device_t ** dev)321 static int open_activity(
322         const struct hw_module_t *module,
323         const char *,
324         struct hw_device_t **dev) {
325     ALOGI("open_activity");
326 
327     ActivityContext *ctx = new ActivityContext(module);
328 
329     gHubAlive = ctx->getHubAlive();
330     *dev = &ctx->device.common;
331 
332     return 0;
333 }
334 
335 static struct hw_module_methods_t activity_module_methods = {
336     .open = open_activity
337 };
338 
get_activity_list(struct activity_recognition_module *,char const * const ** activity_list)339 static int get_activity_list(
340         struct activity_recognition_module *,
341         char const* const **activity_list) {
342     ALOGI("get_activity_list");
343 
344     if (gHubAlive) {
345         *activity_list = kActivityList;
346         return sizeof(kActivityList) / sizeof(kActivityList[0]);
347     } else {
348         *activity_list = {};
349         return 0;
350     }
351 }
352 
353 struct activity_recognition_module HAL_MODULE_INFO_SYM = {
354         .common = {
355                 .tag = HARDWARE_MODULE_TAG,
356                 .version_major = kVersionMajor,
357                 .version_minor = kVersionMinor,
358                 .id = ACTIVITY_RECOGNITION_HARDWARE_MODULE_ID,
359                 .name = "Google Activity Recognition module",
360                 .author = "Google",
361                 .methods = &activity_module_methods,
362                 .dso  = NULL,
363                 .reserved = {0},
364         },
365         .get_supported_activities_list = get_activity_list,
366 };
367 
368