From fe375f3606ca7da816ad1755e4c0f7754ebfbb27 Mon Sep 17 00:00:00 2001 From: Julia Reynolds Date: Mon, 7 Aug 2023 15:45:31 -0400 Subject: [PATCH] Remove obsolete FGS notification code The features that used this code were turned off several years ago. Test: atest SystemUITests Test: run FGS - see notification in shade and app in task manager Fixes: 275709313 Change-Id: Ie21fc03ac243932426e78c36ce2ec34d1a16a173 --- .../src/com/android/systemui/Dependency.java | 7 +- .../systemui/ForegroundServiceController.java | 183 ------- ...ForegroundServiceNotificationListener.java | 150 ------ .../coordinator/AppOpsCoordinator.java | 130 ----- .../coordinator/ColorizedFgsCoordinator.java | 81 +++ .../coordinator/NotifCoordinators.kt | 60 +-- .../init/NotificationsControllerImpl.kt | 3 - .../ForegroundServiceControllerTest.java | 487 ------------------ ....java => ColorizedFgsCoordinatorTest.java} | 56 +- .../StatusBarNotificationPresenterTest.java | 2 - 10 files changed, 119 insertions(+), 1040 deletions(-) delete mode 100644 packages/SystemUI/src/com/android/systemui/ForegroundServiceController.java delete mode 100644 packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java delete mode 100644 packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinator.java create mode 100644 packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ColorizedFgsCoordinator.java delete mode 100644 packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java rename packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/{AppOpsCoordinatorTest.java => ColorizedFgsCoordinatorTest.java} (69%) diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java index 04acd0b911736..27b9056da81cf 100644 --- a/packages/SystemUI/src/com/android/systemui/Dependency.java +++ b/packages/SystemUI/src/com/android/systemui/Dependency.java @@ -131,14 +131,14 @@ import com.android.systemui.util.leak.LeakDetector; import com.android.systemui.util.leak.LeakReporter; import com.android.systemui.util.sensors.AsyncSensorManager; -import dagger.Lazy; - import java.util.concurrent.Executor; import java.util.function.Consumer; import javax.inject.Inject; import javax.inject.Named; +import dagger.Lazy; + /** * Class to handle ugly dependencies throughout sysui until we determine the * long-term dependency injection solution. @@ -280,7 +280,6 @@ public class Dependency { @Inject Lazy mAccessibilityManagerWrapper; @Inject Lazy mSysuiColorExtractor; @Inject Lazy mTunablePaddingService; - @Inject Lazy mForegroundServiceController; @Inject Lazy mUiOffloadThread; @Inject Lazy mWarningsUI; @Inject Lazy mLightBarController; @@ -458,8 +457,6 @@ public class Dependency { mProviders.put(TunablePaddingService.class, mTunablePaddingService::get); - mProviders.put(ForegroundServiceController.class, mForegroundServiceController::get); - mProviders.put(UiOffloadThread.class, mUiOffloadThread::get); mProviders.put(PowerUI.WarningsUI.class, mWarningsUI::get); diff --git a/packages/SystemUI/src/com/android/systemui/ForegroundServiceController.java b/packages/SystemUI/src/com/android/systemui/ForegroundServiceController.java deleted file mode 100644 index 15e8c4e7abfb4..0000000000000 --- a/packages/SystemUI/src/com/android/systemui/ForegroundServiceController.java +++ /dev/null @@ -1,183 +0,0 @@ -/* - * 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.annotation.Nullable; -import android.app.AppOpsManager; -import android.os.Handler; -import android.os.UserHandle; -import android.service.notification.StatusBarNotification; -import android.util.ArraySet; -import android.util.SparseArray; - -import com.android.internal.messages.nano.SystemMessageProto; -import com.android.systemui.appops.AppOpsController; -import com.android.systemui.dagger.SysUISingleton; -import com.android.systemui.dagger.qualifiers.Main; -import com.android.systemui.util.Assert; - -import javax.inject.Inject; - -/** - * Tracks state of foreground services and notifications related to foreground services per user. - */ -@SysUISingleton -public class ForegroundServiceController { - public static final int[] APP_OPS = new int[] {AppOpsManager.OP_SYSTEM_ALERT_WINDOW}; - - private final SparseArray mUserServices = new SparseArray<>(); - private final Object mMutex = new Object(); - private final Handler mMainHandler; - - @Inject - public ForegroundServiceController( - AppOpsController appOpsController, - @Main Handler mainHandler) { - mMainHandler = mainHandler; - appOpsController.addCallback(APP_OPS, (code, uid, packageName, active) -> { - mMainHandler.post(() -> { - onAppOpChanged(code, uid, packageName, active); - }); - }); - } - - /** - * @return true if this user has services missing notifications and therefore needs a - * disclosure notification for running a foreground service. - */ - public boolean isDisclosureNeededForUser(int userId) { - synchronized (mMutex) { - final ForegroundServicesUserState services = mUserServices.get(userId); - if (services == null) return false; - return services.isDisclosureNeeded(); - } - } - - /** - * @return true if this user/pkg has a missing or custom layout notification and therefore needs - * 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.getStandardLayoutKeys(pkg) == null; - } - } - - /** - * Gets active app ops for this user and package - */ - @Nullable - public ArraySet getAppOps(int userId, String pkg) { - synchronized (mMutex) { - final ForegroundServicesUserState services = mUserServices.get(userId); - if (services == null) { - return null; - } - return services.getFeatures(pkg); - } - } - - /** - * Records active app ops and updates the app op for the pending or visible notifications - * with the given parameters. - * App Ops are stored in FSC in addition to NotificationEntry in case they change before we - * have a notification to tag. - * @param appOpCode code for appOp to add/remove - * @param uid of user the notification is sent to - * @param packageName package that created the notification - * @param active whether the appOpCode is active or not - */ - void onAppOpChanged(int appOpCode, int uid, String packageName, boolean active) { - Assert.isMainThread(); - - int userId = UserHandle.getUserId(uid); - // Record active app ops - synchronized (mMutex) { - ForegroundServicesUserState userServices = mUserServices.get(userId); - if (userServices == null) { - userServices = new ForegroundServicesUserState(); - mUserServices.put(userId, userServices); - } - if (active) { - userServices.addOp(packageName, appOpCode); - } else { - userServices.removeOp(packageName, appOpCode); - } - } - } - - /** - * Looks up the {@link ForegroundServicesUserState} for the given {@code userId}, then performs - * the given {@link UserStateUpdateCallback} on it. If no state exists for the user ID, creates - * a new one if {@code createIfNotFound} is true, then performs the update on the new state. - * If {@code createIfNotFound} is false, no update is performed. - * - * @return false if no user state was found and none was created; true otherwise. - */ - boolean updateUserState(int userId, - UserStateUpdateCallback updateCallback, - boolean createIfNotFound) { - synchronized (mMutex) { - ForegroundServicesUserState userState = mUserServices.get(userId); - if (userState == null) { - if (createIfNotFound) { - userState = new ForegroundServicesUserState(); - mUserServices.put(userId, userState); - } else { - return false; - } - } - return updateCallback.updateUserState(userState); - } - } - - /** - * @return true if {@code sbn} is the system-provided disclosure notification containing the - * list of running foreground services. - */ - public boolean isDisclosureNotification(StatusBarNotification sbn) { - return sbn.getId() == SystemMessageProto.SystemMessage.NOTE_FOREGROUND_SERVICES - && sbn.getTag() == null - && sbn.getPackageName().equals("android"); - } - - /** - * @return true if sbn is one of the window manager "drawing over other apps" notifications - */ - public boolean isSystemAlertNotification(StatusBarNotification sbn) { - return sbn.getPackageName().equals("android") - && sbn.getTag() != null - && sbn.getTag().contains("AlertWindowNotification"); - } - - /** - * Callback provided to {@link #updateUserState(int, UserStateUpdateCallback, boolean)} - * to perform the update. - */ - interface UserStateUpdateCallback { - /** - * Perform update operations on the provided {@code userState}. - * - * @return true if the update succeeded. - */ - boolean updateUserState(ForegroundServicesUserState userState); - - /** Called if the state was not found and was not created. */ - default void userStateNotFound(int userId) { - } - } -} diff --git a/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java b/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java deleted file mode 100644 index a1a3b7280fa99..0000000000000 --- a/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (C) 2018 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.Log; - -import com.android.systemui.dagger.SysUISingleton; -import com.android.systemui.statusbar.notification.collection.NotifPipeline; -import com.android.systemui.statusbar.notification.collection.NotificationEntry; -import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener; - -import javax.inject.Inject; - -/** Updates foreground service notification state in response to notification data events. */ -@SysUISingleton -public class ForegroundServiceNotificationListener { - - private static final String TAG = "FgServiceController"; - private static final boolean DBG = false; - - private final Context mContext; - private final ForegroundServiceController mForegroundServiceController; - private final NotifPipeline mNotifPipeline; - - @Inject - public ForegroundServiceNotificationListener(Context context, - ForegroundServiceController foregroundServiceController, - NotifPipeline notifPipeline) { - mContext = context; - mForegroundServiceController = foregroundServiceController; - mNotifPipeline = notifPipeline; - } - - /** Initializes this listener by connecting it to the notification pipeline. */ - public void init() { - mNotifPipeline.addCollectionListener(new NotifCollectionListener() { - @Override - public void onEntryAdded(NotificationEntry entry) { - addNotification(entry, entry.getImportance()); - } - - @Override - public void onEntryUpdated(NotificationEntry entry) { - updateNotification(entry, entry.getImportance()); - } - - @Override - public void onEntryRemoved(NotificationEntry entry, int reason) { - removeNotification(entry.getSbn()); - } - }); - } - - /** - * @param entry notification that was just posted - */ - private void addNotification(NotificationEntry entry, int importance) { - updateNotification(entry, importance); - } - - /** - * @param sbn notification that was just removed - */ - private void removeNotification(StatusBarNotification sbn) { - mForegroundServiceController.updateUserState( - sbn.getUserId(), - new ForegroundServiceController.UserStateUpdateCallback() { - @Override - public boolean updateUserState(ForegroundServicesUserState userState) { - if (mForegroundServiceController.isDisclosureNotification(sbn)) { - // if you remove the dungeon entirely, we take that to mean there are - // no running services - userState.setRunningServices(null, 0); - return true; - } else { - // this is safe to call on any notification, not just - // FLAG_FOREGROUND_SERVICE - return userState.removeNotification(sbn.getPackageName(), sbn.getKey()); - } - } - - @Override - public void userStateNotFound(int userId) { - if (DBG) { - Log.w(TAG, String.format( - "user %d with no known notifications got removeNotification " - + "for %s", - sbn.getUserId(), sbn)); - } - } - }, - false /* don't create */); - } - - /** - * @param entry notification that was just changed in some way - */ - private void updateNotification(NotificationEntry entry, int newImportance) { - final StatusBarNotification sbn = entry.getSbn(); - mForegroundServiceController.updateUserState( - sbn.getUserId(), - userState -> { - if (mForegroundServiceController.isDisclosureNotification(sbn)) { - final Bundle extras = sbn.getNotification().extras; - if (extras != null) { - final String[] svcs = extras.getStringArray( - Notification.EXTRA_FOREGROUND_APPS); - userState.setRunningServices(svcs, sbn.getNotification().when); - } - } else { - userState.removeNotification(sbn.getPackageName(), sbn.getKey()); - if (0 != (sbn.getNotification().flags - & Notification.FLAG_FOREGROUND_SERVICE)) { - if (newImportance > NotificationManager.IMPORTANCE_MIN) { - userState.addImportantNotification(sbn.getPackageName(), - sbn.getKey()); - } - } - final Notification.Builder builder = - Notification.Builder.recoverBuilder( - mContext, sbn.getNotification()); - if (builder.usesStandardHeader()) { - userState.addStandardLayoutNotification( - sbn.getPackageName(), sbn.getKey()); - } - } - return true; - }, - true /* create if not found */); - } -} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinator.java deleted file mode 100644 index f04b24ebfb42b..0000000000000 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinator.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (C) 2019 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.notification.collection.coordinator; - -import static android.app.NotificationManager.IMPORTANCE_MIN; - -import android.app.Notification; -import android.service.notification.StatusBarNotification; - -import com.android.systemui.ForegroundServiceController; -import com.android.systemui.appops.AppOpsController; -import com.android.systemui.dagger.qualifiers.Main; -import com.android.systemui.statusbar.notification.collection.ListEntry; -import com.android.systemui.statusbar.notification.collection.NotifPipeline; -import com.android.systemui.statusbar.notification.collection.NotificationEntry; -import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope; -import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter; -import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner; -import com.android.systemui.statusbar.notification.stack.NotificationPriorityBucketKt; -import com.android.systemui.util.concurrency.DelayableExecutor; - -import javax.inject.Inject; - -/** - * 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 - * Puts foreground service notifications into the FGS section. See {@link NotifCoordinators} for - * section ordering priority. - * - * Previously this logic lived in - * 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 - */ -@CoordinatorScope -public class AppOpsCoordinator implements Coordinator { - private static final String TAG = "AppOpsCoordinator"; - - private final ForegroundServiceController mForegroundServiceController; - private final AppOpsController mAppOpsController; - private final DelayableExecutor mMainExecutor; - - private NotifPipeline mNotifPipeline; - - @Inject - public AppOpsCoordinator( - ForegroundServiceController foregroundServiceController, - AppOpsController appOpsController, - @Main DelayableExecutor mainExecutor) { - mForegroundServiceController = foregroundServiceController; - mAppOpsController = appOpsController; - mMainExecutor = mainExecutor; - } - - @Override - public void attach(NotifPipeline pipeline) { - mNotifPipeline = pipeline; - - // filter out foreground service notifications that aren't necessary anymore - mNotifPipeline.addPreGroupFilter(mNotifFilter); - - } - - public NotifSectioner getSectioner() { - return mNotifSectioner; - } - - /** - * 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; - } - return false; - } - }; - - /** - * Puts colorized foreground service and call notifications into its own section. - */ - private final NotifSectioner mNotifSectioner = new NotifSectioner("ForegroundService", - NotificationPriorityBucketKt.BUCKET_FOREGROUND_SERVICE) { - @Override - public boolean isInSection(ListEntry entry) { - NotificationEntry notificationEntry = entry.getRepresentativeEntry(); - if (notificationEntry != null) { - return isColorizedForegroundService(notificationEntry) || isCall(notificationEntry); - } - return false; - } - - private boolean isColorizedForegroundService(NotificationEntry entry) { - Notification notification = entry.getSbn().getNotification(); - return notification.isForegroundService() - && notification.isColorized() - && entry.getImportance() > IMPORTANCE_MIN; - } - - private boolean isCall(NotificationEntry entry) { - Notification notification = entry.getSbn().getNotification(); - return entry.getImportance() > IMPORTANCE_MIN - && notification.isStyle(Notification.CallStyle.class); - } - }; -} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ColorizedFgsCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ColorizedFgsCoordinator.java new file mode 100644 index 0000000000000..63997f8f24572 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ColorizedFgsCoordinator.java @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2019 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.notification.collection.coordinator; + +import static android.app.NotificationManager.IMPORTANCE_MIN; + +import android.app.Notification; + +import com.android.systemui.statusbar.notification.collection.ListEntry; +import com.android.systemui.statusbar.notification.collection.NotifPipeline; +import com.android.systemui.statusbar.notification.collection.NotificationEntry; +import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope; +import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner; +import com.android.systemui.statusbar.notification.stack.NotificationPriorityBucketKt; + +import javax.inject.Inject; + +/** + * Handles sectioning for foreground service notifications. + * Puts non-min colorized foreground service notifications into the FGS section. See + * {@link NotifCoordinators} for section ordering priority. + */ +@CoordinatorScope +public class ColorizedFgsCoordinator implements Coordinator { + private static final String TAG = "ColorizedCoordinator"; + + @Inject + public ColorizedFgsCoordinator() { + } + + @Override + public void attach(NotifPipeline pipeline) { + } + + public NotifSectioner getSectioner() { + return mNotifSectioner; + } + + + /** + * Puts colorized foreground service and call notifications into its own section. + */ + private final NotifSectioner mNotifSectioner = new NotifSectioner("ColorizedSectioner", + NotificationPriorityBucketKt.BUCKET_FOREGROUND_SERVICE) { + @Override + public boolean isInSection(ListEntry entry) { + NotificationEntry notificationEntry = entry.getRepresentativeEntry(); + if (notificationEntry != null) { + return isColorizedForegroundService(notificationEntry) || isCall(notificationEntry); + } + return false; + } + + private boolean isColorizedForegroundService(NotificationEntry entry) { + Notification notification = entry.getSbn().getNotification(); + return notification.isForegroundService() + && notification.isColorized() + && entry.getImportance() > IMPORTANCE_MIN; + } + + private boolean isCall(NotificationEntry entry) { + Notification notification = entry.getSbn().getNotification(); + return entry.getImportance() > IMPORTANCE_MIN + && notification.isStyle(Notification.CallStyle.class); + } + }; +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.kt index 0ccab9e46b729..226a9577c8208 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.kt @@ -33,34 +33,34 @@ interface NotifCoordinators : Coordinator, PipelineDumpable @CoordinatorScope class NotifCoordinatorsImpl @Inject constructor( - sectionStyleProvider: SectionStyleProvider, - featureFlags: FeatureFlags, - dataStoreCoordinator: DataStoreCoordinator, - hideLocallyDismissedNotifsCoordinator: HideLocallyDismissedNotifsCoordinator, - hideNotifsForOtherUsersCoordinator: HideNotifsForOtherUsersCoordinator, - keyguardCoordinator: KeyguardCoordinator, - rankingCoordinator: RankingCoordinator, - appOpsCoordinator: AppOpsCoordinator, - deviceProvisionedCoordinator: DeviceProvisionedCoordinator, - bubbleCoordinator: BubbleCoordinator, - headsUpCoordinator: HeadsUpCoordinator, - gutsCoordinator: GutsCoordinator, - conversationCoordinator: ConversationCoordinator, - debugModeCoordinator: DebugModeCoordinator, - groupCountCoordinator: GroupCountCoordinator, - groupWhenCoordinator: GroupWhenCoordinator, - mediaCoordinator: MediaCoordinator, - preparationCoordinator: PreparationCoordinator, - remoteInputCoordinator: RemoteInputCoordinator, - rowAppearanceCoordinator: RowAppearanceCoordinator, - stackCoordinator: StackCoordinator, - shadeEventCoordinator: ShadeEventCoordinator, - smartspaceDedupingCoordinator: SmartspaceDedupingCoordinator, - viewConfigCoordinator: ViewConfigCoordinator, - visualStabilityCoordinator: VisualStabilityCoordinator, - sensitiveContentCoordinator: SensitiveContentCoordinator, - dismissibilityCoordinator: DismissibilityCoordinator, - dreamCoordinator: DreamCoordinator, + sectionStyleProvider: SectionStyleProvider, + featureFlags: FeatureFlags, + dataStoreCoordinator: DataStoreCoordinator, + hideLocallyDismissedNotifsCoordinator: HideLocallyDismissedNotifsCoordinator, + hideNotifsForOtherUsersCoordinator: HideNotifsForOtherUsersCoordinator, + keyguardCoordinator: KeyguardCoordinator, + rankingCoordinator: RankingCoordinator, + colorizedFgsCoordinator: ColorizedFgsCoordinator, + deviceProvisionedCoordinator: DeviceProvisionedCoordinator, + bubbleCoordinator: BubbleCoordinator, + headsUpCoordinator: HeadsUpCoordinator, + gutsCoordinator: GutsCoordinator, + conversationCoordinator: ConversationCoordinator, + debugModeCoordinator: DebugModeCoordinator, + groupCountCoordinator: GroupCountCoordinator, + groupWhenCoordinator: GroupWhenCoordinator, + mediaCoordinator: MediaCoordinator, + preparationCoordinator: PreparationCoordinator, + remoteInputCoordinator: RemoteInputCoordinator, + rowAppearanceCoordinator: RowAppearanceCoordinator, + stackCoordinator: StackCoordinator, + shadeEventCoordinator: ShadeEventCoordinator, + smartspaceDedupingCoordinator: SmartspaceDedupingCoordinator, + viewConfigCoordinator: ViewConfigCoordinator, + visualStabilityCoordinator: VisualStabilityCoordinator, + sensitiveContentCoordinator: SensitiveContentCoordinator, + dismissibilityCoordinator: DismissibilityCoordinator, + dreamCoordinator: DreamCoordinator, ) : NotifCoordinators { private val mCoreCoordinators: MutableList = ArrayList() @@ -79,7 +79,7 @@ class NotifCoordinatorsImpl @Inject constructor( mCoordinators.add(hideNotifsForOtherUsersCoordinator) mCoordinators.add(keyguardCoordinator) mCoordinators.add(rankingCoordinator) - mCoordinators.add(appOpsCoordinator) + mCoordinators.add(colorizedFgsCoordinator) mCoordinators.add(deviceProvisionedCoordinator) mCoordinators.add(bubbleCoordinator) mCoordinators.add(debugModeCoordinator) @@ -106,7 +106,7 @@ class NotifCoordinatorsImpl @Inject constructor( // Manually add Ordered Sections mOrderedSections.add(headsUpCoordinator.sectioner) // HeadsUp - mOrderedSections.add(appOpsCoordinator.sectioner) // ForegroundService + mOrderedSections.add(colorizedFgsCoordinator.sectioner) // ForegroundService mOrderedSections.add(conversationCoordinator.peopleAlertingSectioner) // People Alerting mOrderedSections.add(conversationCoordinator.peopleSilentSectioner) // People Silent mOrderedSections.add(rankingCoordinator.alertingSectioner) // Alerting diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt index 106d11f6bcc13..7d1cca81e6140 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt @@ -17,7 +17,6 @@ package com.android.systemui.statusbar.notification.init import android.service.notification.StatusBarNotification -import com.android.systemui.ForegroundServiceNotificationListener import com.android.systemui.dagger.SysUISingleton import com.android.systemui.flags.FeatureFlags import com.android.systemui.people.widget.PeopleSpaceWidgetManager @@ -70,7 +69,6 @@ class NotificationsControllerImpl @Inject constructor( private val animatedImageNotificationManager: AnimatedImageNotificationManager, private val peopleSpaceWidgetManager: PeopleSpaceWidgetManager, private val bubblesOptional: Optional, - private val fgsNotifListener: ForegroundServiceNotificationListener, private val featureFlags: FeatureFlags ) : NotificationsController { @@ -105,7 +103,6 @@ class NotificationsControllerImpl @Inject constructor( notificationsMediaManager.setUpWithPresenter(presenter) notificationLogger.setUpWithContainer(listContainer) peopleSpaceWidgetManager.attach(notificationListener) - fgsNotifListener.init() } // TODO: Convert all functions below this line into listeners instead of public methods diff --git a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java deleted file mode 100644 index b47b08c2d14c2..0000000000000 --- a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java +++ /dev/null @@ -1,487 +0,0 @@ -/* - * 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 static android.service.notification.NotificationListenerService.REASON_APP_CANCEL; - -import static junit.framework.Assert.assertEquals; -import static junit.framework.Assert.assertNull; -import static junit.framework.TestCase.fail; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.annotation.UserIdInt; -import android.app.AppOpsManager; -import android.app.Notification; -import android.app.NotificationManager; -import android.os.Bundle; -import android.os.Handler; -import android.os.UserHandle; -import android.service.notification.StatusBarNotification; -import android.testing.AndroidTestingRunner; -import android.testing.TestableLooper; -import android.widget.RemoteViews; - -import androidx.test.filters.SmallTest; - -import com.android.internal.messages.nano.SystemMessageProto; -import com.android.systemui.appops.AppOpsController; -import com.android.systemui.statusbar.notification.collection.NotifPipeline; -import com.android.systemui.statusbar.notification.collection.NotificationEntry; -import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder; -import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -@SmallTest -@RunWith(AndroidTestingRunner.class) -@TestableLooper.RunWithLooper -public class ForegroundServiceControllerTest extends SysuiTestCase { - private ForegroundServiceController mFsc; - private ForegroundServiceNotificationListener mListener; - private NotifCollectionListener mCollectionListener; - @Mock private AppOpsController mAppOpsController; - @Mock private Handler mMainHandler; - @Mock private NotifPipeline mNotifPipeline; - - @Before - public void setUp() throws Exception { - // allow the TestLooper to be asserted as the main thread these tests - allowTestableLooperAsMainThread(); - - MockitoAnnotations.initMocks(this); - mFsc = new ForegroundServiceController(mAppOpsController, mMainHandler); - mListener = new ForegroundServiceNotificationListener( - mContext, mFsc, mNotifPipeline); - mListener.init(); - ArgumentCaptor entryListenerCaptor = - ArgumentCaptor.forClass(NotifCollectionListener.class); - verify(mNotifPipeline).addCollectionListener( - entryListenerCaptor.capture()); - mCollectionListener = entryListenerCaptor.getValue(); - } - - @Test - public void testAppOpsChangedCalledFromBgThread() { - try { - // WHEN onAppOpChanged is called from a different thread than the MainLooper - disallowTestableLooperAsMainThread(); - NotificationEntry entry = createFgEntry(); - mFsc.onAppOpChanged( - AppOpsManager.OP_CAMERA, - entry.getSbn().getUid(), - entry.getSbn().getPackageName(), - true); - - // This test is run on the TestableLooper, which is not the MainLooper, so - // we expect an exception to be thrown - fail("onAppOpChanged shouldn't be allowed to be called from a bg thread."); - } catch (IllegalStateException e) { - // THEN expect an exception - } - } - - @Test - public void testAppOpsCRUD() { - // no crash on remove that doesn't exist - mFsc.onAppOpChanged(9, 1000, "pkg1", false); - assertNull(mFsc.getAppOps(0, "pkg1")); - - // multiuser & multipackage - mFsc.onAppOpChanged(8, 50, "pkg1", true); - mFsc.onAppOpChanged(1, 60, "pkg3", true); - mFsc.onAppOpChanged(7, 500000, "pkg2", true); - - assertEquals(1, mFsc.getAppOps(0, "pkg1").size()); - assertTrue(mFsc.getAppOps(0, "pkg1").contains(8)); - - assertEquals(1, mFsc.getAppOps(UserHandle.getUserId(500000), "pkg2").size()); - assertTrue(mFsc.getAppOps(UserHandle.getUserId(500000), "pkg2").contains(7)); - - assertEquals(1, mFsc.getAppOps(0, "pkg3").size()); - assertTrue(mFsc.getAppOps(0, "pkg3").contains(1)); - - // multiple ops for the same package - mFsc.onAppOpChanged(9, 50, "pkg1", true); - mFsc.onAppOpChanged(5, 50, "pkg1", true); - - assertEquals(3, mFsc.getAppOps(0, "pkg1").size()); - assertTrue(mFsc.getAppOps(0, "pkg1").contains(8)); - assertTrue(mFsc.getAppOps(0, "pkg1").contains(9)); - assertTrue(mFsc.getAppOps(0, "pkg1").contains(5)); - - assertEquals(1, mFsc.getAppOps(UserHandle.getUserId(500000), "pkg2").size()); - assertTrue(mFsc.getAppOps(UserHandle.getUserId(500000), "pkg2").contains(7)); - - // remove one of the multiples - mFsc.onAppOpChanged(9, 50, "pkg1", false); - assertEquals(2, mFsc.getAppOps(0, "pkg1").size()); - assertTrue(mFsc.getAppOps(0, "pkg1").contains(8)); - assertTrue(mFsc.getAppOps(0, "pkg1").contains(5)); - - // remove last op - mFsc.onAppOpChanged(1, 60, "pkg3", false); - assertNull(mFsc.getAppOps(0, "pkg3")); - } - - @Test - public void testDisclosurePredicate() { - StatusBarNotification sbn_user1_app1 = makeMockSBN(USERID_ONE, "com.example.app1", - 5000, "monkeys", Notification.FLAG_AUTO_CANCEL); - StatusBarNotification sbn_user1_disclosure = makeMockSBN(USERID_ONE, "android", - SystemMessageProto.SystemMessage.NOTE_FOREGROUND_SERVICES, - null, Notification.FLAG_NO_CLEAR); - - assertTrue(mFsc.isDisclosureNotification(sbn_user1_disclosure)); - assertFalse(mFsc.isDisclosureNotification(sbn_user1_app1)); - } - - @Test - public void testNeedsDisclosureAfterRemovingUnrelatedNotification() { - final String PKG1 = "com.example.app100"; - - StatusBarNotification sbn_user1_app1 = makeMockSBN(USERID_ONE, PKG1, - 5000, "monkeys", Notification.FLAG_AUTO_CANCEL); - StatusBarNotification sbn_user1_app1_fg = makeMockFgSBN(USERID_ONE, PKG1); - - // first add a normal notification - entryAdded(sbn_user1_app1, NotificationManager.IMPORTANCE_DEFAULT); - // nothing required yet - assertFalse(mFsc.isDisclosureNeededForUser(USERID_ONE)); - // now the app starts a fg service - entryAdded(makeMockDisclosure(USERID_ONE, new String[]{PKG1}), - NotificationManager.IMPORTANCE_DEFAULT); - assertTrue(mFsc.isDisclosureNeededForUser(USERID_ONE)); // should be required! - // add the fg notification - entryAdded(sbn_user1_app1_fg, NotificationManager.IMPORTANCE_DEFAULT); - assertFalse(mFsc.isDisclosureNeededForUser(USERID_ONE)); // app1 has got it covered - // remove the boring notification - entryRemoved(sbn_user1_app1); - assertFalse(mFsc.isDisclosureNeededForUser(USERID_ONE)); // app1 has STILL got it covered - entryRemoved(sbn_user1_app1_fg); - assertTrue(mFsc.isDisclosureNeededForUser(USERID_ONE)); // should be required! - } - - @Test - public void testSimpleAddRemove() { - final String PKG1 = "com.example.app1"; - final String PKG2 = "com.example.app2"; - - StatusBarNotification sbn_user1_app1 = makeMockSBN(USERID_ONE, PKG1, - 5000, "monkeys", Notification.FLAG_AUTO_CANCEL); - entryAdded(sbn_user1_app1, NotificationManager.IMPORTANCE_DEFAULT); - - // no services are "running" - entryAdded(makeMockDisclosure(USERID_ONE, null), - NotificationManager.IMPORTANCE_DEFAULT); - - assertFalse(mFsc.isDisclosureNeededForUser(USERID_ONE)); - assertFalse(mFsc.isDisclosureNeededForUser(USERID_TWO)); - - entryUpdated(makeMockDisclosure(USERID_ONE, new String[]{PKG1}), - NotificationManager.IMPORTANCE_DEFAULT); - assertTrue(mFsc.isDisclosureNeededForUser(USERID_ONE)); // should be required! - assertFalse(mFsc.isDisclosureNeededForUser(USERID_TWO)); - - // switch to different package - entryUpdated(makeMockDisclosure(USERID_ONE, new String[]{PKG2}), - NotificationManager.IMPORTANCE_DEFAULT); - assertTrue(mFsc.isDisclosureNeededForUser(USERID_ONE)); - assertFalse(mFsc.isDisclosureNeededForUser(USERID_TWO)); - - entryUpdated(makeMockDisclosure(USERID_TWO, new String[]{PKG1}), - NotificationManager.IMPORTANCE_DEFAULT); - assertTrue(mFsc.isDisclosureNeededForUser(USERID_ONE)); - assertTrue(mFsc.isDisclosureNeededForUser(USERID_TWO)); // finally user2 needs one too - - entryUpdated(makeMockDisclosure(USERID_ONE, new String[]{PKG2, PKG1}), - NotificationManager.IMPORTANCE_DEFAULT); - assertTrue(mFsc.isDisclosureNeededForUser(USERID_ONE)); - assertTrue(mFsc.isDisclosureNeededForUser(USERID_TWO)); - - entryRemoved(makeMockDisclosure(USERID_ONE, null /*unused*/)); - assertFalse(mFsc.isDisclosureNeededForUser(USERID_ONE)); - assertTrue(mFsc.isDisclosureNeededForUser(USERID_TWO)); - - entryRemoved(makeMockDisclosure(USERID_TWO, null /*unused*/)); - assertFalse(mFsc.isDisclosureNeededForUser(USERID_ONE)); - assertFalse(mFsc.isDisclosureNeededForUser(USERID_TWO)); - } - - @Test - public void testDisclosureBasic() { - final String PKG1 = "com.example.app0"; - - StatusBarNotification sbn_user1_app1 = makeMockSBN(USERID_ONE, PKG1, - 5000, "monkeys", Notification.FLAG_AUTO_CANCEL); - StatusBarNotification sbn_user1_app1_fg = makeMockFgSBN(USERID_ONE, PKG1); - - entryAdded(sbn_user1_app1, NotificationManager.IMPORTANCE_DEFAULT); // not fg - entryAdded(makeMockDisclosure(USERID_ONE, new String[]{PKG1}), - NotificationManager.IMPORTANCE_DEFAULT); - assertTrue(mFsc.isDisclosureNeededForUser(USERID_ONE)); // should be required! - entryAdded(sbn_user1_app1_fg, NotificationManager.IMPORTANCE_DEFAULT); - assertFalse(mFsc.isDisclosureNeededForUser(USERID_ONE)); // app1 has got it covered - assertFalse(mFsc.isDisclosureNeededForUser(USERID_TWO)); - - // let's take out the other notification and see what happens. - - entryRemoved(sbn_user1_app1); - assertFalse( - mFsc.isDisclosureNeededForUser(USERID_ONE)); // still covered by sbn_user1_app1_fg - assertFalse(mFsc.isDisclosureNeededForUser(USERID_TWO)); - - // let's attempt to downgrade the notification from FLAG_FOREGROUND and see what we get - StatusBarNotification sbn_user1_app1_fg_sneaky = makeMockFgSBN(USERID_ONE, PKG1); - sbn_user1_app1_fg_sneaky.getNotification().flags = 0; - entryUpdated(sbn_user1_app1_fg_sneaky, - NotificationManager.IMPORTANCE_DEFAULT); - assertTrue(mFsc.isDisclosureNeededForUser(USERID_ONE)); // should be required! - assertFalse(mFsc.isDisclosureNeededForUser(USERID_TWO)); - - // ok, ok, we'll put it back - sbn_user1_app1_fg_sneaky.getNotification().flags = Notification.FLAG_FOREGROUND_SERVICE; - entryUpdated(sbn_user1_app1_fg, NotificationManager.IMPORTANCE_DEFAULT); - assertFalse(mFsc.isDisclosureNeededForUser(USERID_ONE)); - assertFalse(mFsc.isDisclosureNeededForUser(USERID_TWO)); - - entryRemoved(sbn_user1_app1_fg_sneaky); - assertTrue(mFsc.isDisclosureNeededForUser(USERID_ONE)); // should be required! - assertFalse(mFsc.isDisclosureNeededForUser(USERID_TWO)); - - // now let's test an upgrade - entryAdded(sbn_user1_app1, NotificationManager.IMPORTANCE_DEFAULT); - assertTrue(mFsc.isDisclosureNeededForUser(USERID_ONE)); - assertFalse(mFsc.isDisclosureNeededForUser(USERID_TWO)); - sbn_user1_app1.getNotification().flags |= Notification.FLAG_FOREGROUND_SERVICE; - entryUpdated(sbn_user1_app1, - NotificationManager.IMPORTANCE_DEFAULT); // this is now a fg notification - - assertFalse(mFsc.isDisclosureNeededForUser(USERID_TWO)); - assertFalse(mFsc.isDisclosureNeededForUser(USERID_ONE)); - - // remove it, make sure we're out of compliance again - entryRemoved(sbn_user1_app1); // was fg, should return true - entryRemoved(sbn_user1_app1); - assertFalse(mFsc.isDisclosureNeededForUser(USERID_TWO)); - assertTrue(mFsc.isDisclosureNeededForUser(USERID_ONE)); - - // importance upgrade - entryAdded(sbn_user1_app1_fg, NotificationManager.IMPORTANCE_MIN); - assertTrue(mFsc.isDisclosureNeededForUser(USERID_ONE)); - assertFalse(mFsc.isDisclosureNeededForUser(USERID_TWO)); - sbn_user1_app1.getNotification().flags |= Notification.FLAG_FOREGROUND_SERVICE; - entryUpdated(sbn_user1_app1_fg, - NotificationManager.IMPORTANCE_DEFAULT); // this is now a fg notification - - // finally, let's turn off the service - entryAdded(makeMockDisclosure(USERID_ONE, null), - NotificationManager.IMPORTANCE_DEFAULT); - - assertFalse(mFsc.isDisclosureNeededForUser(USERID_ONE)); - assertFalse(mFsc.isDisclosureNeededForUser(USERID_TWO)); - } - - @Test - public void testNoNotifsNorAppOps_noSystemAlertWarningRequired() { - // no notifications nor app op signals that this package/userId requires system alert - // warning - assertFalse(mFsc.isSystemAlertWarningNeeded(USERID_ONE, "any")); - } - - @Test - public void testCustomLayouts_systemAlertWarningRequired() { - // GIVEN a notification with a custom layout - final String pkg = "com.example.app0"; - StatusBarNotification customLayoutNotif = makeMockSBN(USERID_ONE, pkg, 0, - false); - - // WHEN the custom layout entry is added - entryAdded(customLayoutNotif, NotificationManager.IMPORTANCE_MIN); - - // THEN a system alert warning is required since there aren't any notifications that can - // display the app ops - assertTrue(mFsc.isSystemAlertWarningNeeded(USERID_ONE, pkg)); - } - - @Test - public void testStandardLayoutExists_noSystemAlertWarningRequired() { - // GIVEN two notifications (one with a custom layout, the other with a standard layout) - final String pkg = "com.example.app0"; - StatusBarNotification customLayoutNotif = makeMockSBN(USERID_ONE, pkg, 0, - false); - StatusBarNotification standardLayoutNotif = makeMockSBN(USERID_ONE, pkg, 1, true); - - // WHEN the entries are added - entryAdded(customLayoutNotif, NotificationManager.IMPORTANCE_MIN); - entryAdded(standardLayoutNotif, NotificationManager.IMPORTANCE_MIN); - - // THEN no system alert warning is required, since there is at least one notification - // with a standard layout that can display the app ops on the notification - assertFalse(mFsc.isSystemAlertWarningNeeded(USERID_ONE, pkg)); - } - - @Test - public void testStandardLayoutRemoved_systemAlertWarningRequired() { - // GIVEN two notifications (one with a custom layout, the other with a standard layout) - final String pkg = "com.example.app0"; - StatusBarNotification customLayoutNotif = makeMockSBN(USERID_ONE, pkg, 0, - false); - StatusBarNotification standardLayoutNotif = makeMockSBN(USERID_ONE, pkg, 1, true); - - // WHEN the entries are added and then the standard layout notification is removed - entryAdded(customLayoutNotif, NotificationManager.IMPORTANCE_MIN); - entryAdded(standardLayoutNotif, NotificationManager.IMPORTANCE_MIN); - entryRemoved(standardLayoutNotif); - - // THEN a system alert warning is required since there aren't any notifications that can - // display the app ops - assertTrue(mFsc.isSystemAlertWarningNeeded(USERID_ONE, pkg)); - } - - @Test - public void testStandardLayoutUpdatedToCustomLayout_systemAlertWarningRequired() { - // GIVEN a standard layout notification and then an updated version with a customLayout - final String pkg = "com.example.app0"; - StatusBarNotification standardLayoutNotif = makeMockSBN(USERID_ONE, pkg, 1, true); - StatusBarNotification updatedToCustomLayoutNotif = makeMockSBN(USERID_ONE, pkg, 1, false); - - // WHEN the entries is added and then updated to a custom layout - entryAdded(standardLayoutNotif, NotificationManager.IMPORTANCE_MIN); - entryUpdated(updatedToCustomLayoutNotif, NotificationManager.IMPORTANCE_MIN); - - // THEN a system alert warning is required since there aren't any notifications that can - // display the app ops - assertTrue(mFsc.isSystemAlertWarningNeeded(USERID_ONE, pkg)); - } - - private StatusBarNotification makeMockSBN(int userId, String pkg, int id, String tag, - int flags) { - final Notification n = mock(Notification.class); - n.extras = new Bundle(); - n.flags = flags; - return makeMockSBN(userId, pkg, id, tag, n); - } - - private StatusBarNotification makeMockSBN(int userid, String pkg, int id, String tag, - Notification n) { - final StatusBarNotification sbn = mock(StatusBarNotification.class); - when(sbn.getNotification()).thenReturn(n); - when(sbn.getId()).thenReturn(id); - when(sbn.getPackageName()).thenReturn(pkg); - when(sbn.getTag()).thenReturn(tag); - when(sbn.getUserId()).thenReturn(userid); - when(sbn.getUser()).thenReturn(new UserHandle(userid)); - when(sbn.getKey()).thenReturn("MOCK:"+userid+"|"+pkg+"|"+id+"|"+tag); - return sbn; - } - - private StatusBarNotification makeMockSBN(int uid, String pkg, int id, - boolean usesStdLayout) { - StatusBarNotification sbn = makeMockSBN(uid, pkg, id, "foo", 0); - if (usesStdLayout) { - sbn.getNotification().contentView = null; - sbn.getNotification().headsUpContentView = null; - sbn.getNotification().bigContentView = null; - } else { - sbn.getNotification().contentView = mock(RemoteViews.class); - } - return sbn; - } - - private StatusBarNotification makeMockFgSBN(int uid, String pkg, int id, - boolean usesStdLayout) { - StatusBarNotification sbn = - makeMockSBN(uid, pkg, id, "foo", Notification.FLAG_FOREGROUND_SERVICE); - if (usesStdLayout) { - sbn.getNotification().contentView = null; - sbn.getNotification().headsUpContentView = null; - sbn.getNotification().bigContentView = null; - } else { - sbn.getNotification().contentView = mock(RemoteViews.class); - } - return sbn; - } - - private StatusBarNotification makeMockFgSBN(int uid, String pkg) { - return makeMockSBN(uid, pkg, 1000, "foo", Notification.FLAG_FOREGROUND_SERVICE); - } - - private StatusBarNotification makeMockDisclosure(int userid, String[] pkgs) { - final Notification n = mock(Notification.class); - n.flags = Notification.FLAG_ONGOING_EVENT; - final Bundle extras = new Bundle(); - if (pkgs != null) extras.putStringArray(Notification.EXTRA_FOREGROUND_APPS, pkgs); - n.extras = extras; - n.when = System.currentTimeMillis() - 10000; // ten seconds ago - final StatusBarNotification sbn = makeMockSBN(userid, "android", - SystemMessageProto.SystemMessage.NOTE_FOREGROUND_SERVICES, - null, n); - sbn.getNotification().extras = extras; - return sbn; - } - - private NotificationEntry addFgEntry() { - NotificationEntry entry = createFgEntry(); - mCollectionListener.onEntryAdded(entry); - return entry; - } - - private NotificationEntry createFgEntry() { - return new NotificationEntryBuilder() - .setSbn(makeMockFgSBN(0, TEST_PACKAGE_NAME, 1000, true)) - .setImportance(NotificationManager.IMPORTANCE_DEFAULT) - .build(); - } - - private void entryRemoved(StatusBarNotification notification) { - mCollectionListener.onEntryRemoved( - new NotificationEntryBuilder() - .setSbn(notification) - .build(), - REASON_APP_CANCEL); - } - - private void entryAdded(StatusBarNotification notification, int importance) { - NotificationEntry entry = new NotificationEntryBuilder() - .setSbn(notification) - .setImportance(importance) - .build(); - mCollectionListener.onEntryAdded(entry); - } - - private void entryUpdated(StatusBarNotification notification, int importance) { - NotificationEntry entry = new NotificationEntryBuilder() - .setSbn(notification) - .setImportance(importance) - .build(); - mCollectionListener.onEntryUpdated(entry); - } - - @UserIdInt private static final int USERID_ONE = 10; // UserManagerService.MIN_USER_ID; - @UserIdInt private static final int USERID_TWO = USERID_ONE + 1; - private static final String TEST_PACKAGE_NAME = "test"; -} diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ColorizedFgsCoordinatorTest.java similarity index 69% rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinatorTest.java rename to packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ColorizedFgsCoordinatorTest.java index bc32759a99387..f2207afeda106 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinatorTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ColorizedFgsCoordinatorTest.java @@ -24,97 +24,53 @@ import static android.app.NotificationManager.IMPORTANCE_MIN; import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertTrue; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - import android.app.Notification; import android.app.PendingIntent; import android.app.Person; import android.content.Intent; import android.graphics.Color; import android.os.UserHandle; -import android.service.notification.StatusBarNotification; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import androidx.test.filters.SmallTest; -import com.android.systemui.ForegroundServiceController; import com.android.systemui.SysuiTestCase; -import com.android.systemui.appops.AppOpsController; import com.android.systemui.statusbar.notification.collection.NotifPipeline; -import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder; -import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter; import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner; -import com.android.systemui.util.concurrency.FakeExecutor; -import com.android.systemui.util.time.FakeSystemClock; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; @SmallTest @RunWith(AndroidTestingRunner.class) @TestableLooper.RunWithLooper -public class AppOpsCoordinatorTest extends SysuiTestCase { - private static final String TEST_PKG = "test_pkg"; - private static final int NOTIF_USER_ID = 0; +public class ColorizedFgsCoordinatorTest extends SysuiTestCase { - @Mock private ForegroundServiceController mForegroundServiceController; - @Mock private AppOpsController mAppOpsController; + private static final int NOTIF_USER_ID = 0; @Mock private NotifPipeline mNotifPipeline; private NotificationEntryBuilder mEntryBuilder; - private AppOpsCoordinator mAppOpsCoordinator; - private NotifFilter mForegroundFilter; + private ColorizedFgsCoordinator mColorizedFgsCoordinator; private NotifSectioner mFgsSection; - private FakeSystemClock mClock = new FakeSystemClock(); - private FakeExecutor mExecutor = new FakeExecutor(mClock); - @Before public void setup() { MockitoAnnotations.initMocks(this); allowTestableLooperAsMainThread(); - mAppOpsCoordinator = - new AppOpsCoordinator( - mForegroundServiceController, - mAppOpsController, - mExecutor); + mColorizedFgsCoordinator = new ColorizedFgsCoordinator(); mEntryBuilder = new NotificationEntryBuilder() .setUser(new UserHandle(NOTIF_USER_ID)); - mAppOpsCoordinator.attach(mNotifPipeline); + mColorizedFgsCoordinator.attach(mNotifPipeline); - // capture filter - ArgumentCaptor filterCaptor = ArgumentCaptor.forClass(NotifFilter.class); - verify(mNotifPipeline, times(1)).addPreGroupFilter(filterCaptor.capture()); - mForegroundFilter = filterCaptor.getValue(); - - mFgsSection = mAppOpsCoordinator.getSectioner(); - } - - @Test - public void filterTest_disclosureUnnecessary() { - NotificationEntry entry = mEntryBuilder.build(); - StatusBarNotification sbn = entry.getSbn(); - - // GIVEN the notification is a disclosure notification - when(mForegroundServiceController.isDisclosureNotification(sbn)).thenReturn(true); - - // GIVEN the disclosure isn't needed for this user - when(mForegroundServiceController.isDisclosureNeededForUser(sbn.getUserId())) - .thenReturn(false); - - // THEN filter out the notification - assertTrue(mForegroundFilter.shouldFilterOut(entry, 0)); + mFgsSection = mColorizedFgsCoordinator.getSectioner(); } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java index 9c52788dc2ebe..34c4ac1f4b67b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java @@ -32,7 +32,6 @@ import android.testing.TestableLooper.RunWithLooper; import androidx.test.filters.SmallTest; import com.android.internal.logging.testing.FakeMetricsLogger; -import com.android.systemui.ForegroundServiceNotificationListener; import com.android.systemui.InitController; import com.android.systemui.SysuiTestCase; import com.android.systemui.plugins.ActivityStarter; @@ -94,7 +93,6 @@ public class StatusBarNotificationPresenterTest extends SysuiTestCase { mDependency.injectTestDependency(ShadeController.class, mShadeController); mDependency.injectMockDependency(NotificationRemoteInputManager.Callback.class); mDependency.injectMockDependency(NotificationShadeWindowController.class); - mDependency.injectMockDependency(ForegroundServiceNotificationListener.class); NotificationShadeWindowView notificationShadeWindowView = mock(NotificationShadeWindowView.class);