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

Commit bf20eab6 authored by John Spurlock's avatar John Spurlock
Browse files

Put suppressed notifications behind a summary notification.

Bug:13726563
Change-Id: Ib1c3fba3a328792dc674c8403735f75d4db41973
parent cfd3cd6d
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -526,4 +526,12 @@
    <string name="description_direction_up">Slide up for <xliff:g id="target_description" example="Unlock">%s</xliff:g>.</string>
    <!-- Description of the left direction in which one can to slide the handle in the Slide unlock screen. [CHAR LIMIT=NONE] -->
    <string name="description_direction_left">"Slide left for <xliff:g id="target_description" example="Unlock">%s</xliff:g>.</string>

    <!-- Zen mode: Summary notification content title. [CHAR LIMIT=NONE] -->
    <plurals name="zen_mode_notification_title">
        <item quantity="one">Notification hidden</item>
        <item quantity="other">%d notifications hidden</item>
    </plurals>
    <!-- Zen mode: Summary notification content text. [CHAR LIMIT=NONE] -->
    <string name="zen_mode_notification_text">Touch to show</string>
</resources>
+0 −27
Original line number Diff line number Diff line
@@ -109,9 +109,6 @@ public abstract class BaseStatusBar extends SystemUI implements
    public static final int EXPANDED_LEAVE_ALONE = -10000;
    public static final int EXPANDED_FULL_OPEN = -10001;

    private static final String EXTRA_INTERCEPT = "android.intercept";
    private static final float INTERCEPTED_ALPHA = .2f;

    protected CommandQueue mCommandQueue;
    protected IStatusBarService mBarService;
    protected H mHandler = createHandler();
@@ -1049,7 +1046,6 @@ public abstract class BaseStatusBar extends SystemUI implements
        if (DEBUG) {
            Log.d(TAG, "addNotificationViews: added at " + pos);
        }
        updateInterceptedState(entry);
        updateExpansionStates();
        updateNotificationIcons();
    }
@@ -1082,32 +1078,10 @@ public abstract class BaseStatusBar extends SystemUI implements

    protected void setZenMode(int mode) {
        if (!isDeviceProvisioned()) return;
        final boolean change = mZenMode != mode;
        mZenMode = mode;
        final int N = mNotificationData.size();
        for (int i = 0; i < N; i++) {
            final NotificationData.Entry entry = mNotificationData.get(i);
            if (change && !shouldIntercept()) {
                entry.notification.getNotification().extras.putBoolean(EXTRA_INTERCEPT, false);
            }
            updateInterceptedState(entry);
        }
        updateNotificationIcons();
    }

    private boolean shouldIntercept() {
        return mZenMode != Settings.Global.ZEN_MODE_OFF;
    }

    protected boolean shouldIntercept(Notification n) {
        return shouldIntercept() && n.extras.getBoolean(EXTRA_INTERCEPT);
    }

    private void updateInterceptedState(NotificationData.Entry entry) {
        final boolean intercepted = shouldIntercept(entry.notification.getNotification());
        entry.row.findViewById(R.id.container).setAlpha(intercepted ? INTERCEPTED_ALPHA : 1);
    }

    protected abstract void haltTicker();
    protected abstract void setAreThereNotifications();
    protected abstract void updateNotificationIcons();
@@ -1312,7 +1286,6 @@ public abstract class BaseStatusBar extends SystemUI implements
        } else {
            entry.content.setOnClickListener(null);
        }
        updateInterceptedState(entry);
    }

    protected void notifyHeadsUpScreenOn(boolean screenOn) {
+119 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2014 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.statusbar;

import android.app.Notification;
import android.content.Context;
import android.os.Binder;
import android.os.IBinder;
import android.os.Process;
import android.service.notification.StatusBarNotification;
import android.util.ArrayMap;
import android.view.View;

import com.android.systemui.R;
import com.android.systemui.statusbar.NotificationData.Entry;
import com.android.systemui.statusbar.phone.PhoneStatusBar;

public class InterceptedNotifications {
    private static final String TAG = "InterceptedNotifications";
    private static final String EXTRA_INTERCEPT = "android.intercept";

    private final Context mContext;
    private final PhoneStatusBar mBar;
    private final ArrayMap<IBinder, StatusBarNotification> mIntercepted
            = new ArrayMap<IBinder, StatusBarNotification>();

    private Binder mSynKey;

    public InterceptedNotifications(Context context, PhoneStatusBar bar) {
        mContext = context;
        mBar = bar;
    }

    public void releaseIntercepted() {
        final int n = mIntercepted.size();
        for (int i = 0; i < n; i++) {
            final IBinder key = mIntercepted.keyAt(i);
            final StatusBarNotification sbn = mIntercepted.valueAt(i);
            sbn.getNotification().extras.putBoolean(EXTRA_INTERCEPT, false);
            mBar.addNotification(key, sbn);
        }
        mIntercepted.clear();
        updateSyntheticNotification();
    }

    public boolean tryIntercept(IBinder key, StatusBarNotification notification) {
        if (!notification.getNotification().extras.getBoolean(EXTRA_INTERCEPT)) return false;
        mIntercepted.put(key, notification);
        updateSyntheticNotification();
        return true;
    }

    public void remove(IBinder key) {
        if (mIntercepted.remove(key) != null) {
            updateSyntheticNotification();
        }
    }

    public boolean isSyntheticEntry(Entry ent) {
        return mSynKey != null && ent.key.equals(mSynKey);
    }

    public void update(IBinder key, StatusBarNotification notification) {
        if (mIntercepted.containsKey(key)) {
            mIntercepted.put(key, notification);
        }
    }

    private void updateSyntheticNotification() {
        if (mIntercepted.isEmpty()) {
            if (mSynKey != null) {
                mBar.removeNotification(mSynKey);
                mSynKey = null;
            }
            return;
        }
        final Notification n = new Notification.Builder(mContext)
                .setSmallIcon(R.drawable.stat_sys_zen_limited)
                .setContentTitle(mContext.getResources().getQuantityString(
                        R.plurals.zen_mode_notification_title,
                        mIntercepted.size(), mIntercepted.size()))
                .setContentText(mContext.getString(R.string.zen_mode_notification_text))
                .setOngoing(true)
                .build();
        final StatusBarNotification sbn = new StatusBarNotification(mContext.getPackageName(),
                mContext.getBasePackageName(),
                TAG.hashCode(), TAG, Process.myUid(), Process.myPid(), 0, n,
                mBar.getCurrentUserHandle());
        if (mSynKey == null) {
            mSynKey = new Binder();
            mBar.addNotification(mSynKey, sbn);
        } else {
           mBar.updateNotification(mSynKey, sbn);
        }
        final NotificationData.Entry entry = mBar.mNotificationData.findByKey(mSynKey);
        entry.content.setOnClickListener(mSynClickListener);
    }

    private final View.OnClickListener mSynClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            releaseIntercepted();
        }
    };
}
+54 −38
Original line number Diff line number Diff line
@@ -59,6 +59,7 @@ import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.Settings;
import android.provider.Settings.Global;
import android.service.notification.StatusBarNotification;
import android.util.DisplayMetrics;
import android.util.EventLog;
@@ -89,11 +90,11 @@ import com.android.systemui.R;
import com.android.systemui.statusbar.BaseStatusBar;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.GestureRecorder;
import com.android.systemui.statusbar.InterceptedNotifications;
import com.android.systemui.statusbar.NotificationData;
import com.android.systemui.statusbar.NotificationData.Entry;
import com.android.systemui.statusbar.SignalClusterView;
import com.android.systemui.statusbar.StatusBarIconView;

import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.BluetoothController;
import com.android.systemui.statusbar.policy.DateView;
@@ -101,7 +102,6 @@ import com.android.systemui.statusbar.policy.HeadsUpNotificationView;
import com.android.systemui.statusbar.policy.LocationController;
import com.android.systemui.statusbar.policy.NetworkController;
import com.android.systemui.statusbar.policy.RotationLockController;

import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;

import java.io.FileDescriptor;
@@ -347,6 +347,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
        }};

    private Runnable mOnFlipRunnable;
    private InterceptedNotifications mIntercepted;

    public void setOnFlipRunnable(Runnable onFlipRunnable) {
        mOnFlipRunnable = onFlipRunnable;
@@ -357,7 +358,11 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
        super.setZenMode(mode);
        if (mModeIcon == null) return;
        if (!isDeviceProvisioned()) return;
        mModeIcon.setVisibility(mode != Settings.Global.ZEN_MODE_OFF ? View.VISIBLE : View.GONE);
        final boolean zen = mode != Settings.Global.ZEN_MODE_OFF;
        mModeIcon.setVisibility(zen ? View.VISIBLE : View.GONE);
        if (!zen) {
            mIntercepted.releaseIntercepted();
        }
    }

    @Override
@@ -365,7 +370,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
        mDisplay = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE))
                .getDefaultDisplay();
        updateDisplaySize();

        mIntercepted = new InterceptedNotifications(mContext, this);
        super.start(); // calls createAndAddWindows()

        addNavigationBar();
@@ -931,13 +936,19 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
        mStatusIcons.removeViewAt(viewIndex);
    }

    public UserHandle getCurrentUserHandle() {
        return new UserHandle(mCurrentUserId);
    }

    public void addNotification(IBinder key, StatusBarNotification notification) {
        if (DEBUG) Log.d(TAG, "addNotification score=" + notification.getScore());
        Entry shadeEntry = createNotificationViews(key, notification);
        if (shadeEntry == null) {
            return;
        }
        if (!shouldIntercept(notification.getNotification())) {
        if (mZenMode != Global.ZEN_MODE_OFF && mIntercepted.tryIntercept(key, notification)) {
            return;
        }
        if (mUseHeadsUp && shouldInterrupt(notification)) {
            if (DEBUG) Log.d(TAG, "launching notification in heads up mode");
            Entry interruptionCandidate = new Entry(key, notification, null);
@@ -975,7 +986,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
                tick(null, notification, true);
            }
        }
        }
        addNotificationViews(shadeEntry);
        // Recalculate the position of the sliding windows and the titles.
        setAreThereNotifications();
@@ -991,6 +1001,12 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
        }
    }

    @Override
    public void updateNotification(IBinder key, StatusBarNotification notification) {
        super.updateNotification(key, notification);
        mIntercepted.update(key, notification);
    }

    public void removeNotification(IBinder key) {
        StatusBarNotification old = removeNotificationViews(key);
        if (SPEW) Log.d(TAG, "removeNotification key=" + key + " old=" + old);
@@ -1012,7 +1028,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
                animateCollapsePanels();
            }
        }

        mIntercepted.remove(key);
        setAreThereNotifications();
    }

@@ -1129,7 +1145,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
                // in "public" mode (atop a secure keyguard), secret notifs are totally hidden
                continue;
            }
            if (shouldIntercept(ent.notification.getNotification())) {
            if (mIntercepted.isSyntheticEntry(ent)) {
                continue;
            }
            toShow.add(ent.icon);