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

Commit 14d26c51 authored by Nextbit's avatar Nextbit Committed by Adnan Begovic
Browse files

Recents long press: add pluggable implementation

Adds a new intent ACTION_RECENTS_LONG_PRESS for the
long press of the recents button. Other system applications
can register for the intent to provide custom handling.
Handlers of this intent are queried for in the settings
application, and if no handlers are found, the default
implementation falls back on ActionUtils.switchToLastApp().

The long press listener on the recents button is replaced
with a touch handler to allow for more custom handling.

Change-Id: I8a27ae0fe58d92a1626f0bd661c5f57c589fac17
parent 41255051
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -1248,6 +1248,14 @@ public class Intent implements Parcelable, Cloneable {
    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
    public static final String ACTION_SEARCH_LONG_PRESS = "android.intent.action.SEARCH_LONG_PRESS";

    /**
     * Activity Action: Start action associated with long press on the recents key.
     * <p>Input: Nothing
     * <p>Output: Nothing
     * @hide
     */
    public static final String ACTION_RECENTS_LONG_PRESS = "android.intent.action.RECENTS_LONG_PRESS";

    /**
     * Activity Action: The user pressed the "Report" button in the crash/ANR dialog.
     * This intent is delivered to the package which installed the application, usually
+9 −3
Original line number Diff line number Diff line
@@ -305,6 +305,14 @@ public class NavigationBarView extends LinearLayout {
        mDelegateHelper.setBar(phoneStatusBar);
    }

    public void disableSearchBar() {
        mDelegateHelper.setDisabled(true);
    }

    public void enableSearchBar() {
        mDelegateHelper.setDisabled(false);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (mDeadZone != null && event.getAction() == MotionEvent.ACTION_OUTSIDE) {
@@ -333,11 +341,10 @@ public class NavigationBarView extends LinearLayout {
    }

    /* package */ void setListeners(OnClickListener recentsClickListener,
            OnTouchListener recentsPreloadListener, OnLongClickListener recentsLongClickListener,
            OnTouchListener recentsPreloadListener,
            OnTouchListener homeSearchActionListener) {
        mRecentsClickListener = recentsClickListener;
        mRecentsPreloadListener = recentsPreloadListener;
        mRecentsLongClickListener = recentsLongClickListener;
        mHomeSearchActionListener = homeSearchActionListener;
        updateButtonListeners();
    }
@@ -360,7 +367,6 @@ public class NavigationBarView extends LinearLayout {
        if (recentView != null) {
            recentView.setOnClickListener(mRecentsClickListener);
            recentView.setOnTouchListener(mRecentsPreloadListener);
            recentView.setOnLongClickListener(mRecentsLongClickListener);
        }
        View homeView = findButton(NavbarEditor.NAVBAR_HOME);
        if (homeView != null) {
+95 −6
Original line number Diff line number Diff line
@@ -34,11 +34,11 @@ import android.animation.ObjectAnimator;
import android.animation.TimeInterpolator;
import android.app.ActivityManager;
import android.app.ActivityManagerNative;
import android.app.ActivityOptions;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.StatusBarManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
@@ -1097,14 +1097,104 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
        }
    };

    private View.OnLongClickListener mRecentsLongPressListener = new View.OnLongClickListener() {
    private Runnable mDefaultRecentsLongPressHandler = new Runnable() {
        @Override
        public boolean onLongClick(View v) {
        public void run() {
            mHandler.removeCallbacks(mDefaultRecentsLongPressHandler);
            cancelPreloadingRecentTasksList();
            return ActionUtils.switchToLastApp(mContext, mCurrentUserId);
            boolean switched = ActionUtils.switchToLastApp(mContext, mCurrentUserId);
            if (switched) {
                mNavigationBarView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
            }
            mRecentsLongPressed = true;
        }
    };

    private Runnable mIntentRecentsLongPressHandler = new Runnable() {
        @Override
        public void run() {
            mHandler.removeCallbacks(mIntentRecentsLongPressHandler);
            cancelPreloadingRecentTasksList();

            // allow touch events to leave the system ui
            mNavigationBarView.setSlippery(true);
            mNavigationBarView.disableSearchBar();
            mRecentsLongPressed = true;

            // Let the default activity handle this
            Intent intent = new Intent(Intent.ACTION_RECENTS_LONG_PRESS);
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                    | Intent.FLAG_ACTIVITY_CLEAR_TOP);
            ComponentName componentName = getRecentsTouchHandlerComponentName();
            if (componentName != null) {
                intent.setComponent(componentName);
                mContext.startActivityAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
            }
        }
    };
    private Runnable getRecentsLongPressHandler(boolean custom) {
        return custom ? mIntentRecentsLongPressHandler : mDefaultRecentsLongPressHandler;
    }

    private boolean mRecentsLongPressed = false;
    private View.OnTouchListener mRecentsTouchListener = new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            if (event.getAction() == MotionEvent.ACTION_DOWN) {
                boolean hasIntentHandler = hasRecentsTouchHandler();
                Runnable recentsLongPressHandler = getRecentsLongPressHandler(hasIntentHandler);
                mHandler.removeCallbacks(recentsLongPressHandler);
                mHandler.postDelayed(recentsLongPressHandler,
                        ViewConfiguration.getLongPressTimeout());
            } else if (event.getAction() == MotionEvent.ACTION_UP ||
                    event.getAction() == MotionEvent.ACTION_CANCEL) {
                recentsTouchCleanupHandler(hasRecentsTouchHandler());
            }
            return mRecentsPreloadOnTouchListener.onTouch(v, event);
        }
    };

    private void recentsTouchCleanupHandler(boolean hasIntentHandler) {
        if (hasIntentHandler && mRecentsLongPressed) {
            mNavigationBarView.setSlippery(false);
            mNavigationBarView.enableSearchBar();
        }
        mRecentsLongPressed = false;
        mHandler.removeCallbacks(getRecentsLongPressHandler(hasIntentHandler));
    }

    private ComponentName getRecentsTouchHandlerComponentName() {
        String componentString = Settings.Secure.getString(mContext.getContentResolver(),
                Settings.Secure.RECENTS_LONG_PRESS_ACTIVITY);
        return componentString == null ? null : ComponentName.unflattenFromString(componentString);
    }

    private boolean hasRecentsTouchHandler() {
        // Check if ACTION_RECENTS_LONG_PRESS has a registered handler
        PackageManager pm = mContext.getPackageManager();
        Intent intent = new Intent(Intent.ACTION_RECENTS_LONG_PRESS);

        ComponentName defaultComponent = getRecentsTouchHandlerComponentName();
        if (defaultComponent == null) {
            return false;
        }

        // Query PackageManager for all packages that can handle this intent
        List<ResolveInfo> activities = pm.queryIntentActivities(intent,
                PackageManager.MATCH_DEFAULT_ONLY);
        if (activities.size() > 0) {
            for (ResolveInfo info : activities) {
                // Check that we have a valid ComponentName before launching
                ComponentName targetComponent = new ComponentName(info.activityInfo.packageName,
                        info.activityInfo.name);
                if (targetComponent.equals(defaultComponent)) {
                    return true;
                }
            }
        }
        return false;
    }

    private int mShowSearchHoldoff = 0;
    private Runnable mShowSearchPanel = new Runnable() {
        public void run() {
@@ -1145,8 +1235,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,

    private void prepareNavigationBarView() {
        mNavigationBarView.reorient();
        mNavigationBarView.setListeners(mRecentsClickListener,
                mRecentsPreloadOnTouchListener, mRecentsLongPressListener,
        mNavigationBarView.setListeners(mRecentsClickListener, mRecentsTouchListener,
                mHomeSearchActionListener);
        updateSearchPanel();
    }