diff --git a/DeviceSettings/res/values-de-rDE/strings.xml b/DeviceSettings/res/values-de-rDE/strings.xml
index 4c722f7a..ca2aab91 100644
--- a/DeviceSettings/res/values-de-rDE/strings.xml
+++ b/DeviceSettings/res/values-de-rDE/strings.xml
@@ -91,4 +91,6 @@
Wert zwischen %1d und %2d
Inaktivitätsdisplay
Graustufen-Modus
+ Aktiviere Aufwecken mit Flip Cover
+ Schalte das Gerät AN und AUS mit einem magnetischen Flip Cover
diff --git a/DeviceSettings/res/values-es-rES/strings.xml b/DeviceSettings/res/values-es-rES/strings.xml
index 9c9d64fc..d7ca6084 100644
--- a/DeviceSettings/res/values-es-rES/strings.xml
+++ b/DeviceSettings/res/values-es-rES/strings.xml
@@ -107,6 +107,10 @@
Amoled Extremo
Amoled caliente
Mamba híbrido
+
+ Despertar con funda flip
+ Activar levantamiento con funda flip
+ Despertar dispositivo con una funda flip magnética
Valor por defecto
diff --git a/DeviceSettings/res/values-in-rID/strings.xml b/DeviceSettings/res/values-in-rID/strings.xml
index 11d8c1b9..bf980116 100644
--- a/DeviceSettings/res/values-in-rID/strings.xml
+++ b/DeviceSettings/res/values-in-rID/strings.xml
@@ -112,6 +112,9 @@
Amoled hangat
Hibrid
+ Flip cover nyala
+ Aktifkan Flip Cover nyala
+ Nyalakan perangkat saat flip cover magnetik dibuka
@string/presets_dialog_title
Reset
diff --git a/DeviceSettings/res/values-ja-rJP/strings.xml b/DeviceSettings/res/values-ja-rJP/strings.xml
index 647ddeaa..558fb76f 100644
--- a/DeviceSettings/res/values-ja-rJP/strings.xml
+++ b/DeviceSettings/res/values-ja-rJP/strings.xml
@@ -106,6 +106,8 @@
暖色 AMOLED
Hybrid Mamba
+
+
@string/presets_dialog_title
リセット
@@ -114,5 +116,9 @@
新しい値を選択して下さい
既定値
値は %1$d と %2$d の間です
-
+
+
+ フリップカバーの復帰
+ フリップカバーの復帰の有効化
+ マグネットフリップカバーでスリープ解除する
diff --git a/DeviceSettings/res/values-pt-rBR/strings.xml b/DeviceSettings/res/values-pt-rBR/strings.xml
index e4660ac9..f37fa314 100644
--- a/DeviceSettings/res/values-pt-rBR/strings.xml
+++ b/DeviceSettings/res/values-pt-rBR/strings.xml
@@ -114,6 +114,9 @@
Amoled Quente
Mamba Híbrida
+ Flip Cover
+ Ativar a tela com Flip Cover
+ Ativa a tela ao usar uma Flip Cover magnética
@string/presets_dialog_title
Redefinir
diff --git a/DeviceSettings/res/values-ru-rRU/strings.xml b/DeviceSettings/res/values-ru-rRU/strings.xml
index 07170491..ade6c345 100644
--- a/DeviceSettings/res/values-ru-rRU/strings.xml
+++ b/DeviceSettings/res/values-ru-rRU/strings.xml
@@ -114,6 +114,9 @@
Теплый Amoled
Гибридная Мамба
+ Пробуждение умным чехлом
+ Включить пробуждение откидной крышкой
+ Пробуждение устройства через магнитную откидную крышку
@string/presets_dialog_title
Сбросить
diff --git a/DeviceSettings/res/values-sk-rSK/strings.xml b/DeviceSettings/res/values-sk-rSK/strings.xml
index e1c95025..e7888eea 100644
--- a/DeviceSettings/res/values-sk-rSK/strings.xml
+++ b/DeviceSettings/res/values-sk-rSK/strings.xml
@@ -112,6 +112,9 @@
Teplý - Amoled
Hybrid Mamba
+ Zobudenie preklopením krytu
+ Povoliť zobudenie preklopením krytu
+ Zobudenia zariadenia magnetickým krytom
@string/presets_dialog_title
Resetovať
diff --git a/DeviceSettings/res/values/strings.xml b/DeviceSettings/res/values/strings.xml
index 72c70195..ccc61816 100644
--- a/DeviceSettings/res/values/strings.xml
+++ b/DeviceSettings/res/values/strings.xml
@@ -69,6 +69,9 @@
Warm Amoled
Hybrid Mamba
+ Flip Cover Wakeup
+ Enable Flip Cover Wakeup
+ Wakeup device via magnetic Flip Cover
@string/presets_dialog_title
Reset
diff --git a/DeviceSettings/res/xml/preferences_xiaomi_parts.xml b/DeviceSettings/res/xml/preferences_xiaomi_parts.xml
index e360cb4d..d748a815 100644
--- a/DeviceSettings/res/xml/preferences_xiaomi_parts.xml
+++ b/DeviceSettings/res/xml/preferences_xiaomi_parts.xml
@@ -15,7 +15,6 @@
-->
-
@@ -149,4 +148,15 @@
+
+
+
+
diff --git a/DeviceSettings/src/org/lineageos/settings/device/BootReceiver.java b/DeviceSettings/src/org/lineageos/settings/device/BootReceiver.java
index dccf5754..5914c0d5 100644
--- a/DeviceSettings/src/org/lineageos/settings/device/BootReceiver.java
+++ b/DeviceSettings/src/org/lineageos/settings/device/BootReceiver.java
@@ -77,6 +77,10 @@ public class BootReceiver extends BroadcastReceiver implements Utils {
// Vibration Strength
FileUtils.setValue(DeviceSettings.VIBRATION_STRENGTH_PATH, Settings.Secure.getInt(
context.getContentResolver(), DeviceSettings.PREF_VIBRATION_STRENGTH, 80) / 100.0 * (DeviceSettings.MAX_VIBRATION - DeviceSettings.MIN_VIBRATION) + DeviceSettings.MIN_VIBRATION);
+ FileUtils.setValue(DeviceSettings.HALL_WAKEUP_PATH, Settings.Secure.getInt(
+ context.getContentResolver(), DeviceSettings.PREF_HALL_WAKEUP, 1) == 1 ? "Y" : "N");
+ FileUtils.setProp(DeviceSettings.HALL_WAKEUP_PROP, Settings.Secure.getInt(
+ context.getContentResolver(), DeviceSettings.PREF_HALL_WAKEUP, 1) == 1);
// Dirac
context.startService(new Intent(context, DiracService.class));
diff --git a/DeviceSettings/src/org/lineageos/settings/device/DeviceSettings.java b/DeviceSettings/src/org/lineageos/settings/device/DeviceSettings.java
index e3c83290..e996d196 100644
--- a/DeviceSettings/src/org/lineageos/settings/device/DeviceSettings.java
+++ b/DeviceSettings/src/org/lineageos/settings/device/DeviceSettings.java
@@ -69,6 +69,11 @@ public class DeviceSettings extends PreferenceFragment implements
private static final String PREF_DEVICE_DOZE = "device_doze";
private static final String PREF_DEVICE_KCAL = "device_kcal";
+ private static final String CATEGORY_HALL_WAKEUP = "hall_wakeup";
+ public static final String PREF_HALL_WAKEUP = "hall";
+ public static final String HALL_WAKEUP_PATH = "/sys/module/hall/parameters/hall_toggle";
+ public static final String HALL_WAKEUP_PROP = "persist.service.folio_daemon";
+
private static final String DEVICE_DOZE_PACKAGE_NAME = "com.advanced.settings.doze";
private static final String DEVICE_JASON_PACKAGE_NAME = "org.lineageos.settings.devicex";
@@ -166,6 +171,13 @@ public class DeviceSettings extends PreferenceFragment implements
mPreset = (SecureSettingListPreference) findPreference(PREF_PRESET);
mPreset.setOnPreferenceChangeListener(this);
+ if (FileUtils.fileWritable(HALL_WAKEUP_PATH)) {
+ SecureSettingSwitchPreference hall = (SecureSettingSwitchPreference) findPreference(PREF_HALL_WAKEUP);
+ hall.setChecked(FileUtils.getValue(HALL_WAKEUP_PATH).equals("Y"));
+ hall.setOnPreferenceChangeListener(this);
+ } else {
+ getPreferenceScreen().removePreference(findPreference(CATEGORY_HALL_WAKEUP));
+ }
}
@Override
@@ -220,6 +232,11 @@ public class DeviceSettings extends PreferenceFragment implements
}
break;
+ case PREF_HALL_WAKEUP:
+ FileUtils.setValue(HALL_WAKEUP_PATH, (boolean) value ? "Y" : "N");
+ FileUtils.setProp(HALL_WAKEUP_PROP, (boolean) value);
+ break;
+
case PREF_KEY_FPS_INFO:
boolean enabled = (boolean) value;
Intent fpsinfo = new Intent(this.getContext(), FPSInfoService.class);
diff --git a/folio_daemon/Android.bp b/folio_daemon/Android.bp
new file mode 100755
index 00000000..c609cfb1
--- /dev/null
+++ b/folio_daemon/Android.bp
@@ -0,0 +1,21 @@
+cc_binary {
+ name: "folio_daemon",
+
+ shared_libs: [
+ "libandroid",
+ "libcutils",
+ "liblog",
+ ],
+
+ srcs: ["main.cpp"],
+
+ cflags: [
+ "-DLOG_TAG=\"folio_daemon\"",
+ "-DLOG_NDEBUG=0",
+ "-Wall",
+ "-Werror",
+ ],
+
+ owner: "google",
+
+}
diff --git a/folio_daemon/main.cpp b/folio_daemon/main.cpp
new file mode 100644
index 00000000..1cda1ce5
--- /dev/null
+++ b/folio_daemon/main.cpp
@@ -0,0 +1,182 @@
+/*
+ * 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
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+// Hall-effect sensor type
+#define SENSOR_TYPE 33171016
+
+#define RETRY_LIMIT 120
+#define RETRY_PERIOD 30 // 30 seconds
+#define WARN_PERIOD (time_t)300 // 5 minutes
+
+/*
+ * 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;
+ time_t lastWarn = 0;
+ int attemptCount = 0;
+
+ 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);
+ /*
+ * As long as we are unable to get the sensor handle, periodically retry
+ * and emit an error message at a low frequency to prevent high CPU usage
+ * and log spam. If we simply exited with an error here, we would be
+ * immediately restarted and fail in the same way indefinitely.
+ */
+ while (true) {
+ time_t now = time(NULL);
+ hallSensor = ASensorManager_getDefaultSensor(sensorManager,
+ SENSOR_TYPE);
+ if (hallSensor != nullptr) {
+ break;
+ }
+
+ if (++attemptCount >= RETRY_LIMIT) {
+ ALOGE("Retries exhausted; exiting");
+ goto out;
+ } else if (now > lastWarn + WARN_PERIOD) {
+ ALOGE("Unable to get Hall-effect sensor");
+ lastWarn = now;
+ }
+
+ sleep(RETRY_PERIOD);
+ }
+
+ 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) {
+ int eventCount = 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");
+ eventCount++;
+ }
+
+ if (eventCount == 0) {
+ ALOGE("Poll returned with zero events: %s", strerror(errno));
+ break;
+ }
+ }
+
+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;
+}
diff --git a/rootdir/etc/init.target.rc b/rootdir/etc/init.target.rc
index 8ee4d26d..12d64d25 100755
--- a/rootdir/etc/init.target.rc
+++ b/rootdir/etc/init.target.rc
@@ -465,6 +465,18 @@ service dcvs-sh /vendor/bin/init.qti.dcvs.sh
on property:vendor.dcvs.prop=1
start dcvs-sh
+service folio_daemon /system/bin/folio_daemon
+ class late_start
+ user system
+ group system uhid
+ disabled
+
+on property:persist.service.folio_daemon=0
+ stop folio_daemon
+
+on property:persist.service.folio_daemon=1
+ start folio_daemon
+
service ppd /system/vendor/bin/mm-pp-dpps
class late_start
user system
diff --git a/rootdir/etc/init.xiaomi_parts.rc b/rootdir/etc/init.xiaomi_parts.rc
index cfb4fa64..47b32c05 100644
--- a/rootdir/etc/init.xiaomi_parts.rc
+++ b/rootdir/etc/init.xiaomi_parts.rc
@@ -15,9 +15,11 @@
#
on boot
- # Haptic strength
+ # XiaomiParts
chown system system /sys/devices/virtual/timed_output/vibrator/vtg_level
chmod 0660 /sys/devices/virtual/timed_output/vibrator/vtg_level
+ chown system system /sys/module/hall/parameters/hall_toggle
+ chmod 0660 /sys/module/hall/parameters/hall_toggle
# FPS
chown system system /sys/devices/virtual/graphics/fb0/measured_fps
diff --git a/sdm660.mk b/sdm660.mk
index 2b6e4198..20d1caf7 100644
--- a/sdm660.mk
+++ b/sdm660.mk
@@ -203,6 +203,10 @@ PRODUCT_PACKAGES += \
android.hardware.drm@1.4-service.clearkey \
android.hardware.drm@1.4.vendor
+# Folio
+PRODUCT_PACKAGES += \
+ folio_daemon
+
# Freeform Multiwindow
PRODUCT_COPY_FILES += \
frameworks/native/data/etc/android.software.freeform_window_management.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.software.freeform_window_management.xml
diff --git a/sepolicy/private/file_contexts b/sepolicy/private/file_contexts
index e59ed67c..3bc206b5 100644
--- a/sepolicy/private/file_contexts
+++ b/sepolicy/private/file_contexts
@@ -1,3 +1,3 @@
# Executables
/system/bin/chargeonlymode u:object_r:charger_exec:s0
-
+/system/bin/folio_daemon u:object_r:folio_daemon_exec:s0
diff --git a/sepolicy/private/folio_daemon.te b/sepolicy/private/folio_daemon.te
new file mode 100644
index 00000000..f48a3b2f
--- /dev/null
+++ b/sepolicy/private/folio_daemon.te
@@ -0,0 +1,15 @@
+type folio_daemon, domain, coredomain;
+type folio_daemon_exec, system_file_type, exec_type, file_type;
+
+init_daemon_domain(folio_daemon)
+
+allow folio_daemon binder_device:chr_file rw_file_perms;
+allow folio_daemon uhid_device:chr_file rw_file_perms;
+
+allow folio_daemon system_server:unix_stream_socket rw_socket_perms_no_ioctl;
+
+binder_use(folio_daemon)
+binder_call(folio_daemon, system_server)
+
+allow folio_daemon sensorservice_service:service_manager find;
+allow folio_daemon permission_service:service_manager find;
diff --git a/sepolicy/private/system_server.te b/sepolicy/private/system_server.te
index 1e735c29..d8bf45a4 100644
--- a/sepolicy/private/system_server.te
+++ b/sepolicy/private/system_server.te
@@ -1,3 +1,4 @@
+binder_call(system_server, folio_daemon)
# Allow system_server to set persist_camera_prop
get_prop(system_server, vendor_persist_camera_prop)
diff --git a/sepolicy/vendor/file.te b/sepolicy/vendor/file.te
index 6dc994f1..25f44f84 100644
--- a/sepolicy/vendor/file.te
+++ b/sepolicy/vendor/file.te
@@ -14,6 +14,9 @@ type sysfs_earpiecegain, sysfs_type, fs_type;
# HVDCP
type vendor_sysfs_hvdcp, fs_type, sysfs_type;
+# Hall Switch
+type hall_dev, sysfs_type, fs_type;
+
# Kcal
type kcal_dev, sysfs_type, fs_type;
diff --git a/sepolicy/vendor/file_contexts b/sepolicy/vendor/file_contexts
index 188ec11d..06b4caa5 100644
--- a/sepolicy/vendor/file_contexts
+++ b/sepolicy/vendor/file_contexts
@@ -29,6 +29,9 @@
/bt_firmware(/.*)? u:object_r:bt_firmware_file:s0
/persist(/.*)? u:object_r:persist_file:s0
+# Hall Switch
+/sys/module/hall/parameters(/.*)? u:object_r:hall_dev:s0
+
# Hexagon DSP-side executable needed for Halide operation
# This is labeled as public_adsprpcd_file as it needs to be read by apps
# (e.g. Google Camera App)
diff --git a/sepolicy/vendor/property_contexts b/sepolicy/vendor/property_contexts
index af6b9436..419a336e 100644
--- a/sepolicy/vendor/property_contexts
+++ b/sepolicy/vendor/property_contexts
@@ -40,6 +40,9 @@ ro.boot.fp. u:object_r:hal_fingerprint_prop:s0
ro.boot.fpsensor u:object_r:hal_fingerprint_prop:s0
sys.fp. u:object_r:hal_fingerprint_prop:s0
+# Hall wakeup
+persist.service.folio_daemon u:object_r:system_prop:s0
+
# Media
gpu.stats.debug.level u:object_r:vendor_default_prop:s0
diff --git a/sepolicy/vendor/system_app.te b/sepolicy/vendor/system_app.te
index 71516fcc..bede6c45 100644
--- a/sepolicy/vendor/system_app.te
+++ b/sepolicy/vendor/system_app.te
@@ -1,4 +1,6 @@
allow system_app blkio_dev:dir search;
+allow system_app hall_dev:file rw_file_perms;
+allow system_app hall_dev:dir search;
allow system_app kcal_dev:dir search;
allow system_app kcal_dev:file rw_file_perms;
allow system_app proc_vmallocinfo:file read;
diff --git a/sepolicy/vendor/ueventd.te b/sepolicy/vendor/ueventd.te
index 985c8ec4..9d1e2181 100644
--- a/sepolicy/vendor/ueventd.te
+++ b/sepolicy/vendor/ueventd.te
@@ -1 +1,4 @@
+allow ueventd hall_dev:dir r_dir_perms;
+allow ueventd hall_dev:file rw_file_perms;
+allow ueventd hall_dev:lnk_file r_file_perms;
allow ueventd metadata_file:dir search;