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

Commit ea633ce2 authored by John Spurlock's avatar John Spurlock Committed by Android (Google) Code Review
Browse files

Merge "Reveal hideybars using system gesture."

parents ce74a074 57306e6b
Loading
Loading
Loading
Loading
+21 −24
Original line number Diff line number Diff line
@@ -152,8 +152,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
    static public final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey";
    static public final String SYSTEM_DIALOG_REASON_ASSIST = "assist";

    static public final String ACTION_HIDEYBARS = "android.intent.action.HIDEYBARS";

    /**
     * These are the system UI flags that, when changing, can cause the layout
     * of the screen to change.
@@ -559,12 +557,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
    private static final int HIDEYBARS_HIDING = 2;
    private int mHideybars;

    BroadcastReceiver mHideybarsReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
           receivedHideybars(intent.getAction());
        }
    };
    private InputChannel mSystemGestureInputChannel;
    private InputEventReceiver mSystemGestures;

    IStatusBarService getStatusBarService() {
        synchronized (mServiceAquireLock) {
@@ -918,10 +912,15 @@ public class PhoneWindowManager implements WindowManagerPolicy {
        filter = new IntentFilter(Intent.ACTION_USER_SWITCHED);
        context.registerReceiver(mMultiuserReceiver, filter);

        // register for hideybars
        filter = new IntentFilter();
        filter.addAction(ACTION_HIDEYBARS);
        context.registerReceiver(mHideybarsReceiver, filter);
        // monitor for system gestures
        mSystemGestureInputChannel = mWindowManagerFuncs.monitorInput("SystemGestures");
        mSystemGestures = new SystemGestures(mSystemGestureInputChannel,
                mHandler.getLooper(), context,
                new SystemGestures.Callbacks() {
                    @Override
                    public void onSwipeFromTop() {
                        showHideybars();
                    }});

        mVibrator = (Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE);
        mLongPressVibePattern = getLongIntArray(mContext.getResources(),
@@ -4118,9 +4117,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
        }
    };

    private void receivedHideybars(String action) {
    private void showHideybars() {
        synchronized(mLock) {
            if (action.equals(ACTION_HIDEYBARS)) {
            if (mHideybars == HIDEYBARS_SHOWING) {
                if (DEBUG) Slog.d(TAG, "Not showing hideybars, already shown");
                return;
@@ -4133,7 +4131,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
            updateSystemUiVisibilityLw();
        }
    }
    }

    @Override
    public void screenTurnedOff(int why) {
+159 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2013 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.
 */

package com.android.internal.policy.impl;

import android.content.Context;
import android.os.Looper;
import android.util.Slog;
import android.view.InputChannel;
import android.view.InputDevice;
import android.view.InputEvent;
import android.view.InputEventReceiver;
import android.view.MotionEvent;

/*
 * Listens for system-wide input gestures, firing callbacks when detected.
 * @hide
 */
public class SystemGestures extends InputEventReceiver {
    private static final String TAG = "SystemGestures";
    private static final boolean DEBUG = false;
    private static final long SWIPE_TIMEOUT_MS = 500;
    private static final int MAX_TRACKED_POINTERS = 32;  // max per input system
    private static final int UNTRACKED_POINTER = -1;

    private final int mSwipeStartThreshold;
    private final int mSwipeEndThreshold;
    private final Callbacks mCallbacks;
    private final int[] mDownPointerId = new int[MAX_TRACKED_POINTERS];
    private final float[] mDownY = new float[MAX_TRACKED_POINTERS];
    private final long[] mDownTime = new long[MAX_TRACKED_POINTERS];

    private int mDownPointers;
    private boolean mSwipeFromTopFireable;

    public SystemGestures(InputChannel inputChannel, Looper looper,
            Context context, Callbacks callbacks) {
        super(inputChannel, looper);
        mCallbacks = checkNull("callbacks", callbacks);
        mSwipeStartThreshold = checkNull("context", context).getResources()
                .getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
        mSwipeEndThreshold = mSwipeStartThreshold * 2;
    }

    private static <T> T checkNull(String name, T arg) {
        if (arg == null) {
            throw new IllegalArgumentException(name + " must not be null");
        }
        return arg;
    }

    @Override
    public void onInputEvent(InputEvent event) {
        if (event instanceof MotionEvent && event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
            onPointerMotionEvent((MotionEvent) event);
        }
        finishInputEvent(event, false /*handled*/);
    }

    private void onPointerMotionEvent(MotionEvent event) {
        switch (event.getActionMasked()) {
            case MotionEvent.ACTION_DOWN:
                mSwipeFromTopFireable = true;
                mDownPointers = 0;
                captureDown(event, 0);
                break;
            case MotionEvent.ACTION_POINTER_DOWN:
                captureDown(event, event.getActionIndex());
                break;
            case MotionEvent.ACTION_MOVE:
                if (mSwipeFromTopFireable && detectSwipeFromTop(event)) {
                    mSwipeFromTopFireable = false;
                    if (DEBUG) Slog.d(TAG, "Firing onSwipeFromTop");
                    mCallbacks.onSwipeFromTop();
                }
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                mSwipeFromTopFireable = false;
                break;
            default:
                if (DEBUG) Slog.d(TAG, "Ignoring " + event);
        }
    }

    private void captureDown(MotionEvent event, int pointerIndex) {
        final int pointerId = event.getPointerId(pointerIndex);
        final int i = findIndex(pointerId);
        if (DEBUG) Slog.d(TAG, "pointer " + pointerId +
                " down pointerIndex=" + pointerIndex + " trackingIndex=" + i);
        if (i != UNTRACKED_POINTER) {
            mDownY[i] = event.getY(pointerIndex);
            mDownTime[i] = event.getEventTime();
            if (DEBUG) Slog.d(TAG, "pointer " + pointerId + " down y=" + mDownY[i]);
        }
    }

    private int findIndex(int pointerId) {
        for (int i = 0; i < mDownPointers; i++) {
            if (mDownPointerId[i] == pointerId) {
                return i;
            }
        }
        if (mDownPointers == MAX_TRACKED_POINTERS || pointerId == MotionEvent.INVALID_POINTER_ID) {
            return UNTRACKED_POINTER;
        }
        mDownPointerId[mDownPointers++] = pointerId;
        return mDownPointers - 1;
    }

    private boolean detectSwipeFromTop(MotionEvent move) {
        final int historySize = move.getHistorySize();
        final int pointerCount = move.getPointerCount();
        for (int p = 0; p < pointerCount; p++) {
            final int pointerId = move.getPointerId(p);
            final int i = findIndex(pointerId);
            if (i != UNTRACKED_POINTER) {
                for (int h = 0; h < historySize; h++) {
                    final long time = move.getHistoricalEventTime(h);
                    final float y = move.getHistoricalY(p,  h);
                    if (detectSwipeFromTop(i, time, y)) {
                        return true;
                    }
                }
                if (detectSwipeFromTop(i, move.getEventTime(), move.getY(p))) {
                    return true;
                }
            }
        }
        return false;
    }

    private boolean detectSwipeFromTop(int i, long time, float y) {
        final float fromY = mDownY[i];
        final long elapsed = time - mDownTime[i];
        if (DEBUG) Slog.d(TAG, "pointer " + mDownPointerId[i]
                + " moved from.y=" + fromY + " to.y=" + y + " in " + elapsed);
        return fromY <= mSwipeStartThreshold
                && y > fromY + mSwipeEndThreshold
                && elapsed < SWIPE_TIMEOUT_MS;
    }

    interface Callbacks {
        void onSwipeFromTop();
    }
}