summaryrefslogtreecommitdiffstats
path: root/folio_daemon
diff options
context:
space:
mode:
authorAndrew Lehmer <alehmer@google.com>2017-03-29 10:17:06 -0700
committerAndrew Lehmer <alehmer@google.com>2017-03-31 13:08:45 -0700
commit99cbc8d59606301fd0c8d65a089d93f7f6986666 (patch)
tree0d12e47d73f05b310c138c4b49da61e0ed5b2055 /folio_daemon
parent1e723fbe133968cddac45460c82d9081fdf2337f (diff)
downloaddevice_google_wahoo-99cbc8d59606301fd0c8d65a089d93f7f6986666.tar.gz
device_google_wahoo-99cbc8d59606301fd0c8d65a089d93f7f6986666.tar.bz2
device_google_wahoo-99cbc8d59606301fd0c8d65a089d93f7f6986666.zip
Add support for folio cases
Bug: 35243564 Test: Used magnet to wake and lock device. Also tested during suspend. Change-Id: I4b819e12cc23a3d7a8ce048e208c15eac4f8d6c5
Diffstat (limited to 'folio_daemon')
-rwxr-xr-xfolio_daemon/Android.mk22
-rw-r--r--folio_daemon/main.cpp147
2 files changed, 169 insertions, 0 deletions
diff --git a/folio_daemon/Android.mk b/folio_daemon/Android.mk
new file mode 100755
index 00000000..4ba85126
--- /dev/null
+++ b/folio_daemon/Android.mk
@@ -0,0 +1,22 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SHARED_LIBRARIES := \
+ libandroid \
+ libcutils \
+ liblog
+
+LOCAL_SRC_FILES := \
+ main.cpp
+
+LOCAL_C_INCLUDES :=
+
+LOCAL_CFLAGS := $(common_flags) -DLOG_TAG=\"folio_daemon\" -DLOG_NDEBUG=0
+
+LOCAL_CLANG := true
+LOCAL_MODULE := folio_daemon
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_OWNER := google
+LOCAL_PROPRIETARY_MODULE := true
+
+include $(BUILD_EXECUTABLE)
diff --git a/folio_daemon/main.cpp b/folio_daemon/main.cpp
new file mode 100644
index 00000000..417cffe2
--- /dev/null
+++ b/folio_daemon/main.cpp
@@ -0,0 +1,147 @@
+/*
+ * Copyright 2017 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 <fcntl.h>
+#include <unistd.h>
+#include <linux/input.h>
+#include <linux/uinput.h>
+#include <android/looper.h>
+#include <android/sensor.h>
+#include <cutils/log.h>
+
+// Hall-effect sensor type
+#define SENSOR_TYPE 33171016
+
+/*
+ * This simple daemon listens for events from the Hall-effect sensor and writes
+ * the appropriate SW_LID event to a uinput node. This allows the screen to be
+ * locked with a magnetic folio case.
+ */
+int main(void) {
+ int uinputFd;
+ int err;
+ struct uinput_user_dev uidev;
+ ASensorManager *sensorManager = nullptr;
+ ASensorRef hallSensor;
+ ALooper *looper;
+ ASensorEventQueue *eventQueue = nullptr;
+
+ ALOGI("Started");
+
+ uinputFd = TEMP_FAILURE_RETRY(open("/dev/uinput", O_WRONLY | O_NONBLOCK));
+ if (uinputFd < 0) {
+ ALOGE("Unable to open uinput node: %s", strerror(errno));
+ goto out;
+ }
+
+ err = TEMP_FAILURE_RETRY(ioctl(uinputFd, UI_SET_EVBIT, EV_SW))
+ | TEMP_FAILURE_RETRY(ioctl(uinputFd, UI_SET_EVBIT, EV_SYN))
+ | TEMP_FAILURE_RETRY(ioctl(uinputFd, UI_SET_SWBIT, SW_LID));
+ if (err != 0) {
+ ALOGE("Unable to enable SW_LID events: %s", strerror(errno));
+ goto out;
+ }
+
+ memset(&uidev, 0, sizeof (uidev));
+ snprintf(uidev.name, UINPUT_MAX_NAME_SIZE, "uinput-folio");
+ uidev.id.bustype = BUS_VIRTUAL;
+ uidev.id.vendor = 0;
+ uidev.id.product = 0;
+ uidev.id.version = 0;
+
+ err = TEMP_FAILURE_RETRY(write(uinputFd, &uidev, sizeof (uidev)));
+ if (err < 0) {
+ ALOGE("Write user device to uinput node failed: %s", strerror(errno));
+ goto out;
+ }
+
+ err = TEMP_FAILURE_RETRY(ioctl(uinputFd, UI_DEV_CREATE));
+ if (err < 0) {
+ ALOGE("Unable to create uinput device: %s", strerror(errno));
+ goto out;
+ }
+
+ ALOGI("Successfully registered uinput-folio for SW_LID events");
+
+ // Get Hall-effect sensor events from the NDK
+ sensorManager = ASensorManager_getInstanceForPackage(nullptr);
+ hallSensor = ASensorManager_getDefaultSensor(sensorManager, SENSOR_TYPE);
+ if (hallSensor == nullptr) {
+ ALOGE("Unable to get Hall-effect sensor");
+ goto out;
+ }
+
+ looper = ALooper_forThread();
+ if (looper == nullptr) {
+ looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS);
+ }
+
+ eventQueue = ASensorManager_createEventQueue(sensorManager, looper, 0, NULL,
+ NULL);
+ err = ASensorEventQueue_registerSensor(eventQueue, hallSensor,
+ ASensor_getMinDelay(hallSensor),
+ 10000);
+ if (err < 0) {
+ ALOGE("Unable to register for Hall-effect sensor events");
+ goto out;
+ }
+
+ ALOGI("Starting polling loop");
+
+ // Polling loop
+ while (ALooper_pollAll(-1, NULL, NULL, NULL) == 0) {
+ ASensorEvent sensorEvent;
+ while (ASensorEventQueue_getEvents(eventQueue, &sensorEvent, 1) > 0) {
+ // 1 means closed; 0 means open
+ int isClosed = sensorEvent.data[0] > 0.0f ? 1 : 0;
+ struct input_event event;
+ event.type = EV_SW;
+ event.code = SW_LID;
+ event.value = isClosed;
+ err = TEMP_FAILURE_RETRY(write(uinputFd, &event, sizeof (event)));
+ if (err < 0) {
+ ALOGE("Write EV_SW to uinput node failed: %s", strerror(errno));
+ goto out;
+ }
+
+ // Force a flush with an EV_SYN
+ event.type = EV_SYN;
+ event.code = SYN_REPORT;
+ event.value = 0;
+ err = TEMP_FAILURE_RETRY(write(uinputFd, &event, sizeof (event)));
+ if (err < 0) {
+ ALOGE("Write EV_SYN to uinput node failed: %s",
+ strerror(errno));
+ goto out;
+ }
+
+ ALOGI("Sent lid %s event", isClosed ? "closed" : "open");
+ }
+ }
+
+out:
+ // Clean up
+ if (sensorManager != nullptr && eventQueue != nullptr) {
+ ASensorManager_destroyEventQueue(sensorManager, eventQueue);
+ }
+
+ if (uinputFd >= 0) {
+ close(uinputFd);
+ }
+
+ // The loop can only be exited via failure or signal
+ return 1;
+}