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