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

Commit dfa3298a authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Track non-foreground service notifs for appOps" into rvc-dev

parents 67cb3a61 546aa10d
Loading
Loading
Loading
Loading
+28 −24
Original line number Diff line number Diff line
@@ -29,6 +29,8 @@ import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.util.Assert;

import java.util.Set;

import javax.inject.Inject;
import javax.inject.Singleton;

@@ -62,7 +64,7 @@ public class ForegroundServiceController {

    /**
     * @return true if this user has services missing notifications and therefore needs a
     * disclosure notification.
     * disclosure notification for running a foreground service.
     */
    public boolean isDisclosureNeededForUser(int userId) {
        synchronized (mMutex) {
@@ -74,26 +76,26 @@ public class ForegroundServiceController {

    /**
     * @return true if this user/pkg has a missing or custom layout notification and therefore needs
     * a disclosure notification for system alert windows.
     * a disclosure notification showing the user which appsOps the app is using.
     */
    public boolean isSystemAlertWarningNeeded(int userId, String pkg) {
        synchronized (mMutex) {
            final ForegroundServicesUserState services = mUserServices.get(userId);
            if (services == null) return false;
            return services.getStandardLayoutKey(pkg) == null;
            return services.getStandardLayoutKeys(pkg) == null;
        }
    }

    /**
     * Returns the key of the foreground service from this package using the standard template,
     * if one exists.
     * Returns the keys for notifications from this package using the standard template,
     * if they exist.
     */
    @Nullable
    public String getStandardLayoutKey(int userId, String pkg) {
    public ArraySet<String> getStandardLayoutKeys(int userId, String pkg) {
        synchronized (mMutex) {
            final ForegroundServicesUserState services = mUserServices.get(userId);
            if (services == null) return null;
            return services.getStandardLayoutKey(pkg);
            return services.getStandardLayoutKeys(pkg);
        }
    }

@@ -140,20 +142,23 @@ public class ForegroundServiceController {
        }

        // TODO: (b/145659174) remove when moving to NewNotifPipeline. Replaced by
        //  ForegroundCoordinator
        // Update appOp if there's an associated pending or visible notification:
        final String foregroundKey = getStandardLayoutKey(userId, packageName);
        if (foregroundKey != null) {
            final NotificationEntry entry = mEntryManager.getPendingOrActiveNotif(foregroundKey);
        //  AppOpsCoordinator
        // Update appOps if there are associated pending or visible notifications
        final Set<String> notificationKeys = getStandardLayoutKeys(userId, packageName);
        if (notificationKeys != null) {
            boolean changed = false;
            for (String key : notificationKeys) {
                final NotificationEntry entry = mEntryManager.getPendingOrActiveNotif(key);
                if (entry != null
                        && uid == entry.getSbn().getUid()
                        && packageName.equals(entry.getSbn().getPackageName())) {
                boolean changed;
                    synchronized (entry.mActiveAppOps) {
                        if (active) {
                        changed = entry.mActiveAppOps.add(appOpCode);
                            changed |= entry.mActiveAppOps.add(appOpCode);
                        } else {
                        changed = entry.mActiveAppOps.remove(appOpCode);
                            changed |= entry.mActiveAppOps.remove(appOpCode);
                        }
                    }
                }
            }
            if (changed) {
@@ -161,7 +166,6 @@ public class ForegroundServiceController {
            }
        }
    }
    }

    /**
     * Looks up the {@link ForegroundServicesUserState} for the given {@code userId}, then performs
+13 −13
Original line number Diff line number Diff line
@@ -163,6 +163,7 @@ public class ForegroundServiceNotificationListener {
                                userState.addImportantNotification(sbn.getPackageName(),
                                        sbn.getKey());
                            }
                        }
                        final Notification.Builder builder =
                                Notification.Builder.recoverBuilder(
                                        mContext, sbn.getNotification());
@@ -171,23 +172,22 @@ public class ForegroundServiceNotificationListener {
                                    sbn.getPackageName(), sbn.getKey());
                        }
                    }
                    }
                    tagForeground(entry);
                    tagAppOps(entry);
                    return true;
                },
                true /* create if not found */);
    }

    // TODO: (b/145659174) remove when moving to NewNotifPipeline. Replaced by
    //  ForegroundCoordinator
    private void tagForeground(NotificationEntry entry) {
    //  AppOpsCoordinator
    private void tagAppOps(NotificationEntry entry) {
        final StatusBarNotification sbn = entry.getSbn();
        ArraySet<Integer> activeOps = mForegroundServiceController.getAppOps(
                sbn.getUserId(),
                sbn.getPackageName());
        if (activeOps != null) {
        synchronized (entry.mActiveAppOps) {
            entry.mActiveAppOps.clear();
            if (activeOps != null) {
                entry.mActiveAppOps.addAll(activeOps);
            }
        }
+14 −4
Original line number Diff line number Diff line
@@ -30,9 +30,11 @@ public class ForegroundServicesUserState {

    private String[] mRunning = null;
    private long mServiceStartTime = 0;
    // package -> sufficiently important posted notification keys

    // package -> sufficiently important posted notification keys that signal an app is
    // running a foreground service
    private ArrayMap<String, ArraySet<String>> mImportantNotifications = new ArrayMap<>(1);
    // package -> standard layout posted notification keys
    // package -> standard layout posted notification keys that can display appOps
    private ArrayMap<String, ArraySet<String>> mStandardLayoutNotifications = new ArrayMap<>(1);

    // package -> app ops
@@ -110,6 +112,11 @@ public class ForegroundServicesUserState {
        return found;
    }

    /**
     * System disclosures for foreground services are required if an app has a foreground service
     * running AND the app hasn't posted its own notification signalling it is running a
     * foreground service
     */
    public boolean isDisclosureNeeded() {
        if (mRunning != null
                && System.currentTimeMillis() - mServiceStartTime
@@ -129,12 +136,15 @@ public class ForegroundServicesUserState {
        return mAppOps.get(pkg);
    }

    public String getStandardLayoutKey(String pkg) {
    /**
     * Gets the notifications with standard layouts associated with this package
     */
    public ArraySet<String> getStandardLayoutKeys(String pkg) {
        final ArraySet<String> set = mStandardLayoutNotifications.get(pkg);
        if (set == null || set.size() == 0) {
            return null;
        }
        return set.valueAt(0);
        return set;
    }

    @Override
+33 −28
Original line number Diff line number Diff line
@@ -39,8 +39,8 @@ import javax.inject.Inject;
import javax.inject.Singleton;

/**
 * Handles ForegroundService interactions with notifications.
 *  Tags notifications with appOps.
 * Handles ForegroundService and AppOp interactions with notifications.
 *  Tags notifications with appOps
 *  Lifetime extends notifications associated with an ongoing ForegroundService.
 *  Filters out notifications that represent foreground services that are no longer running
 *
@@ -48,12 +48,10 @@ import javax.inject.Singleton;
 *  frameworks/base/packages/SystemUI/src/com/android/systemui/ForegroundServiceController
 *  frameworks/base/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener
 *  frameworks/base/packages/SystemUI/src/com/android/systemui/ForegroundServiceLifetimeExtender
 *
 *  TODO: AppOps stuff should be spun off into its own coordinator
 */
@Singleton
public class ForegroundCoordinator implements Coordinator {
    private static final String TAG = "ForegroundCoordinator";
public class AppOpsCoordinator implements Coordinator {
    private static final String TAG = "AppOpsCoordinator";

    private final ForegroundServiceController mForegroundServiceController;
    private final AppOpsController mAppOpsController;
@@ -62,7 +60,7 @@ public class ForegroundCoordinator implements Coordinator {
    private NotifPipeline mNotifPipeline;

    @Inject
    public ForegroundCoordinator(
    public AppOpsCoordinator(
            ForegroundServiceController foregroundServiceController,
            AppOpsController appOpsController,
            @Main DelayableExecutor mainExecutor) {
@@ -89,18 +87,22 @@ public class ForegroundCoordinator implements Coordinator {
    }

    /**
     * Filters out notifications that represent foreground services that are no longer running.
     * Filters out notifications that represent foreground services that are no longer running or
     * that already have an app notification with the appOps tagged to
     */
    private final NotifFilter mNotifFilter = new NotifFilter(TAG) {
        @Override
        public boolean shouldFilterOut(NotificationEntry entry, long now) {
            StatusBarNotification sbn = entry.getSbn();

            // Filters out system-posted disclosure notifications when unneeded
            if (mForegroundServiceController.isDisclosureNotification(sbn)
                    && !mForegroundServiceController.isDisclosureNeededForUser(
                            sbn.getUser().getIdentifier())) {
                return true;
            }

            // Filters out system alert notifications when unneeded
            if (mForegroundServiceController.isSystemAlertNotification(sbn)) {
                final String[] apps = sbn.getNotification().extras.getStringArray(
                        Notification.EXTRA_FOREGROUND_APPS);
@@ -179,23 +181,24 @@ public class ForegroundCoordinator implements Coordinator {
    private NotifCollectionListener mNotifCollectionListener = new NotifCollectionListener() {
        @Override
        public void onEntryAdded(NotificationEntry entry) {
            tagForeground(entry);
            tagAppOps(entry);
        }

        @Override
        public void onEntryUpdated(NotificationEntry entry) {
            tagForeground(entry);
            tagAppOps(entry);
        }

        private void tagForeground(NotificationEntry entry) {
        private void tagAppOps(NotificationEntry entry) {
            final StatusBarNotification sbn = entry.getSbn();
            // note: requires that the ForegroundServiceController is updating their appOps first
            ArraySet<Integer> activeOps =
                    mForegroundServiceController.getAppOps(
                            sbn.getUser().getIdentifier(),
                            sbn.getPackageName());
            if (activeOps != null) {

            entry.mActiveAppOps.clear();
            if (activeOps != null) {
                entry.mActiveAppOps.addAll(activeOps);
            }
        }
@@ -218,26 +221,28 @@ public class ForegroundCoordinator implements Coordinator {

        int userId = UserHandle.getUserId(uid);

        // Update appOp if there's an associated posted notification:
        final String foregroundKey = mForegroundServiceController.getStandardLayoutKey(userId,
                packageName);
        if (foregroundKey != null) {
            final NotificationEntry entry = findNotificationEntryWithKey(foregroundKey);
        // Update appOps of the app's posted notifications with standard layouts
        final ArraySet<String> notifKeys =
                mForegroundServiceController.getStandardLayoutKeys(userId, packageName);
        if (notifKeys != null) {
            boolean changed = false;
            for (int i = 0; i < notifKeys.size(); i++) {
                final NotificationEntry entry = findNotificationEntryWithKey(notifKeys.valueAt(i));
                if (entry != null
                        && uid == entry.getSbn().getUid()
                        && packageName.equals(entry.getSbn().getPackageName())) {
                boolean changed;
                    if (active) {
                    changed = entry.mActiveAppOps.add(code);
                        changed |= entry.mActiveAppOps.add(code);
                    } else {
                    changed = entry.mActiveAppOps.remove(code);
                        changed |= entry.mActiveAppOps.remove(code);
                    }
                }
            }
            if (changed) {
                mNotifFilter.invalidateList();
            }
        }
    }
    }

    private NotificationEntry findNotificationEntryWithKey(String key) {
        for (NotificationEntry entry : mNotifPipeline.getAllNotifs()) {
+2 −2
Original line number Diff line number Diff line
@@ -52,7 +52,7 @@ public class NotifCoordinators implements Dumpable {
            HideNotifsForOtherUsersCoordinator hideNotifsForOtherUsersCoordinator,
            KeyguardCoordinator keyguardCoordinator,
            RankingCoordinator rankingCoordinator,
            ForegroundCoordinator foregroundCoordinator,
            AppOpsCoordinator appOpsCoordinator,
            DeviceProvisionedCoordinator deviceProvisionedCoordinator,
            BubbleCoordinator bubbleCoordinator,
            HeadsUpCoordinator headsUpCoordinator,
@@ -64,7 +64,7 @@ public class NotifCoordinators implements Dumpable {
        mCoordinators.add(hideNotifsForOtherUsersCoordinator);
        mCoordinators.add(keyguardCoordinator);
        mCoordinators.add(rankingCoordinator);
        mCoordinators.add(foregroundCoordinator);
        mCoordinators.add(appOpsCoordinator);
        mCoordinators.add(deviceProvisionedCoordinator);
        mCoordinators.add(bubbleCoordinator);
        if (featureFlags.isNewNotifPipelineRenderingEnabled()) {
Loading