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

Commit b8a5fe7b authored by David van Tonder's avatar David van Tonder Committed by Gerrit Code Review
Browse files

Merge "Adapt navigation bar's long press behaviour for pie controls" into cm-10.1

parents 44e5f6ca 41cb63ab
Loading
Loading
Loading
Loading
+63 −0
Original line number Diff line number Diff line
package com.android.internal.util.cm;

import android.app.ActivityManagerNative;
import android.app.IActivityManager;
import android.app.ActivityManager.RunningAppProcessInfo;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ResolveInfo;
import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
import android.provider.Settings;

import java.util.List;

public class DevUtils {

    /**
     * Kills the top most / most recent user application, but leaves out the launcher.
     * This is function governed by {@link Settings.Secure.KILL_APP_LONGPRESS_BACK}.
     *
     * @param context the current context, used to retrieve the package manager.
     * @return {@code true} when a user application was found and closed.
     */
    public static boolean killForegroundApplication(Context context) {
        boolean targetKilled = false;
        try {
            final Intent intent = new Intent(Intent.ACTION_MAIN);
            String defaultHomePackage = "com.android.launcher";
            intent.addCategory(Intent.CATEGORY_HOME);
            final ResolveInfo res = context.getPackageManager().resolveActivity(intent, 0);
            if (res.activityInfo != null && !res.activityInfo.packageName.equals("android")) {
                defaultHomePackage = res.activityInfo.packageName;
            }
            IActivityManager am = ActivityManagerNative.getDefault();
            List<RunningAppProcessInfo> apps = am.getRunningAppProcesses();
            for (RunningAppProcessInfo appInfo : apps) {
                int uid = appInfo.uid;
                // Make sure it's a foreground user application (not system,
                // root, phone, etc.)
                if (uid >= Process.FIRST_APPLICATION_UID && uid <= Process.LAST_APPLICATION_UID
                        && appInfo.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
                    if (appInfo.pkgList != null && (appInfo.pkgList.length > 0)) {
                        for (String pkg : appInfo.pkgList) {
                            if (!pkg.equals("com.android.systemui") && !pkg.equals(defaultHomePackage)) {
                                am.forceStopPackage(pkg, UserHandle.USER_CURRENT);
                                targetKilled = true;
                                break;
                            }
                        }
                    } else {
                        Process.killProcess(appInfo.pid);
                        targetKilled = true;
                        break;
                    }
                }
            }
        } catch (RemoteException remoteException) {
            // Do nothing; just let it go.
        }
        return targetKilled;
    }
}
+1 −0
Original line number Diff line number Diff line
@@ -45,5 +45,6 @@
    <color name="pie_foreground_color">#ffffffff</color>
    <color name="pie_background_color">#dd0099cc</color>
    <color name="pie_selected_color">@android:color/holo_blue_light</color>
    <color name="pie_long_pressed_color">#ff8ad5f0</color>
    <color name="pie_outline_color">#dd0099cc</color>
</resources>
+46 −10
Original line number Diff line number Diff line
@@ -44,6 +44,7 @@ public class PieItem extends PieLayout.PieDrawable {

    private Paint mBackgroundPaint = new Paint();
    private Paint mSelectedPaint = new Paint();
    private Paint mLongPressPaint = new Paint();
    private Paint mOutlinePaint = new Paint();

    private View mView;
@@ -68,10 +69,23 @@ public class PieItem extends PieLayout.PieDrawable {
    }
    private PieOnClickListener mOnClickListener = null;

    public interface PieOnLongClickListener {
        public void onLongClick(PieItem item);
    }
    private PieOnLongClickListener mOnLongClickListener = null;

    /**
     * The item is selected / has the focus from the gesture.
     */
    public final static int SELECTED = 0x100;
    /**
     * The item was long pressed.
     */
    public final static int LONG_PRESSED = 0x200;
    /**
     * The item can be long pressed.
     */
    public final static int CAN_LONG_PRESS = 0x400;

    public PieItem(Context context, PieLayout parent, int flags, int width, Object tag, View view) {
        mView = view;
@@ -86,6 +100,8 @@ public class PieItem extends PieLayout.PieDrawable {
        mBackgroundPaint.setAntiAlias(true);
        mSelectedPaint.setColor(res.getColor(R.color.pie_selected_color));
        mSelectedPaint.setAntiAlias(true);
        mLongPressPaint.setColor(res.getColor(R.color.pie_long_pressed_color));
        mLongPressPaint.setAntiAlias(true);
        mOutlinePaint.setColor(res.getColor(R.color.pie_outline_color));
        mOutlinePaint.setAntiAlias(true);
        mOutlinePaint.setStyle(Style.STROKE);
@@ -102,6 +118,15 @@ public class PieItem extends PieLayout.PieDrawable {
        mOnClickListener = onClickListener;
    }

    public void setOnLongClickListener(PieOnLongClickListener onLongClickListener) {
        mOnLongClickListener = onLongClickListener;
        if (onLongClickListener != null) {
            flags |= CAN_LONG_PRESS;
        } else {
            flags &= ~CAN_LONG_PRESS;
        }
    }

    public void show(boolean show) {
        if (show) {
            flags |= PieLayout.PieDrawable.VISIBLE;
@@ -110,12 +135,13 @@ public class PieItem extends PieLayout.PieDrawable {
        }
    }

    public void setSelected(boolean selected) {
    public void setSelected(boolean selected, boolean longPressed) {
        mPieLayout.postInvalidate();
        longPressed = longPressed & (flags & CAN_LONG_PRESS) != 0;
        if (selected) {
            flags |= SELECTED;
            flags |= longPressed ? SELECTED | LONG_PRESSED : SELECTED;
        } else {
            flags &= ~SELECTED;
            flags &= ~SELECTED & ~LONG_PRESSED;
        }
    }

@@ -163,10 +189,14 @@ public class PieItem extends PieLayout.PieDrawable {

    @Override
    public void draw(Canvas canvas, Position position) {
        canvas.drawPath(mPath, (flags & SELECTED) != 0
                ? mSelectedPaint : mBackgroundPaint);
        canvas.drawPath(mPath, (flags & SELECTED) != 0
                ? mSelectedPaint : mOutlinePaint);
        if ((flags & SELECTED) != 0) {
            Paint paint = (flags & LONG_PRESSED) == 0
                    ? mSelectedPaint : mLongPressPaint;
            canvas.drawPath(mPath, paint);
        } else {
            canvas.drawPath(mPath, mBackgroundPaint);
            canvas.drawPath(mPath, mOutlinePaint);
        }

        if (mView != null) {
            int state = canvas.save();
@@ -192,10 +222,16 @@ public class PieItem extends PieLayout.PieDrawable {
        return null;
    }

    /* package */ void onClickCall() {
    /* package */ void onClickCall(boolean longPressed) {
        if (!longPressed) {
            if (mOnClickListener != null) {
                mOnClickListener.onClick(this);
            }
        } else {
            if (mOnLongClickListener != null) {
                mOnLongClickListener.onLongClick(this);
            }
        }
    }

    private boolean hit(float alpha, int radius) {
+49 −18
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@ import android.provider.Settings;
import android.util.Slog;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.widget.FrameLayout;

import com.android.systemui.statusbar.policy.PieController.Position;
@@ -56,8 +57,8 @@ public class PieLayout extends FrameLayout implements View.OnTouchListener {
    /* DEBUG */
    private long mActivateStartDebug = 0;

    private static final int TIME_FADEIN = 600;
    private static final int TIME_FADEIN_DELAY = 1000;
    private static final int TIME_FADEIN = 300;
    private static final int TIME_FADEIN_DELAY = 400;

    private static final int COLOR_BACKGROUND = 0xee000000;

@@ -81,6 +82,14 @@ public class PieLayout extends FrameLayout implements View.OnTouchListener {
    private Position mPosition = Position.BOTTOM;
    private Position mLayoutDoneForPosition;

    private Handler mHandler;
    private Runnable mLongPressRunnable = new Runnable() {
        @Override
        public void run() {
            updateActiveItem(mActiveItem, true);
        }
    };

    private ValueAnimator mBackgroundAnimator
            = ValueAnimator.ofFloat(0.0f, 1.0f).setDuration(TIME_FADEIN);
    private List<ValueAnimator.AnimatorUpdateListener> mAnimationListenerCache
@@ -178,6 +187,7 @@ public class PieLayout extends FrameLayout implements View.OnTouchListener {
    private List<PieSlice> mSlices = new ArrayList<PieSlice>();
    private List<PieDrawable> mDrawableCache = new ArrayList<PieDrawable>();
    private PieItem mActiveItem;
    private boolean mLongPressed = false;

    private class SnapPoint {
        private final int mX;
@@ -263,6 +273,7 @@ public class PieLayout extends FrameLayout implements View.OnTouchListener {
    public PieLayout(Context context) {
        super(context);

        mHandler = new Handler();
        mBackgroundAnimator.addUpdateListener(mUpdateListener);

        setDrawingCacheEnabled(false);
@@ -440,15 +451,7 @@ public class PieLayout extends FrameLayout implements View.OnTouchListener {
                        newItem = tmp;
                    }
                }
                if (newItem != mActiveItem) {
                    if (newItem != null) {
                        newItem.setSelected(true);
                    }
                    if (mActiveItem != null) {
                        mActiveItem.setSelected(false);
                    }
                    mActiveItem = newItem;
                }
                updateActiveItem(newItem, mLongPressed);
            }

            if (action == MotionEvent.ACTION_UP) {
@@ -459,15 +462,46 @@ public class PieLayout extends FrameLayout implements View.OnTouchListener {
                    }
                } else {
                    if (mActiveItem != null) {
                        mActiveItem.onClickCall();
                        mActiveItem.onClickCall(mLongPressed);
                    }
                }
                PieLayout.this.exit();
            }

            if (action == MotionEvent.ACTION_CANCEL) {
                PieLayout.this.exit();
            }
        }
        return true;
    }

    private void updateActiveItem(PieItem newActiveItem, boolean newLongPressed) {
        if (mActiveItem != newActiveItem || mLongPressed != newLongPressed) {
            mHandler.removeCallbacks(mLongPressRunnable);
            if (mActiveItem != null) {
                mActiveItem.setSelected(false, false);
            }
            if (newActiveItem != null) {
                boolean canLongPressed = (newActiveItem.flags & PieItem.CAN_LONG_PRESS) != 0;
                newLongPressed = newLongPressed && canLongPressed;
                newActiveItem.setSelected(true, newLongPressed);
                if (canLongPressed && !newLongPressed) {
                    mHandler.postDelayed(mLongPressRunnable,
                            (int) (ViewConfiguration.getLongPressTimeout() * 1.5f));
                }
                // if the fade in hasn't started yet, restart again
                if (!mBackgroundAnimator.isRunning() && mBackgroundFraction == 0.0f) {
                    mBackgroundAnimator.cancel();
                    mBackgroundAnimator.start();
                }
            } else {
                newLongPressed = false;
            }
        }
        mActiveItem = newActiveItem;
        mLongPressed = newLongPressed;
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
@@ -573,7 +607,7 @@ public class PieLayout extends FrameLayout implements View.OnTouchListener {
        }

        mBackgroundFraction = 0.0f;
        mBackgroundAnimator.setStartDelay(TIME_FADEIN_DELAY);
        mBackgroundAnimator.setStartDelay(ViewConfiguration.getLongPressTimeout() * 2);
        mBackgroundAnimator.start();

        setVisibility(View.VISIBLE);
@@ -594,10 +628,7 @@ public class PieLayout extends FrameLayout implements View.OnTouchListener {
            }
        }

        if (mActiveItem != null) {
            mActiveItem.setSelected(false);
        }
        mActiveItem = null;
        updateActiveItem(null, false);

        mActive = false;
    }
@@ -609,7 +640,7 @@ public class PieLayout extends FrameLayout implements View.OnTouchListener {
        if (!mActive) {
            mAnimationListenerCache.clear();
            mDrawableCache.clear();
            mActiveItem = null;
            updateActiveItem(null, false);
        }
    }

+39 −4
Original line number Diff line number Diff line
@@ -16,7 +16,10 @@
 */
package com.android.systemui.statusbar.policy;

import android.app.ActivityManager.RunningAppProcessInfo;
import android.app.ActivityManagerNative;
import android.app.ActivityOptions;
import android.app.IActivityManager;
import android.app.SearchManager;
import android.app.StatusBarManager;
import android.content.ActivityNotFoundException;
@@ -26,6 +29,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.database.ContentObserver;
import android.graphics.Point;
@@ -55,7 +59,9 @@ import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.view.accessibility.AccessibilityEvent;
import android.widget.ImageView;
import android.widget.Toast;

import com.android.internal.util.cm.DevUtils;
import com.android.systemui.R;
import com.android.systemui.statusbar.BaseStatusBar;
import com.android.systemui.statusbar.NavigationButtons;
@@ -67,6 +73,8 @@ import com.android.systemui.statusbar.pie.PieLayout.PieSlice;
import com.android.systemui.statusbar.pie.PieSliceContainer;
import com.android.systemui.statusbar.pie.PieSysInfo;

import java.util.List;

/**
 * Controller class for the default pie control.
 * <p>
@@ -74,7 +82,7 @@ import com.android.systemui.statusbar.pie.PieSysInfo;
 * executing the actions that can be triggered by the pie control.
 */
public class PieController implements BaseStatusBar.NavigationBarCallback,
        PieLayout.OnSnapListener, PieItem.PieOnClickListener {
        PieLayout.OnSnapListener, PieItem.PieOnClickListener, PieItem.PieOnLongClickListener {
    public static final String TAG = "PieController";
    public static final boolean DEBUG = false;

@@ -271,6 +279,8 @@ public class PieController implements BaseStatusBar.NavigationBarCallback,
            ContentResolver resolver = mContext.getContentResolver();
            resolver.registerContentObserver(Settings.System.getUriFor(
                    Settings.System.NAV_BUTTONS), false, this);
            resolver.registerContentObserver(Settings.Secure.getUriFor(
                    Settings.Secure.KILL_APP_LONGPRESS_BACK), false, this);
        }

        @Override
@@ -372,6 +382,8 @@ public class PieController implements BaseStatusBar.NavigationBarCallback,

    private void setupNavigationItems() {
        int minimumImageSize = (int)mContext.getResources().getDimension(R.dimen.pie_item_size);
        boolean killAppLongPress = Settings.Secure.getInt(mContext.getContentResolver(),
                Settings.Secure.KILL_APP_LONGPRESS_BACK, 0) == 1;
        ButtonInfo[] buttons = NavigationButtons.loadButtonMap(mContext);

        mNavigationSlice.clear();
@@ -385,13 +397,16 @@ public class PieController implements BaseStatusBar.NavigationBarCallback,
                    // search light has a width of 6 to take the complete space that normally
                    // BACK HOME RECENT would occupy
                    mSearchLight = constructItem(6, SEARCHLIGHT,
                            SEARCHLIGHT.portResource, minimumImageSize);
                            SEARCHLIGHT.portResource, minimumImageSize, false);
                    mNavigationSlice.addItem(mSearchLight);
                }

                boolean canLongPress = bi == NavigationButtons.HOME
                        || (bi == NavigationButtons.BACK && killAppLongPress);
                boolean isSmall = NavigationButtons.IS_SLOT_SMALL[i];
                mNavigationSlice.addItem(constructItem(isSmall ? 1 : 2, bi,
                        isSmall ? bi.sideResource : bi.portResource, minimumImageSize));
                        isSmall ? bi.sideResource : bi.portResource, minimumImageSize,
                        canLongPress));
            }
        }
        mMenuButton = findItem(NavigationButtons.CONDITIONAL_MENU);
@@ -400,7 +415,8 @@ public class PieController implements BaseStatusBar.NavigationBarCallback,
        setMenuVisibility(mShowMenu);
    }

    private PieItem constructItem(int width, ButtonInfo type, int image, int minimumImageSize) {
    private PieItem constructItem(int width, ButtonInfo type, int image, int minimumImageSize,
            boolean canLongPress) {
        ImageView view = new ImageView(mContext);
        view.setImageResource(image);
        view.setMinimumWidth(minimumImageSize);
@@ -409,6 +425,9 @@ public class PieController implements BaseStatusBar.NavigationBarCallback,
        view.setLayoutParams(lp);
        PieItem item = new PieItem(mContext, mPieContainer, 0, width, type, view);
        item.setOnClickListener(this);
        if (canLongPress) {
            item.setOnLongClickListener(this);
        }
        return item;
    }

@@ -565,6 +584,22 @@ public class PieController implements BaseStatusBar.NavigationBarCallback,
        }
    }

    @Override
    public void onLongClick(PieItem item) {
        ButtonInfo bi = (ButtonInfo) item.tag;
        mPieContainer.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
        mPieContainer.playSoundEffect(SoundEffectConstants.CLICK);

        if (bi == NavigationButtons.HOME) {
            launchAssistAction(false);
        } else if (bi == NavigationButtons.BACK) {
            if (DevUtils.killForegroundApplication(mContext)) {
                Toast.makeText(mContext, com.android.internal.R.string.app_killed_message,
                        Toast.LENGTH_SHORT).show();
            }
        }
    }

    private void doHapticTriggerFeedback() {
        if (mVibrator == null || !mVibrator.hasVibrator()) {
            return;
Loading