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

Commit 95d743c3 authored by Mady Mellor's avatar Mady Mellor
Browse files

Add plugin interfaces to control notification menu / swipe behavior

1) Updates the notification menu plugin to do more:
- The plugin can now supply the view it wants to display behind a
  notification as the menu
- Touch interaction (i.e. notification translating on top) is piped
  through to the plugin so it can update the view behind the notification

2) Makes NotificationMenuRow an implementor of the plugin which moves
   a bunch of that logic out of NotificationStackScroller

Test: runtest systemui
Change-Id: I8723b96c195ff7311317d5523418cfcbe2a79b52
parent fc7f4ceb
Loading
Loading
Loading
Loading
+97 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2017 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.systemui.plugins.statusbar;

import android.content.Context;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;

import java.util.ArrayList;

import com.android.systemui.plugins.Plugin;
import com.android.systemui.plugins.annotations.DependsOn;
import com.android.systemui.plugins.annotations.ProvidesInterface;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.OnMenuEventListener;
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.SnoozeOption;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.MenuItem;

@ProvidesInterface(action = NotificationMenuRowPlugin.ACTION,
        version = NotificationMenuRowPlugin.VERSION)
@DependsOn(target = OnMenuEventListener.class)
@DependsOn(target = MenuItem.class)
@DependsOn(target = NotificationSwipeActionHelper.class)
@DependsOn(target = SnoozeOption.class)
public interface NotificationMenuRowPlugin extends Plugin {

    public static final String ACTION = "com.android.systemui.action.PLUGIN_NOTIFICATION_MENU_ROW";
    public static final int VERSION = 1;

    @ProvidesInterface(version = OnMenuEventListener.VERSION)
    public interface OnMenuEventListener {
        public static final int VERSION = 1;
        public void onMenuClicked(View row, int x, int y, MenuItem menu);

        public void onMenuReset(View row);

        public void onMenuShown(View row);
    }

    @ProvidesInterface(version = MenuItem.VERSION)
    public interface MenuItem {
        public static final int VERSION = 1;
        public View getMenuView();

        public View getGutsView();

        public String getContentDescription();
    }

    /**
     * @return a list of items to populate the menu 'behind' a notification.
     */
    public ArrayList<MenuItem> getMenuItems(Context context);

    /**
     * @return the {@link MenuItem} to display when a notification is long pressed.
     */
    public MenuItem getLongpressMenuItem(Context context);

    public void setMenuItems(ArrayList<MenuItem> items);

    public void setMenuClickListener(OnMenuEventListener listener);

    public void setSwipeActionHelper(NotificationSwipeActionHelper listener);

    public void setAppName(String appName);

    public void createMenu(ViewGroup parent);

    public View getMenuView();

    public boolean isMenuVisible();

    public void resetMenu();

    public void onTranslationUpdate(float translation);

    public void onHeightUpdate();

    public boolean onTouchEvent(View view, MotionEvent ev, float velocity);

    public default boolean useDefaultMenuItems() {
        return false;
    }
}
+72 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2017 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.systemui.plugins.statusbar;
package com.android.systemui.plugins.statusbar;


import android.content.Context;
import com.android.systemui.plugins.annotations.DependsOn;
import android.graphics.drawable.Drawable;
import com.android.systemui.plugins.annotations.ProvidesInterface;
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.SnoozeOption;

import android.service.notification.SnoozeCriterion;
import android.service.notification.SnoozeCriterion;
import android.service.notification.StatusBarNotification;
import android.service.notification.StatusBarNotification;
import android.view.MotionEvent;
import android.view.View;
import android.view.View;


import java.util.ArrayList;
@ProvidesInterface(version = NotificationSwipeActionHelper.VERSION)

@DependsOn(target = SnoozeOption.class)
import com.android.systemui.plugins.Plugin;
public interface NotificationSwipeActionHelper {
import com.android.systemui.plugins.annotations.ProvidesInterface;
    public static final String ACTION = "com.android.systemui.action.PLUGIN_NOTIFICATION_SWIPE_ACTION";

@ProvidesInterface(action = NotificationMenuRowProvider.ACTION,
        version = NotificationMenuRowProvider.VERSION)
public interface NotificationMenuRowProvider extends Plugin {

    public static final String ACTION = "com.android.systemui.action.PLUGIN_NOTIFICATION_MENU_ROW";


    public static final int VERSION = 1;
    public static final int VERSION = 1;


    /**
    /**
     * Returns a list of items to populate the menu 'behind' a notification.
     * Call this to dismiss a notification.
     */
     */
    public ArrayList<MenuItem> getMenuItems(Context context);
    public void dismiss(View animView, float velocity);

    public interface OnMenuClickListener {
        public void onMenuClicked(View row, int x, int y, MenuItem menu);

        public void onMenuReset(View row);
    }

    public interface GutsInteractionListener {
        public void onInteraction(View view);

        public void closeGuts(View view);
    }

    public interface GutsContent {
        public void setInteractionListener(GutsInteractionListener listener);

        public View getContentView();

        public boolean handleCloseControls(boolean save);


        public boolean willBeRemoved();
    /**
    }
     * Call this to snap a notification to provided {@code targetLeft}.

     */
    public interface SnoozeGutsContent extends GutsContent {
    public void snap(View animView, float velocity, float targetLeft);
        public void setSnoozeListener(SnoozeListener listener);

        public void setStatusBarNotification(StatusBarNotification sbn);
    }


    public interface SnoozeListener {
    /**
        public void snoozeNotification(StatusBarNotification sbn, SnoozeOption snoozeOption);
     * Call this to snooze a notification based on the provided {@link SnoozeOption}.
    }
     */
    public void snooze(StatusBarNotification sbn, SnoozeOption snoozeOption);


    public static class MenuItem {
    public float getMinDismissVelocity();
        public Drawable icon;
        public String menuDescription;
        public View menuView;
        public GutsContent gutsContent;


        public MenuItem(Drawable i, String s, GutsContent content) {
    public boolean isDismissGesture(MotionEvent ev);
            icon = i;
            menuDescription = s;
            gutsContent = content;
        }


        public View getGutsView() {
    public boolean swipedFarEnough(float translation, float viewSize);
            return gutsContent.getContentView();
        }


        public boolean onTouch(View v, int x, int y) {
    public boolean swipedFastEnough(float translation, float velocity);
            return false;
        }
    }


    @ProvidesInterface(version = SnoozeOption.VERSION)
    public static class SnoozeOption {
    public static class SnoozeOption {
        public SnoozeCriterion criterion;
        public static final int VERSION = 1;
        public int snoozeForMinutes;
        public int snoozeForMinutes;
        public SnoozeCriterion criterion;
        public CharSequence description;
        public CharSequence description;
        public CharSequence confirmation;
        public CharSequence confirmation;


+0 −22
Original line number Original line Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!--
    Copyright 2016, 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.
-->
<com.android.systemui.statusbar.NotificationMenuRow
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:systemui="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:visibility="invisible"/>
 No newline at end of file
+1 −7
Original line number Original line Diff line number Diff line
@@ -23,13 +23,7 @@
    android:clickable="true"
    android:clickable="true"
    >
    >


    <ViewStub
    <!-- Menu displayed behind notification added here programmatically -->
        android:layout="@layout/notification_menu_row"
        android:id="@+id/menu_row_stub"
        android:inflatedId="@+id/notification_menu_row"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        />


    <com.android.systemui.statusbar.NotificationBackgroundView
    <com.android.systemui.statusbar.NotificationBackgroundView
        android:id="@+id/backgroundNormal"
        android:id="@+id/backgroundNormal"
+14 −9
Original line number Original line Diff line number Diff line
@@ -32,9 +32,10 @@ import android.view.ViewConfiguration;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityEvent;


import com.android.systemui.classifier.FalsingManager;
import com.android.systemui.classifier.FalsingManager;
import com.android.systemui.plugins.statusbar.NotificationMenuRowProvider.MenuItem;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.MenuItem;
import com.android.systemui.statusbar.ExpandableNotificationRow;
import com.android.systemui.statusbar.FlingAnimationUtils;
import com.android.systemui.statusbar.FlingAnimationUtils;
import com.android.systemui.statusbar.NotificationMenuRow;


import java.util.HashMap;
import java.util.HashMap;


@@ -267,7 +268,7 @@ public class SwipeHelper implements Gefingerpoken {
                mCurrView = mCallback.getChildAtPosition(ev);
                mCurrView = mCallback.getChildAtPosition(ev);


                if (mCurrView != null) {
                if (mCurrView != null) {
                    onDownUpdate(mCurrView);
                    onDownUpdate(mCurrView, ev);
                    mCanCurrViewBeDimissed = mCallback.canChildBeDismissed(mCurrView);
                    mCanCurrViewBeDimissed = mCallback.canChildBeDismissed(mCurrView);
                    mVelocityTracker.addMovement(ev);
                    mVelocityTracker.addMovement(ev);
                    mInitialTouchPos = getPos(ev);
                    mInitialTouchPos = getPos(ev);
@@ -285,8 +286,12 @@ public class SwipeHelper implements Gefingerpoken {
                                        mCurrView.getLocationOnScreen(mTmpPos);
                                        mCurrView.getLocationOnScreen(mTmpPos);
                                        final int x = (int) ev.getRawX() - mTmpPos[0];
                                        final int x = (int) ev.getRawX() - mTmpPos[0];
                                        final int y = (int) ev.getRawY() - mTmpPos[1];
                                        final int y = (int) ev.getRawY() - mTmpPos[1];
                                        mLongPressListener.onLongPress(mCurrView, x, y,
                                        MenuItem menuItem = null;
                                                NotificationMenuRow.getLongpressMenuItem(mContext));
                                        if (mCurrView instanceof ExpandableNotificationRow) {
                                            menuItem = ((ExpandableNotificationRow) mCurrView)
                                                    .getProvider().getLongpressMenuItem(mContext);
                                        }
                                        mLongPressListener.onLongPress(mCurrView, x, y, menuItem);
                                    }
                                    }
                                }
                                }
                            };
                            };
@@ -479,14 +484,14 @@ public class SwipeHelper implements Gefingerpoken {
    /**
    /**
     * Called when there's a down event.
     * Called when there's a down event.
     */
     */
    public void onDownUpdate(View currView) {
    public void onDownUpdate(View currView, MotionEvent ev) {
        // Do nothing
        // Do nothing
    }
    }


    /**
    /**
     * Called on a move event.
     * Called on a move event.
     */
     */
    protected void onMoveUpdate(View view, float totalTranslation, float delta) {
    protected void onMoveUpdate(View view, MotionEvent ev, float totalTranslation, float delta) {
        // Do nothing
        // Do nothing
    }
    }


@@ -580,7 +585,7 @@ public class SwipeHelper implements Gefingerpoken {


                    setTranslation(mCurrView, mTranslation + delta);
                    setTranslation(mCurrView, mTranslation + delta);
                    updateSwipeProgressFromOffset(mCurrView, mCanCurrViewBeDimissed);
                    updateSwipeProgressFromOffset(mCurrView, mCanCurrViewBeDimissed);
                    onMoveUpdate(mCurrView, mTranslation + delta, delta);
                    onMoveUpdate(mCurrView, ev, mTranslation + delta, delta);
                }
                }
                break;
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_UP:
@@ -635,7 +640,7 @@ public class SwipeHelper implements Gefingerpoken {
        return DISMISS_IF_SWIPED_FAR_ENOUGH && Math.abs(translation) > 0.4 * getSize(mCurrView);
        return DISMISS_IF_SWIPED_FAR_ENOUGH && Math.abs(translation) > 0.4 * getSize(mCurrView);
    }
    }


    protected boolean isDismissGesture(MotionEvent ev) {
    public boolean isDismissGesture(MotionEvent ev) {
        boolean falsingDetected = mCallback.isAntiFalsingNeeded();
        boolean falsingDetected = mCallback.isAntiFalsingNeeded();
        if (mFalsingManager.isClassiferEnabled()) {
        if (mFalsingManager.isClassiferEnabled()) {
            falsingDetected = falsingDetected && mFalsingManager.isFalseTouch();
            falsingDetected = falsingDetected && mFalsingManager.isFalseTouch();
Loading