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

Commit 008cea77 authored by Dan Sandler's avatar Dan Sandler
Browse files

Hide redundant foreground service notifications.

If an app with a foreground service has (at least one)
FLAG_FOREGROUND notification shown to the user, we allow
that to satisfy the requirement that the user be informed
about such things. But if the fg notification or its channel
is blocked by the user, we show the NOTE_FOREGROUND_SERVICES
notification (a/k/a Dianne's Dungeon) provided to us by the
activity manager.

Note that if even one of the foreground processes for the
current user is missing its disclosure notification, the
user will see the whole dungeon.

Bug: 36891897
Test: runtest -x frameworks/base/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java
Change-Id: I4f5d96f80b7c1901faadb56661a42d26f746aa88
parent 2f36ab88
Loading
Loading
Loading
Loading
+3 −0
Original line number Original line Diff line number Diff line
@@ -264,6 +264,9 @@ public class Dependency extends SystemUI {
        mProviders.put(AccessibilityManagerWrapper.class,
        mProviders.put(AccessibilityManagerWrapper.class,
                () -> new AccessibilityManagerWrapper(mContext));
                () -> new AccessibilityManagerWrapper(mContext));


        mProviders.put(ForegroundServiceController.class,
                () -> new ForegroundServiceControllerImpl(mContext));

        mProviders.put(UiOffloadThread.class, UiOffloadThread::new);
        mProviders.put(UiOffloadThread.class, UiOffloadThread::new);


        // Put all dependencies above here so the factory can override them if it wants.
        // Put all dependencies above here so the factory can override them if it wants.
+49 −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;

import android.service.notification.StatusBarNotification;

public interface ForegroundServiceController {
    /**
     * @param sbn notification that was just posted
     * @param importance
     */
    void addNotification(StatusBarNotification sbn, int importance);

    /**
     * @param sbn notification that was just changed in some way
     * @param newImportance
     */
    void updateNotification(StatusBarNotification sbn, int newImportance);

    /**
     * @param sbn notification that was just canceled
     */
    boolean removeNotification(StatusBarNotification sbn);

    /**
     * @param userId
     * @return true if this user has services missing notifications and therefore needs a
     * disclosure notification.
     */
    boolean isDungeonNeededForUser(int userId);

    /**
     * @param sbn
     * @return true if sbn is the system-provided "dungeon" (list of running foreground services).
     */
    boolean isDungeonNotification(StatusBarNotification sbn);
}
+156 −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;

import android.app.Notification;
import android.app.NotificationManager;
import android.content.Context;
import android.os.Bundle;
import android.service.notification.StatusBarNotification;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
import android.util.SparseArray;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.messages.nano.SystemMessageProto;

import java.util.Arrays;

/**
 * Foreground service controller, a/k/a Dianne's Dungeon.
 */
public class ForegroundServiceControllerImpl
        implements ForegroundServiceController {
    private static final String TAG = "FgServiceController";
    private static final boolean DBG = false;

    private final SparseArray<UserServices> mUserServices = new SparseArray<>();
    private final Object mMutex = new Object();

    public ForegroundServiceControllerImpl(Context context) {
    }

    @Override
    public boolean isDungeonNeededForUser(int userId) {
        synchronized (mMutex) {
            final UserServices services = mUserServices.get(userId);
            if (services == null) return false;
            return services.isDungeonNeeded();
        }
    }

    @Override
    public void addNotification(StatusBarNotification sbn, int importance) {
        updateNotification(sbn, importance);
    }

    @Override
    public boolean removeNotification(StatusBarNotification sbn) {
        synchronized (mMutex) {
            final UserServices userServices = mUserServices.get(sbn.getUserId());
            if (userServices == null) {
                if (DBG) {
                    Log.w(TAG, String.format(
                            "user %d with no known notifications got removeNotification for %s",
                            sbn.getUserId(), sbn));
                }
                return false;
            }
            if (isDungeonNotification(sbn)) {
                // if you remove the dungeon entirely, we take that to mean there are
                // no running services
                userServices.setRunningServices(null);
                return true;
            } else {
                // this is safe to call on any notification, not just FLAG_FOREGROUND_SERVICE
                return userServices.removeNotification(sbn.getPackageName(), sbn.getKey());
            }
        }
    }

    @Override
    public void updateNotification(StatusBarNotification sbn, int newImportance) {
        synchronized (mMutex) {
            UserServices userServices = mUserServices.get(sbn.getUserId());
            if (userServices == null) {
                userServices = new UserServices();
                mUserServices.put(sbn.getUserId(), userServices);
            }

            if (isDungeonNotification(sbn)) {
                final Bundle extras = sbn.getNotification().extras;
                if (extras != null) {
                    final String[] svcs = extras.getStringArray(Notification.EXTRA_FOREGROUND_APPS);
                    userServices.setRunningServices(svcs); // null ok
                }
            } else {
                userServices.removeNotification(sbn.getPackageName(), sbn.getKey());
                if (0 != (sbn.getNotification().flags & Notification.FLAG_FOREGROUND_SERVICE)
                        && newImportance > NotificationManager.IMPORTANCE_MIN) {
                    userServices.addNotification(sbn.getPackageName(), sbn.getKey());
                }
            }
        }
    }

    @Override
    public boolean isDungeonNotification(StatusBarNotification sbn) {
        return sbn.getId() == SystemMessageProto.SystemMessage.NOTE_FOREGROUND_SERVICES
                && sbn.getTag() == null
                && sbn.getPackageName().equals("android");
    }

    /**
     * Struct to track relevant packages and notifications for a userid's foreground services.
     */
    private static class UserServices {
        private String[] mRunning = null;
        private ArrayMap<String, ArraySet<String>> mNotifications = new ArrayMap<>(1);
        public void setRunningServices(String[] pkgs) {
            mRunning = pkgs != null ? Arrays.copyOf(pkgs, pkgs.length) : null;
        }
        public void addNotification(String pkg, String key) {
            if (mNotifications.get(pkg) == null) {
                mNotifications.put(pkg, new ArraySet<String>());
            }
            mNotifications.get(pkg).add(key);
        }
        public boolean removeNotification(String pkg, String key) {
            final boolean found;
            final ArraySet<String> keys = mNotifications.get(pkg);
            if (keys == null) {
                found = false;
            } else {
                found = keys.remove(key);
                if (keys.size() == 0) {
                    mNotifications.remove(pkg);
                }
            }
            return found;
        }
        public boolean isDungeonNeeded() {
            if (mRunning != null) {
                for (String pkg : mRunning) {
                    final ArraySet<String> set = mNotifications.get(pkg);
                    if (set == null || set.size() == 0) {
                        return true;
                    }
                }
            }
            return false;
        }
    }
}
+17 −0
Original line number Original line Diff line number Diff line
@@ -24,6 +24,8 @@ import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager;
import android.content.Context;
import android.content.Context;
import android.graphics.drawable.Icon;
import android.graphics.drawable.Icon;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.SystemClock;
import android.service.notification.NotificationListenerService;
import android.service.notification.NotificationListenerService;
@@ -38,8 +40,11 @@ import android.widget.RemoteViews;
import android.Manifest;
import android.Manifest;


import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.messages.nano.SystemMessageProto;
import com.android.internal.statusbar.StatusBarIcon;
import com.android.internal.statusbar.StatusBarIcon;
import com.android.internal.util.NotificationColorUtil;
import com.android.internal.util.NotificationColorUtil;
import com.android.systemui.Dependency;
import com.android.systemui.ForegroundServiceController;
import com.android.systemui.statusbar.notification.InflationException;
import com.android.systemui.statusbar.notification.InflationException;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.phone.StatusBar;
@@ -339,6 +344,7 @@ public class NotificationData {
            mEntries.put(entry.notification.getKey(), entry);
            mEntries.put(entry.notification.getKey(), entry);
        }
        }
        mGroupManager.onEntryAdded(entry);
        mGroupManager.onEntryAdded(entry);

        updateRankingAndSort(mRankingMap);
        updateRankingAndSort(mRankingMap);
    }
    }


@@ -466,6 +472,10 @@ public class NotificationData {
        Collections.sort(mSortedAndFiltered, mRankingComparator);
        Collections.sort(mSortedAndFiltered, mRankingComparator);
    }
    }


    /**
     * @param sbn
     * @return true if this notification should NOT be shown right now
     */
    public boolean shouldFilterOut(StatusBarNotification sbn) {
    public boolean shouldFilterOut(StatusBarNotification sbn) {
        if (!(mEnvironment.isDeviceProvisioned() ||
        if (!(mEnvironment.isDeviceProvisioned() ||
                showNotificationEvenIfUnprovisioned(sbn))) {
                showNotificationEvenIfUnprovisioned(sbn))) {
@@ -487,6 +497,13 @@ public class NotificationData {
                && mGroupManager.isChildInGroupWithSummary(sbn)) {
                && mGroupManager.isChildInGroupWithSummary(sbn)) {
            return true;
            return true;
        }
        }

        final ForegroundServiceController fsc = Dependency.get(ForegroundServiceController.class);
        if (fsc.isDungeonNotification(sbn) && !fsc.isDungeonNeededForUser(sbn.getUserId())) {
            // this is a foreground-service disclosure for a user that does not need to show one
            return true;
        }

        return false;
        return false;
    }
    }


+56 −43
Original line number Original line Diff line number Diff line
@@ -36,11 +36,17 @@ import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorListenerAdapter;
import android.annotation.NonNull;
import android.annotation.NonNull;
import android.app.ActivityManager;
import android.app.ActivityManager;
import android.app.ActivityManager.StackId;
import android.app.ActivityOptions;
import android.app.ActivityOptions;
import android.app.INotificationManager;
import android.app.KeyguardManager;
import android.app.Notification;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.PendingIntent;
import android.app.RemoteInput;
import android.app.StatusBarManager;
import android.app.StatusBarManager;
import android.app.TaskStackBuilder;
import android.app.admin.DevicePolicyManager;
import android.app.admin.DevicePolicyManager;
import android.content.BroadcastReceiver;
import android.content.BroadcastReceiver;
import android.content.ComponentCallbacks2;
import android.content.ComponentCallbacks2;
@@ -49,8 +55,11 @@ import android.content.Context;
import android.content.Intent;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.IntentFilter;
import android.content.IntentSender;
import android.content.IntentSender;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.UserInfo;
import android.content.res.Configuration;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.Resources;
import android.database.ContentObserver;
import android.database.ContentObserver;
@@ -75,7 +84,9 @@ import android.media.session.PlaybackState;
import android.metrics.LogMaker;
import android.metrics.LogMaker;
import android.net.Uri;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.IBinder;
import android.os.Message;
import android.os.Message;
import android.os.PowerManager;
import android.os.PowerManager;
@@ -83,54 +94,73 @@ import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.SystemProperties;
import android.os.SystemService;
import android.os.Trace;
import android.os.Trace;
import android.os.UserHandle;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.UserManager;
import android.os.Vibrator;
import android.os.Vibrator;
import android.provider.Settings;
import android.provider.Settings;
import android.service.notification.NotificationListenerService;
import android.service.notification.NotificationListenerService.RankingMap;
import android.service.notification.NotificationListenerService.RankingMap;
import android.service.notification.StatusBarNotification;
import android.service.notification.StatusBarNotification;
import android.service.vr.IVrManager;
import android.service.vr.IVrStateCallbacks;
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.ArraySet;
import android.util.DisplayMetrics;
import android.util.DisplayMetrics;
import android.util.EventLog;
import android.util.EventLog;
import android.util.Log;
import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.view.ContextThemeWrapper;
import android.view.ContextThemeWrapper;
import android.view.Display;
import android.view.Display;
import android.view.IWindowManager;
import android.view.KeyEvent;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.MotionEvent;
import android.view.ThreadedRenderer;
import android.view.ThreadedRenderer;
import android.view.View;
import android.view.View;
import android.view.ViewAnimationUtils;
import android.view.ViewGroup;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.view.ViewParent;
import android.view.ViewStub;
import android.view.ViewStub;
import android.view.ViewTreeObserver;
import android.view.ViewTreeObserver;
import android.view.WindowManager;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
import android.view.WindowManagerGlobal;
import android.view.accessibility.AccessibilityManager;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.Interpolator;
import android.view.animation.Interpolator;
import android.widget.DateTimeView;
import android.widget.DateTimeView;
import android.widget.ImageView;
import android.widget.ImageView;
import android.widget.RemoteViews;
import android.widget.TextView;
import android.widget.TextView;
import android.widget.Toast;


import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.statusbar.NotificationVisibility;
import com.android.internal.statusbar.NotificationVisibility;
import com.android.internal.statusbar.StatusBarIcon;
import com.android.internal.statusbar.StatusBarIcon;
import com.android.internal.util.NotificationMessagingUtil;
import com.android.internal.util.NotificationMessagingUtil;
import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardHostView.OnDismissAction;
import com.android.keyguard.KeyguardHostView.OnDismissAction;
import com.android.keyguard.KeyguardStatusView;
import com.android.keyguard.KeyguardStatusView;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.keyguard.ViewMediatorCallback;
import com.android.keyguard.ViewMediatorCallback;
import com.android.systemui.ActivityStarterDelegate;
import com.android.systemui.ActivityStarterDelegate;
import com.android.systemui.DejankUtils;
import com.android.systemui.DemoMode;
import com.android.systemui.DemoMode;
import com.android.systemui.Dependency;
import com.android.systemui.Dependency;
import com.android.systemui.EventLogTags;
import com.android.systemui.EventLogTags;
import com.android.systemui.ForegroundServiceController;
import com.android.systemui.Interpolators;
import com.android.systemui.Interpolators;
import com.android.systemui.Prefs;
import com.android.systemui.Prefs;
import com.android.systemui.R;
import com.android.systemui.R;
import com.android.systemui.RecentsComponent;
import com.android.systemui.SwipeHelper;
import com.android.systemui.SystemUI;
import com.android.systemui.SystemUIFactory;
import com.android.systemui.SystemUIFactory;
import com.android.systemui.UiOffloadThread;
import com.android.systemui.UiOffloadThread;
import com.android.systemui.assist.AssistManager;
import com.android.systemui.assist.AssistManager;
@@ -141,12 +171,14 @@ import com.android.systemui.doze.DozeLog;
import com.android.systemui.fragments.FragmentHostManager;
import com.android.systemui.fragments.FragmentHostManager;
import com.android.systemui.fragments.PluginFragmentListener;
import com.android.systemui.fragments.PluginFragmentListener;
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.plugins.qs.QS;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.qs.QS;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.MenuItem;
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.SnoozeOption;
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.SnoozeOption;
import com.android.systemui.qs.QSFragment;
import com.android.systemui.qs.QSFragment;
import com.android.systemui.qs.QSPanel;
import com.android.systemui.qs.QSPanel;
import com.android.systemui.qs.QSTileHost;
import com.android.systemui.qs.QSTileHost;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.ScreenPinningRequest;
import com.android.systemui.recents.ScreenPinningRequest;
import com.android.systemui.recents.events.EventBus;
import com.android.systemui.recents.events.EventBus;
import com.android.systemui.recents.events.activity.AppTransitionFinishedEvent;
import com.android.systemui.recents.events.activity.AppTransitionFinishedEvent;
@@ -194,11 +226,15 @@ import com.android.systemui.statusbar.policy.KeyguardUserSwitcher;
import com.android.systemui.statusbar.policy.NetworkController;
import com.android.systemui.statusbar.policy.NetworkController;
import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
import com.android.systemui.statusbar.policy.PreviewInflater;
import com.android.systemui.statusbar.policy.PreviewInflater;
import com.android.systemui.statusbar.policy.RemoteInputView;
import com.android.systemui.statusbar.policy.UserInfoController;
import com.android.systemui.statusbar.policy.UserInfoController;
import com.android.systemui.statusbar.policy.UserInfoControllerImpl;
import com.android.systemui.statusbar.policy.UserInfoControllerImpl;
import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.stack.NotificationStackScrollLayout.OnChildLocationsChangedListener;
import com.android.systemui.statusbar.stack.NotificationStackScrollLayout
        .OnChildLocationsChangedListener;
import com.android.systemui.statusbar.stack.StackStateAnimator;
import com.android.systemui.util.NotificationChannels;
import com.android.systemui.util.leak.LeakDetector;
import com.android.systemui.util.leak.LeakDetector;
import com.android.systemui.volume.VolumeComponent;
import com.android.systemui.volume.VolumeComponent;


@@ -209,48 +245,10 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Collection;
import java.util.Collections;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.app.ActivityManager.StackId;
import android.app.INotificationManager;
import android.app.KeyguardManager;
import android.app.NotificationChannel;
import android.app.RemoteInput;
import android.app.TaskStackBuilder;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.UserInfo;
import android.os.Build;
import android.os.Handler;
import android.service.notification.NotificationListenerService;
import android.service.vr.IVrManager;
import android.service.vr.IVrStateCallbacks;
import android.text.TextUtils;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.view.IWindowManager;
import android.view.ViewAnimationUtils;
import android.view.accessibility.AccessibilityManager;
import android.widget.RemoteViews;
import android.widget.Toast;

import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.widget.LockPatternUtils;
import com.android.systemui.DejankUtils;
import com.android.systemui.RecentsComponent;
import com.android.systemui.SwipeHelper;
import com.android.systemui.SystemUI;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.MenuItem;
import com.android.systemui.recents.Recents;
import com.android.systemui.statusbar.policy.RemoteInputView;
import com.android.systemui.statusbar.stack.StackStateAnimator;
import com.android.systemui.util.NotificationChannels;

import java.util.HashSet;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.Set;
import java.util.Stack;
import java.util.Stack;


@@ -718,6 +716,7 @@ public class StatusBar extends SystemUI implements DemoMode,
    private ConfigurationListener mConfigurationListener;
    private ConfigurationListener mConfigurationListener;
    private boolean mReinflateNotificationsOnUserSwitched;
    private boolean mReinflateNotificationsOnUserSwitched;
    private HashMap<String, Entry> mPendingNotifications = new HashMap<>();
    private HashMap<String, Entry> mPendingNotifications = new HashMap<>();
    private ForegroundServiceController mForegroundServiceController;


    private void recycleAllVisibilityObjects(ArraySet<NotificationVisibility> array) {
    private void recycleAllVisibilityObjects(ArraySet<NotificationVisibility> array) {
        final int N = array.size();
        final int N = array.size();
@@ -761,6 +760,8 @@ public class StatusBar extends SystemUI implements DemoMode,
        mDeviceProvisionedController = Dependency.get(DeviceProvisionedController.class);
        mDeviceProvisionedController = Dependency.get(DeviceProvisionedController.class);
        mSystemServicesProxy = SystemServicesProxy.getInstance(mContext);
        mSystemServicesProxy = SystemServicesProxy.getInstance(mContext);


        mForegroundServiceController = Dependency.get(ForegroundServiceController.class);

        mWindowManager = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
        mWindowManager = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
        mDisplay = mWindowManager.getDefaultDisplay();
        mDisplay = mWindowManager.getDefaultDisplay();
        updateDisplaySize();
        updateDisplaySize();
@@ -1578,6 +1579,10 @@ public class StatusBar extends SystemUI implements DemoMode,
            }
            }
        }
        }
        abortExistingInflation(key);
        abortExistingInflation(key);

        mForegroundServiceController.addNotification(notification,
                mNotificationData.getImportance(key));

        mPendingNotifications.put(key, shadeEntry);
        mPendingNotifications.put(key, shadeEntry);
    }
    }


@@ -1716,6 +1721,10 @@ public class StatusBar extends SystemUI implements DemoMode,
            return;
            return;
        }
        }


        if (entry != null) {
            mForegroundServiceController.removeNotification(entry.notification);
        }

        if (entry != null && entry.row != null) {
        if (entry != null && entry.row != null) {
            entry.row.setRemoved();
            entry.row.setRemoved();
            mStackScroller.cleanUpViewState(entry.row);
            mStackScroller.cleanUpViewState(entry.row);
@@ -6766,6 +6775,9 @@ public class StatusBar extends SystemUI implements DemoMode,
        entry.updateIcons(mContext, n);
        entry.updateIcons(mContext, n);
        inflateViews(entry, mStackScroller);
        inflateViews(entry, mStackScroller);


        mForegroundServiceController.updateNotification(notification,
                mNotificationData.getImportance(key));

        boolean shouldPeek = shouldPeek(entry, notification);
        boolean shouldPeek = shouldPeek(entry, notification);
        boolean alertAgain = alertAgain(entry, n);
        boolean alertAgain = alertAgain(entry, n);


@@ -6783,6 +6795,7 @@ public class StatusBar extends SystemUI implements DemoMode,
            boolean isForCurrentUser = isNotificationForCurrentProfiles(notification);
            boolean isForCurrentUser = isNotificationForCurrentProfiles(notification);
            Log.d(TAG, "notification is " + (isForCurrentUser ? "" : "not ") + "for you");
            Log.d(TAG, "notification is " + (isForCurrentUser ? "" : "not ") + "for you");
        }
        }

        setAreThereNotifications();
        setAreThereNotifications();
    }
    }


Loading