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

Commit 87d7945f authored by Mady Mellor's avatar Mady Mellor
Browse files

Change NotificationGuts to contain a view

NotificationGuts is now given a view to display, the notification
management controls have been moved into their own view.

NotificationGuts is provided a view to show via a MenuItem.

This allows configuration via the NotificationMenuRowProvider Plugin.

Test: manual
Change-Id: I68cb23ea2cada30cc6e930fa8c03e0aa4014dfe2
parent 761cde11
Loading
Loading
Loading
Loading
+22 −1
Original line number Diff line number Diff line
@@ -3,6 +3,7 @@ package com.android.systemui.plugins.statusbar;

import android.content.Context;
import android.graphics.drawable.Drawable;
import android.service.notification.StatusBarNotification;
import android.view.View;

import java.util.ArrayList;
@@ -26,14 +27,34 @@ public interface NotificationMenuRowProvider extends Plugin {
        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();
    }

    public static class MenuItem {
        public Drawable icon;
        public String menuDescription;
        public View menuView;
        public GutsContent gutsContent;

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

        public View getGutsView() {
            return gutsContent.getContentView();
        }

        public boolean onTouch(View v, int x, int y) {
+1 −122
Original line number Diff line number Diff line
@@ -23,125 +23,4 @@
    android:visibility="gone"
    android:clickable="true"
    android:gravity="top|start"
    android:orientation="vertical"
    android:paddingStart="@*android:dimen/notification_content_margin_start"
    android:paddingEnd="8dp"
    android:background="@color/notification_guts_bg_color"
    android:theme="@*android:style/Theme.DeviceDefault.Light">

    <!-- header -->
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingTop="20dp"
        android:paddingEnd="8dp"
        android:paddingBottom="15dp"
        android:id="@+id/notification_guts_header">
        <TextView
            android:id="@+id/pkgname"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentStart="true"
            style="@style/TextAppearance.NotificationGuts.Secondary" />
        <TextView
            android:id="@+id/channel_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentStart="true"
            android:layout_below="@id/pkgname"
            style="@style/TextAppearance.NotificationGuts.Header" />
        <Switch
            android:id="@+id/channel_enabled_switch"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"
            android:background="@null" />
    </RelativeLayout>
    <!-- Importance radio buttons -->
    <LinearLayout
        android:id="@+id/importance"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <RadioGroup
            android:id="@+id/importance_buttons"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:paddingEnd="@*android:dimen/notification_content_margin_end">
            <RadioButton
                android:id="@+id/high_importance"
                android:layout_width="wrap_content"
                android:layout_height="@dimen/notification_inline_importance_height"
                style="@style/TextAppearance.NotificationGuts.Radio"
                android:buttonTint="@color/notification_guts_buttons" />
            <RadioButton
                android:id="@+id/default_importance"
                android:layout_width="wrap_content"
                android:layout_height="@dimen/notification_inline_importance_height"
                style="@style/TextAppearance.NotificationGuts.Radio"
                android:buttonTint="@color/notification_guts_buttons" />
            <RadioButton
                android:id="@+id/low_importance"
                android:layout_width="wrap_content"
                android:layout_height="@dimen/notification_inline_importance_height"
                style="@style/TextAppearance.NotificationGuts.Radio"
                android:buttonTint="@color/notification_guts_buttons" />
            <RadioButton
                android:id="@+id/min_importance"
                android:layout_width="wrap_content"
                android:layout_height="@dimen/notification_inline_importance_height"
                style="@style/TextAppearance.NotificationGuts.Radio"
                android:buttonTint="@color/notification_guts_buttons" />
        </RadioGroup>
        <LinearLayout
            android:id="@+id/importance_buttons_text"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">
            <include layout="@layout/notification_guts_importance_text"/>
            <include layout="@layout/notification_guts_importance_text"/>
            <include layout="@layout/notification_guts_importance_text"/>
            <include layout="@layout/notification_guts_importance_text"/>
        </LinearLayout>
    </LinearLayout>
    <!-- Channel Disabled Text -->
    <TextView
        android:id="@+id/channel_disabled"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/notification_channel_disabled"
        style="@style/TextAppearance.NotificationGuts.Secondary" />
    <!-- Settings and Done buttons -->
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="end"
        android:paddingTop="16dp"
        android:paddingBottom="8dp" >

        <TextView
            android:id="@+id/more_settings"
            android:text="@string/notification_more_settings"
            android:layout_width="wrap_content"
            android:layout_height="36dp"
            style="@style/TextAppearance.NotificationGuts.Button"
            android:background="@drawable/btn_borderless_rect"
            android:gravity="center"
            android:paddingEnd="8dp"
            android:paddingStart="8dp"
            android:focusable="true" />

        <TextView
            android:id="@+id/done"
            android:text="@string/notification_done"
            android:layout_width="wrap_content"
            android:layout_height="36dp"
            style="@style/TextAppearance.NotificationGuts.Button"
            android:background="@drawable/btn_borderless_rect"
            android:gravity="center"
            android:layout_marginStart="8dp"
            android:layout_marginEnd="8dp"
            android:focusable="true"/>
    </LinearLayout>
</com.android.systemui.statusbar.NotificationGuts>
    android:theme="@*android:style/Theme.DeviceDefault.Light"/>
+146 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!--
    Copyright 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.
-->

<com.android.systemui.statusbar.NotificationInfo
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/notification_guts"
        android:clickable="true"
        android:gravity="top|start"
        android:orientation="vertical"
        android:paddingStart="@*android:dimen/notification_content_margin_start"
        android:paddingEnd="8dp"
        android:background="@color/notification_guts_bg_color"
        android:theme="@*android:style/Theme.DeviceDefault.Light">

    <!-- header -->
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingTop="20dp"
        android:paddingEnd="8dp"
        android:paddingBottom="15dp"
        android:id="@+id/notification_guts_header">
        <TextView
            android:id="@+id/pkgname"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentStart="true"
            style="@style/TextAppearance.NotificationGuts.Secondary" />
        <TextView
            android:id="@+id/channel_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentStart="true"
            android:layout_below="@id/pkgname"
            style="@style/TextAppearance.NotificationGuts.Header" />
        <Switch
            android:id="@+id/channel_enabled_switch"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"
            android:background="@null" />
    </RelativeLayout>
    <!-- Importance radio buttons -->
    <LinearLayout
        android:id="@+id/importance"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <RadioGroup
            android:id="@+id/importance_buttons"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:paddingEnd="@*android:dimen/notification_content_margin_end">
            <RadioButton
                android:id="@+id/high_importance"
                android:layout_width="wrap_content"
                android:layout_height="@dimen/notification_inline_importance_height"
                style="@style/TextAppearance.NotificationGuts.Radio"
                android:buttonTint="@color/notification_guts_buttons" />
            <RadioButton
                android:id="@+id/default_importance"
                android:layout_width="wrap_content"
                android:layout_height="@dimen/notification_inline_importance_height"
                style="@style/TextAppearance.NotificationGuts.Radio"
                android:buttonTint="@color/notification_guts_buttons" />
            <RadioButton
                android:id="@+id/low_importance"
                android:layout_width="wrap_content"
                android:layout_height="@dimen/notification_inline_importance_height"
                style="@style/TextAppearance.NotificationGuts.Radio"
                android:buttonTint="@color/notification_guts_buttons" />
            <RadioButton
                android:id="@+id/min_importance"
                android:layout_width="wrap_content"
                android:layout_height="@dimen/notification_inline_importance_height"
                style="@style/TextAppearance.NotificationGuts.Radio"
                android:buttonTint="@color/notification_guts_buttons" />
        </RadioGroup>
        <LinearLayout
            android:id="@+id/importance_buttons_text"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">
            <include layout="@layout/notification_guts_importance_text"/>
            <include layout="@layout/notification_guts_importance_text"/>
            <include layout="@layout/notification_guts_importance_text"/>
            <include layout="@layout/notification_guts_importance_text"/>
        </LinearLayout>
    </LinearLayout>
    <!-- Channel Disabled Text -->
    <TextView
        android:id="@+id/channel_disabled"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/notification_channel_disabled"
        style="@style/TextAppearance.NotificationGuts.Secondary" />
    <!-- Settings and Done buttons -->
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="end"
        android:paddingTop="16dp"
        android:paddingBottom="8dp" >

        <TextView
            android:id="@+id/more_settings"
            android:text="@string/notification_more_settings"
            android:layout_width="wrap_content"
            android:layout_height="36dp"
            style="@style/TextAppearance.NotificationGuts.Button"
            android:background="@drawable/btn_borderless_rect"
            android:gravity="center"
            android:paddingEnd="8dp"
            android:paddingStart="8dp"
            android:focusable="true" />

        <TextView
            android:id="@+id/done"
            android:text="@string/notification_done"
            android:layout_width="wrap_content"
            android:layout_height="36dp"
            style="@style/TextAppearance.NotificationGuts.Button"
            android:background="@drawable/btn_borderless_rect"
            android:gravity="center"
            android:layout_marginStart="8dp"
            android:layout_marginEnd="8dp"
            android:focusable="true"/>
    </LinearLayout>
</com.android.systemui.statusbar.NotificationInfo>
+56 −40
Original line number Diff line number Diff line
@@ -101,6 +101,8 @@ import com.android.systemui.RecentsComponent;
import com.android.systemui.SwipeHelper;
import com.android.systemui.SystemUI;
import com.android.systemui.assist.AssistManager;
import com.android.systemui.plugins.statusbar.NotificationMenuRowProvider;
import com.android.systemui.plugins.statusbar.NotificationMenuRowProvider.MenuItem;
import com.android.systemui.recents.Recents;
import com.android.systemui.statusbar.NotificationData.Entry;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
@@ -247,6 +249,7 @@ public abstract class BaseStatusBar extends SystemUI implements

    // which notification is currently being longpress-examined by the user
    private NotificationGuts mNotificationGutsExposed;
    private MenuItem mGutsMenuItem;

    private KeyboardShortcuts mKeyboardShortcuts;

@@ -702,6 +705,7 @@ public abstract class BaseStatusBar extends SystemUI implements
        }
    }

    @Override
    public void start() {
        mWindowManager = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
        mWindowManagerService = WindowManagerGlobal.getWindowManagerService();
@@ -967,7 +971,7 @@ public abstract class BaseStatusBar extends SystemUI implements
            entry.row.reInflateViews();
            if (exposedGuts) {
                mNotificationGutsExposed = entry.row.getGuts();
                bindGuts(entry.row);
                bindGuts(entry.row, mGutsMenuItem);
            }
            inflateViews(entry, mStackScroller);
        }
@@ -1032,6 +1036,7 @@ public abstract class BaseStatusBar extends SystemUI implements
            @Override
            public boolean onDismiss() {
                AsyncTask.execute(new Runnable() {
                    @Override
                    public void run() {
                        TaskStackBuilder.create(mContext)
                                .addNextIntentWithParentStack(intent)
@@ -1045,11 +1050,10 @@ public abstract class BaseStatusBar extends SystemUI implements
        }, false /* afterKeyguardGone */);
    }

    private void bindGuts(final ExpandableNotificationRow row) {
    private void bindGuts(final ExpandableNotificationRow row, MenuItem item) {
        row.inflateGuts();
        row.setGutsView(item);
        final StatusBarNotification sbn = row.getStatusBarNotification();
        final NotificationChannel channel = row.getEntry().channel;
        PackageManager pmUser = getPackageManagerForUser(mContext, sbn.getUser().getIdentifier());
        row.setTag(sbn.getPackageName());
        final NotificationGuts guts = row.getGuts();
        guts.setClosedListener((NotificationGuts g) -> {
@@ -1059,43 +1063,48 @@ public abstract class BaseStatusBar extends SystemUI implements
            mNotificationGutsExposed = null;
        });

        if (item.gutsContent instanceof NotificationInfo) {
            final NotificationChannel channel = row.getEntry().channel;
            PackageManager pmUser = getPackageManagerForUser(mContext,
                    sbn.getUser().getIdentifier());
            final INotificationManager iNotificationManager = INotificationManager.Stub.asInterface(
                    ServiceManager.getService(Context.NOTIFICATION_SERVICE));

            final String pkg = sbn.getPackageName();
        final NotificationGuts.OnSettingsClickListener onSettingsClick =
                (View v, int appUid) -> {
            NotificationInfo info = (NotificationInfo) item.gutsContent;
            final NotificationInfo.OnSettingsClickListener onSettingsClick = (View v,
                    int appUid) -> {
                MetricsLogger.action(mContext, MetricsEvent.ACTION_NOTE_INFO);
                guts.resetFalsingCheck();
                startAppNotificationSettingsActivity(pkg, appUid);
            };
        final View.OnClickListener onDoneClick =
                (View v) -> {
            final View.OnClickListener onDoneClick = (View v) -> {
                // If the user has security enabled, show challenge if the setting is changed.
                    if (guts.hasImportanceChanged()
                if (info.hasImportanceChanged()
                        && isLockscreenPublicMode(sbn.getUser().getIdentifier())
                        && (mState == StatusBarState.KEYGUARD
                                || mState == StatusBarState.SHADE_LOCKED)) {
                    OnDismissAction dismissAction = new OnDismissAction() {
                        @Override
                        public boolean onDismiss() {
                                closeControls(row, guts, v);
                            saveAndCloseNotificationMenu(info, row, guts, v);
                            return true;
                        }
                    };
                    onLockedNotificationImportanceChange(dismissAction);
                } else {
                        closeControls(row, guts, v);
                    saveAndCloseNotificationMenu(info, row, guts, v);
                }
            };
        guts.bindNotification(pmUser, iNotificationManager, sbn, channel,
                onSettingsClick, onDoneClick, mNonBlockablePkgs);
            info.bindNotification(pmUser, iNotificationManager, sbn, channel, onSettingsClick,
                    onDoneClick,
                    mNonBlockablePkgs);
        }
    }

    private void closeControls(
    private void saveAndCloseNotificationMenu(NotificationInfo info,
            ExpandableNotificationRow row, NotificationGuts guts, View done) {
        guts.resetFalsingCheck();

        info.saveImportance();
        int[] rowLocation = new int[2];
        int[] doneLocation = new int[2];
        row.getLocationOnScreen(rowLocation);
@@ -1111,7 +1120,8 @@ public abstract class BaseStatusBar extends SystemUI implements
    protected SwipeHelper.LongPressListener getNotificationLongClicker() {
        return new SwipeHelper.LongPressListener() {
            @Override
            public boolean onLongPress(View v, final int x, final int y) {
            public boolean onLongPress(View v, final int x, final int y,
                    MenuItem item) {
                if (!(v instanceof ExpandableNotificationRow)) {
                    return false;
                }
@@ -1121,10 +1131,10 @@ public abstract class BaseStatusBar extends SystemUI implements
                }

                final ExpandableNotificationRow row = (ExpandableNotificationRow) v;
                bindGuts(row);
                bindGuts(row, item);
                NotificationGuts guts = row.getGuts();

                // Assume we are a status_bar_notification_row
                final NotificationGuts guts = row.getGuts();
                if (guts == null) {
                    // This view has no guts. Examples are the more card or the dismiss all view
                    return false;
@@ -1142,6 +1152,7 @@ public abstract class BaseStatusBar extends SystemUI implements
                guts.setVisibility(View.INVISIBLE);
                // Post to ensure the the guts are properly laid out.
                guts.post(new Runnable() {
                    @Override
                    public void run() {
                        if (row.getWindowToken() == null) {
                            Log.e(TAG, "Trying to show notification guts, but not attached to "
@@ -1172,6 +1183,7 @@ public abstract class BaseStatusBar extends SystemUI implements
                        row.closeRemoteInput();
                        mStackScroller.onHeightChanged(row, true /* needsAnimation */);
                        mNotificationGutsExposed = guts;
                        mGutsMenuItem = item;
                    }
                });
                return true;
@@ -1483,6 +1495,7 @@ public abstract class BaseStatusBar extends SystemUI implements
    }

    protected class H extends Handler {
        @Override
        public void handleMessage(Message m) {
            switch (m.what) {
             case MSG_SHOW_RECENT_APPS:
@@ -1752,6 +1765,7 @@ public abstract class BaseStatusBar extends SystemUI implements
                && PreviewInflater.wouldLaunchResolverActivity(mContext, intent.getIntent(),
                mCurrentUserId);
        dismissKeyguardThenExecute(new OnDismissAction() {
            @Override
            public boolean onDismiss() {
                new Thread() {
                    @Override
@@ -1802,6 +1816,7 @@ public abstract class BaseStatusBar extends SystemUI implements
    private final class NotificationClicker implements View.OnClickListener {
        private final int[] mTmpInt2 = new int[2];

        @Override
        public void onClick(final View v) {
            if (!(v instanceof ExpandableNotificationRow)) {
                Log.e(TAG, "NotificationClicker called on a view that is not a notification row.");
@@ -1845,6 +1860,7 @@ public abstract class BaseStatusBar extends SystemUI implements
                    && PreviewInflater.wouldLaunchResolverActivity(mContext, intent.getIntent(),
                            mCurrentUserId);
            dismissKeyguardThenExecute(new OnDismissAction() {
                @Override
                public boolean onDismiss() {
                    if (mHeadsUpManager != null && mHeadsUpManager.isHeadsUp(notificationKey)) {
                        // Release the HUN notification to the shade.
+8 −0
Original line number Diff line number Diff line
@@ -50,6 +50,7 @@ import com.android.internal.widget.CachingIconView;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.classifier.FalsingManager;
import com.android.systemui.plugins.statusbar.NotificationMenuRowProvider.MenuItem;
import com.android.systemui.statusbar.notification.HybridNotificationView;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
@@ -666,6 +667,13 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
        mHeadsUpManager = headsUpManager;
    }

    public void setGutsView(MenuItem item) {
        if (mGuts != null) {
            item.gutsContent.setInteractionListener(mGuts);
            mGuts.setGutsContent(item.gutsContent);
        }
    }

    public void reInflateViews() {
        initDimens();
        if (mIsSummaryWithChildren) {
Loading