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

Commit 1ea28f1b authored by jt1134's avatar jt1134
Browse files

LockScreen: allow long-press actions from hardware keys (1/2)

Allow following actions with button long-presses on lockscreen:
* toggle flashlight (if available)
* play/pause/next/previous track selection
* toggle silent mode

Allow customizing of back, menu, and home buttons. Search
button events are completely ignored on the lockscreen.

Auto-detect hardware keys, only show appropriate menu
options based on the actual hardware keys available on the
device (or completely hide if there are no hardware keys).

Based largely on Danny Baumann's work from gingerbread.

Change-Id: I4c4aad62677b610934a0b621b5518f7c57e44a53
parent 611462a3
Loading
Loading
Loading
Loading
+18 −0
Original line number Diff line number Diff line
@@ -2704,6 +2704,24 @@ public final class Settings {
         */
        public static final String LOCKSCREEN_CLOCK_ALIGN = "lockscreen_clock_align";

        /**
         * Action for long-pressing back button on lock screen
         * @hide
         */
        public static final String LOCKSCREEN_LONG_BACK_ACTION = "lockscreen_long_back_action";

        /**
         * Action for long-pressing home button on lock screen
         * @hide
         */
        public static final String LOCKSCREEN_LONG_HOME_ACTION = "lockscreen_long_home_action";

        /**
         * Action for long-pressing menu button on lock screen
         * @hide
         */
        public static final String LOCKSCREEN_LONG_MENU_ACTION = "lockscreen_long_menu_action";

        /**
         * Show the pending notification counts as overlays on the status bar
         * @hide
+97 −0
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@ import android.graphics.drawable.LayerDrawable;
import android.graphics.drawable.StateListDrawable;
import android.media.AudioManager;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.Vibrator;
import android.provider.MediaStore;
import android.provider.Settings;
@@ -735,6 +736,17 @@ class LockScreen extends LinearLayout implements KeyguardScreen {

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK
                || keyCode == KeyEvent.KEYCODE_HOME
                || keyCode == KeyEvent.KEYCODE_MENU) {
            event.startTracking();
            return true;
        }
        return false;
    }

    @Override
    public boolean onKeyUp(int keyCode, KeyEvent event) {
        if ((keyCode == KeyEvent.KEYCODE_MENU && mEnableMenuKeyInLockScreen) ||
            (keyCode == KeyEvent.KEYCODE_HOME && mHomeUnlockScreen)) {
            mCallback.goToUnlockScreen();
@@ -742,6 +754,91 @@ class LockScreen extends LinearLayout implements KeyguardScreen {
        return false;
    }

    @Override
    public boolean onKeyLongPress(int keyCode, KeyEvent event) {
        if (handleKeyLongPress(mContext, keyCode)) {
            mCallback.pokeWakelock();
            return true;
        }
        return false;
    }

    private static final int ACTION_RESULT_RUN = 0;
    private static final int ACTION_RESULT_NOTRUN = 1;

    private static int runAction(Context context, String uri) {
        if ("FLASHLIGHT".equals(uri)) {
            context.sendBroadcast(new Intent("net.cactii.flash2.TOGGLE_FLASHLIGHT"));
            return ACTION_RESULT_RUN;
        } else if ("NEXT".equals(uri)) {
            sendMediaButtonEvent(context, KeyEvent.KEYCODE_MEDIA_NEXT);
            return ACTION_RESULT_RUN;
        } else if ("PREVIOUS".equals(uri)) {
            sendMediaButtonEvent(context, KeyEvent.KEYCODE_MEDIA_PREVIOUS);
            return ACTION_RESULT_RUN;
        } else if ("PLAYPAUSE".equals(uri)) {
            sendMediaButtonEvent(context, KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE);
            return ACTION_RESULT_RUN;
        } else if ("SOUND".equals(uri)) {
            toggleSilentMode(context);
            return ACTION_RESULT_RUN;
        }

        return ACTION_RESULT_NOTRUN;
    }

    public static boolean handleKeyLongPress(Context context, int keyCode) {
        String action = null;

        switch (keyCode) {
            case KeyEvent.KEYCODE_BACK:
                action = Settings.System.LOCKSCREEN_LONG_BACK_ACTION;
                break;
            case KeyEvent.KEYCODE_HOME:
                action = Settings.System.LOCKSCREEN_LONG_HOME_ACTION;
                break;
            case KeyEvent.KEYCODE_MENU:
                action = Settings.System.LOCKSCREEN_LONG_MENU_ACTION;
                break;
        }

        if (action != null) {
            String uri = Settings.System.getString(context.getContentResolver(), action);
            if (uri != null && runAction(context, uri) != ACTION_RESULT_NOTRUN) {
                return true;
            }
        }

        return false;
    }

    private static void sendMediaButtonEvent(Context context, int code) {
        long eventtime = SystemClock.uptimeMillis();

        Intent downIntent = new Intent(Intent.ACTION_MEDIA_BUTTON, null);
        KeyEvent downEvent = new KeyEvent(eventtime, eventtime, KeyEvent.ACTION_DOWN, code, 0);
        downIntent.putExtra(Intent.EXTRA_KEY_EVENT, downEvent);
        context.sendOrderedBroadcast(downIntent, null);

        Intent upIntent = new Intent(Intent.ACTION_MEDIA_BUTTON, null);
        KeyEvent upEvent = new KeyEvent(eventtime, eventtime, KeyEvent.ACTION_UP, code, 0);
        upIntent.putExtra(Intent.EXTRA_KEY_EVENT, upEvent);
        context.sendOrderedBroadcast(upIntent, null);
    }

    private static void toggleSilentMode(Context context) {
        final AudioManager am = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
        final Vibrator vib = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
        final boolean hasVib = vib == null ? false : vib.hasVibrator();
        if (am.getRingerMode() == AudioManager.RINGER_MODE_NORMAL) {
            am.setRingerMode(hasVib
                ? AudioManager.RINGER_MODE_VIBRATE
                : AudioManager.RINGER_MODE_SILENT);
        } else {
            am.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
        }
    }

    void updateConfiguration() {
        Configuration newConfig = getResources().getConfiguration();
        if (newConfig.orientation != mCreationOrientation) {
+21 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import android.content.res.Configuration;
import android.os.CountDownTimer;
import android.os.SystemClock;
import android.security.KeyStore;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.MotionEvent;
@@ -212,6 +213,26 @@ class PatternUnlockScreen extends LinearLayoutWithDefaultTouchRecepient
        mEnableFallback = state;
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK
                || keyCode == KeyEvent.KEYCODE_HOME
                || keyCode == KeyEvent.KEYCODE_MENU) {
            event.startTracking();
            return true;
        }
        return false;
    }

    @Override
    public boolean onKeyLongPress(int keyCode, KeyEvent event) {
        if (LockScreen.handleKeyLongPress(getContext(), keyCode)) {
            mCallback.pokeWakelock();
            return true;
        }
        return false;
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        // as long as the user is entering a pattern (i.e sending a touch
+17 −1
Original line number Diff line number Diff line
@@ -273,7 +273,7 @@ public class SimUnlockScreen extends LinearLayout implements KeyguardScreen, Vie
        }.start();
    }


    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            mCallback.goToLockScreen();
@@ -298,6 +298,22 @@ public class SimUnlockScreen extends LinearLayout implements KeyguardScreen, Vie
            return true;
        }

        if (keyCode == KeyEvent.KEYCODE_BACK
                || keyCode == KeyEvent.KEYCODE_MENU
                || keyCode == KeyEvent.KEYCODE_HOME) {
            event.startTracking();
            return true;
        }

        return false;
    }

    @Override
    public boolean onKeyLongPress(int keyCode, KeyEvent event) {
        if (LockScreen.handleKeyLongPress(getContext(), keyCode)) {
            mCallback.pokeWakelock();
            return true;
        }
        return false;
    }