• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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