Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1bd7a908 authored by Wilhelm Fitzpatrick's avatar Wilhelm Fitzpatrick Committed by Michael Bestas
Browse files

DeskClock: Add back flip and shake actions

Allow the alarm to be dismissed/snoozed by flipping or shaking

Picked from:

http://review.cyanogenmod.org/#/c/29894
http://review.cyanogenmod.org/#/c/80342
http://review.cyanogenmod.org/#/c/81204
http://review.cyanogenmod.org/#/c/94950

Authors/Contributors:

Artem Chep <artemchep@gmail.com>
Danny Baumann <dannybaumann@web.de>
Ronald Ramsay II <ronaldramsayii@gmail.com>
Danesh M <daneshm90@gmail.com>
Michael Bestas <mikeioannina@gmail.com>
Martin Brabham <mbrabham@cyngn.com>
Dan Pasanen <dan.pasanen@gmail.com> - Android 8.1 port

Change-Id: I222b6cd53a95db6f8662e7aef52aa6922d8a5d6a
parent 281ea21d
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!--
     Copyright (C) 2012-2016 The CyanogenMod Project
     Copyright (C) 2017-2018 The LineageOS Project

     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
@@ -15,6 +16,20 @@
     limitations under the License.
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">

    <!-- Setting title for the flip action setting. -->
    <string name="flip_action_title">Device flip action</string>

    <!-- Setting title for the shake action setting. -->
    <string name="shake_action_title">Device shake action</string>

    <!-- Entries listed in the setting flip and shake. -->
    <string-array name="action_setting_entries">
        <item>Snooze</item>
        <item>Dismiss</item>
        <item>Nothing</item>
    </string-array>

    <!-- Setting title for accessing the cLock widget settings -->
    <string name="menu_item_widget_settings">Widget settings</string>

+17 −1
Original line number Diff line number Diff line
@@ -86,6 +86,22 @@
            android:key="volume_button_setting"
            android:title="@string/volume_button_setting_title" />

        <com.android.deskclock.settings.SimpleMenuPreference
            android:defaultValue="0"
            android:dialogTitle="@string/flip_action_title"
            android:entries="@array/action_setting_entries"
            android:entryValues="@array/volume_button_setting_values"
            android:key="flip_action"
            android:title="@string/flip_action_title" />

        <com.android.deskclock.settings.SimpleMenuPreference
            android:defaultValue="0"
            android:dialogTitle="@string/shake_action_title"
            android:entries="@array/action_setting_entries"
            android:entryValues="@array/volume_button_setting_values"
            android:key="shake_action"
            android:title="@string/shake_action_title" />

        <com.android.deskclock.settings.SimpleMenuPreference
            android:dialogTitle="@string/week_start_title"
            android:entries="@array/week_start_entries"
+167 −0
Original line number Diff line number Diff line
@@ -21,6 +21,10 @@ import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Binder;
import android.os.IBinder;
import android.telephony.PhoneStateListener;
@@ -29,6 +33,7 @@ import android.telephony.TelephonyManager;
import com.android.deskclock.AlarmAlertWakeLock;
import com.android.deskclock.LogUtils;
import com.android.deskclock.R;
import com.android.deskclock.data.DataModel;
import com.android.deskclock.events.Events;
import com.android.deskclock.provider.AlarmInstance;

@@ -62,6 +67,14 @@ public class AlarmService extends Service {
    /** Private action used to stop an alarm with this service. */
    public static final String STOP_ALARM_ACTION = "STOP_ALARM";

    // constants for no action/snooze/dismiss
    private static final int ALARM_NO_ACTION = 0;
    private static final int ALARM_SNOOZE = 1;
    private static final int ALARM_DISMISS = 2;

    // default action for flip and shake
    private static final String DEFAULT_ACTION = Integer.toString(ALARM_NO_ACTION);

    /** Binder given to AlarmActivity. */
    private final IBinder mBinder = new Binder();

@@ -103,6 +116,9 @@ public class AlarmService extends Service {

    private TelephonyManager mTelephonyManager;
    private AlarmInstance mCurrentAlarm = null;
    private SensorManager mSensorManager;
    private int mFlipAction;
    private int mShakeAction;

    private void startAlarm(AlarmInstance instance) {
        LogUtils.v("AlarmService.start with instance: " + instance.mId);
@@ -118,6 +134,7 @@ public class AlarmService extends Service {
        mTelephonyManager.listen(mPhoneStateListener.init(), PhoneStateListener.LISTEN_CALL_STATE);
        AlarmKlaxon.start(this, mCurrentAlarm);
        sendBroadcast(new Intent(ALARM_ALERT_ACTION));
        attachListeners();
    }

    private void stopCurrentAlarm() {
@@ -136,6 +153,7 @@ public class AlarmService extends Service {
        stopForeground(true /* removeNotification */);

        mCurrentAlarm = null;
        detachListeners();
        AlarmAlertWakeLock.releaseCpuLock();
    }

@@ -181,6 +199,11 @@ public class AlarmService extends Service {
        filter.addAction(ALARM_DISMISS_ACTION);
        registerReceiver(mActionsReceiver, filter);
        mIsRegistered = true;

        // set up for flip and shake actions
        mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
        mFlipAction = DataModel.getDataModel().getFlipAction();
        mShakeAction = DataModel.getDataModel().getShakeAction();
    }

    @Override
@@ -264,4 +287,148 @@ public class AlarmService extends Service {
            }
        }
    }

    private final SensorEventListener mFlipListener = new SensorEventListener() {
        private static final int FACE_UP_LOWER_LIMIT = -45;
        private static final int FACE_UP_UPPER_LIMIT = 45;
        private static final int FACE_DOWN_UPPER_LIMIT = 135;
        private static final int FACE_DOWN_LOWER_LIMIT = -135;
        private static final int TILT_UPPER_LIMIT = 45;
        private static final int TILT_LOWER_LIMIT = -45;
        private static final int SENSOR_SAMPLES = 3;

        private boolean mWasFaceUp;
        private boolean[] mSamples = new boolean[SENSOR_SAMPLES];
        private int mSampleIndex;

        @Override
        public void onAccuracyChanged(Sensor sensor, int acc) {
        }

        @Override
        public void onSensorChanged(SensorEvent event) {
            // Add a sample overwriting the oldest one. Several samples
            // are used
            // to avoid the erroneous values the sensor sometimes
            // returns.
            float y = event.values[1];
            float z = event.values[2];

            if (!mWasFaceUp) {
                // Check if its face up enough.
                mSamples[mSampleIndex] = y > FACE_UP_LOWER_LIMIT
                        && y < FACE_UP_UPPER_LIMIT
                        && z > TILT_LOWER_LIMIT && z < TILT_UPPER_LIMIT;

                // The device first needs to be face up.
                boolean faceUp = true;
                for (boolean sample : mSamples) {
                    faceUp = faceUp && sample;
                }
                if (faceUp) {
                    mWasFaceUp = true;
                    for (int i = 0; i < SENSOR_SAMPLES; i++) {
                        mSamples[i] = false;
                    }
                }
            } else {
                // Check if its face down enough. Note that wanted
                // values go from FACE_DOWN_UPPER_LIMIT to 180
                // and from -180 to FACE_DOWN_LOWER_LIMIT
                mSamples[mSampleIndex] = (y > FACE_DOWN_UPPER_LIMIT || y < FACE_DOWN_LOWER_LIMIT)
                        && z > TILT_LOWER_LIMIT
                        && z < TILT_UPPER_LIMIT;

                boolean faceDown = true;
                for (boolean sample : mSamples) {
                    faceDown = faceDown && sample;
                }
                if (faceDown) {
                    handleAction(mFlipAction);
                }
            }

            mSampleIndex = ((mSampleIndex + 1) % SENSOR_SAMPLES);
        }
    };

    private final SensorEventListener mShakeListener = new SensorEventListener() {
        private static final float SENSITIVITY = 16;
        private static final int BUFFER = 5;
        private float[] gravity = new float[3];
        private float average = 0;
        private int fill = 0;

        @Override
        public void onAccuracyChanged(Sensor sensor, int acc) {
        }

        public void onSensorChanged(SensorEvent event) {
            final float alpha = 0.8F;

            for (int i = 0; i < 3; i++) {
                gravity[i] = alpha * gravity[i] + (1 - alpha) * event.values[i];
            }

            float x = event.values[0] - gravity[0];
            float y = event.values[1] - gravity[1];
            float z = event.values[2] - gravity[2];

            if (fill <= BUFFER) {
                average += Math.abs(x) + Math.abs(y) + Math.abs(z);
                fill++;
            } else {
                if (average / BUFFER >= SENSITIVITY) {
                    handleAction(mShakeAction);
                }
                average = 0;
                fill = 0;
            }
        }
    };

    private void attachListeners() {
        if (mFlipAction != ALARM_NO_ACTION) {
            mSensorManager.registerListener(mFlipListener,
                    mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION),
                    SensorManager.SENSOR_DELAY_NORMAL,
                    300 * 1000); //batch every 300 milliseconds
        }

        if (mShakeAction != ALARM_NO_ACTION) {
            mSensorManager.registerListener(mShakeListener,
                    mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
                    SensorManager.SENSOR_DELAY_GAME,
                    50 * 1000); //batch every 50 milliseconds
        }
    }

    private void detachListeners() {
        if (mFlipAction != ALARM_NO_ACTION) {
            mSensorManager.unregisterListener(mFlipListener);
        }
        if (mShakeAction != ALARM_NO_ACTION) {
            mSensorManager.unregisterListener(mShakeListener);
        }
    }

    private void handleAction(int action) {
        switch (action) {
            case ALARM_SNOOZE:
                // Setup Snooze Action
                startService(AlarmStateManager.createStateChangeIntent(this,
                        AlarmStateManager.ALARM_SNOOZE_TAG, mCurrentAlarm,
                        AlarmInstance.SNOOZE_STATE));
                break;
            case ALARM_DISMISS:
                // Setup Dismiss Action
                startService(AlarmStateManager.createStateChangeIntent(this,
                        AlarmStateManager.ALARM_DISMISS_TAG, mCurrentAlarm,
                        AlarmInstance.DISMISSED_STATE));
                break;
            case ALARM_NO_ACTION:
            default:
                break;
        }
    }
}
+8 −0
Original line number Diff line number Diff line
@@ -78,6 +78,14 @@ final class AlarmModel {
        return mSettingsModel.getSnoozeLength();
    }

    int getFlipAction() {
        return mSettingsModel.getFlipAction();
    }

    int getShakeAction() {
        return mSettingsModel.getShakeAction();
    }

    /**
     * This receiver is notified when system settings change. Cached information built on
     * those system settings must be cleared.
+8 −0
Original line number Diff line number Diff line
@@ -735,6 +735,14 @@ public final class DataModel {
        return mAlarmModel.getSnoozeLength();
    }

    public int getFlipAction() {
        return mAlarmModel.getFlipAction();
    }

    public int getShakeAction() {
        return mAlarmModel.getShakeAction();
    }

    //
    // Stopwatch
    //
Loading