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

Commit d9e836cf authored by Alexander Roederer's avatar Alexander Roederer Committed by Android (Google) Code Review
Browse files

Merge "Fixes LE Sysui update to use new instead of old" into main

parents c384c3ec 1aec45fe
Loading
Loading
Loading
Loading
+14 −2
Original line number Original line Diff line number Diff line
@@ -140,6 +140,7 @@ import static android.service.notification.NotificationListenerService.TRIM_FULL
import static android.service.notification.NotificationListenerService.TRIM_LIGHT;
import static android.service.notification.NotificationListenerService.TRIM_LIGHT;
import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
import static android.view.contentprotection.flags.Flags.rapidClearNotificationsByListenerAppOpEnabled;
import static android.view.contentprotection.flags.Flags.rapidClearNotificationsByListenerAppOpEnabled;
import static com.android.internal.util.FrameworkStatsLog.DND_MODE_RULE;
import static com.android.internal.util.FrameworkStatsLog.DND_MODE_RULE;
import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_CHANNEL_GROUP_PREFERENCES;
import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_CHANNEL_GROUP_PREFERENCES;
import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_CHANNEL_PREFERENCES;
import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_CHANNEL_PREFERENCES;
@@ -307,6 +308,7 @@ import android.view.Display;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityManager;
import android.widget.RemoteViews;
import android.widget.RemoteViews;
import android.widget.Toast;
import android.widget.Toast;
import com.android.internal.R;
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.annotations.VisibleForTesting;
@@ -358,7 +360,9 @@ import com.android.server.utils.quota.MultiRateLimiter;
import com.android.server.wm.ActivityTaskManagerInternal;
import com.android.server.wm.ActivityTaskManagerInternal;
import com.android.server.wm.BackgroundActivityStartCallback;
import com.android.server.wm.BackgroundActivityStartCallback;
import com.android.server.wm.WindowManagerInternal;
import com.android.server.wm.WindowManagerInternal;
import libcore.io.IoUtils;
import libcore.io.IoUtils;
import org.json.JSONException;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONObject;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserException;
@@ -11776,10 +11780,18 @@ public class NotificationManagerService extends SystemService {
                    }
                    }
                    if (lifetimeExtensionRefactor()) {
                    if (lifetimeExtensionRefactor()) {
                        if (sendRedacted && redactedSbn == null) {
                            redactedSbn = redactStatusBarNotification(sbn);
                            redactedCache = new TrimCache(redactedSbn);
                        }
                        final StatusBarNotification sbnToPost = sendRedacted
                                ? redactedCache.ForListener(info) : trimCache.ForListener(info);
                        // Checks if this is a request to notify system UI about a notification that
                        // Checks if this is a request to notify system UI about a notification that
                        // has been lifetime extended.
                        // has been lifetime extended.
                        // (We only need to check old for the flag, because in both cancellation and
                        // (We only need to check old for the flag, because in both cancellation and
                        // update cases, old should have the flag.)
                        // update cases, old should have the flag, whereas in update cases the
                        // new will NOT have the flag.)
                        // If it is such a request, and this is system UI, we send the post request
                        // If it is such a request, and this is system UI, we send the post request
                        // only to System UI, and break as we don't need to continue checking other
                        // only to System UI, and break as we don't need to continue checking other
                        // Managed Services.
                        // Managed Services.
@@ -11787,7 +11799,7 @@ public class NotificationManagerService extends SystemService {
                                && (old.getNotification().flags
                                && (old.getNotification().flags
                                & FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY) > 0) {
                                & FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY) > 0) {
                            final NotificationRankingUpdate update = makeRankingUpdateLocked(info);
                            final NotificationRankingUpdate update = makeRankingUpdateLocked(info);
                            listenerCalls.add(() -> notifyPosted(info, oldSbn, update));
                            listenerCalls.add(() -> notifyPosted(info, sbnToPost, update));
                            break;
                            break;
                        }
                        }
                    }
                    }
+69 −0
Original line number Original line Diff line number Diff line
@@ -70,6 +70,7 @@ import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserHandle;
import android.platform.test.flag.junit.SetFlagsRule;
import android.platform.test.flag.junit.SetFlagsRule;
import android.service.notification.INotificationListener;
import android.service.notification.INotificationListener;
import android.service.notification.IStatusBarNotificationHolder;
import android.service.notification.NotificationListenerFilter;
import android.service.notification.NotificationListenerFilter;
import android.service.notification.NotificationListenerService;
import android.service.notification.NotificationListenerService;
import android.service.notification.NotificationRankingUpdate;
import android.service.notification.NotificationRankingUpdate;
@@ -90,6 +91,7 @@ import com.google.common.collect.ImmutableList;
import org.junit.Before;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Rule;
import org.junit.Test;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.ArgumentMatcher;
import org.mockito.ArgumentMatcher;
import org.mockito.Mock;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.MockitoAnnotations;
@@ -154,6 +156,11 @@ public class NotificationListenersTest extends UiServiceTestCase {
                .thenReturn(new ArrayList<>());
                .thenReturn(new ArrayList<>());
        mNm.mHandler = mock(NotificationManagerService.WorkerHandler.class);
        mNm.mHandler = mock(NotificationManagerService.WorkerHandler.class);
        mNm.mAssistants = mock(NotificationManagerService.NotificationAssistants.class);
        mNm.mAssistants = mock(NotificationManagerService.NotificationAssistants.class);
        FieldSetter.setField(mNm,
                NotificationManagerService.class.getDeclaredField("mListeners"),
                mListeners);
        doReturn(android.service.notification.NotificationListenerService.TRIM_FULL)
                .when(mListeners).getOnNotificationPostedTrim(any());
    }
    }


    @Test
    @Test
@@ -827,6 +834,68 @@ public class NotificationListenersTest extends UiServiceTestCase {
        verify(mListeners, never()).redactStatusBarNotification(eq(sbn));
        verify(mListeners, never()).redactStatusBarNotification(eq(sbn));
    }
    }


    @Test
    public void testListenerPost_UpdateLifetimeExtended() throws Exception {
        mSetFlagsRule.enableFlags(android.app.Flags.FLAG_LIFETIME_EXTENSION_REFACTOR);

        // Create original notification, with FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY.
        String pkg = "pkg";
        int uid = 9;
        UserHandle userHandle = UserHandle.getUserHandleForUid(uid);
        NotificationChannel channel = new NotificationChannel("id", "name",
                NotificationManager.IMPORTANCE_HIGH);
        Notification.Builder nb = new Notification.Builder(mContext, channel.getId())
                .setContentTitle("foo")
                .setSmallIcon(android.R.drawable.sym_def_app_icon)
                .setFlag(Notification.FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY, true);
        StatusBarNotification sbn = new StatusBarNotification(pkg, pkg, 8, "tag", uid, 0,
                nb.build(), userHandle, null, 0);
        NotificationRecord old = new NotificationRecord(mContext, sbn, channel);

        // Creates updated notification (without FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY)
        Notification.Builder nb2 = new Notification.Builder(mContext, channel.getId())
                .setContentTitle("new title")
                .setSmallIcon(android.R.drawable.sym_def_app_icon)
                .setFlag(Notification.FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY, false);
        StatusBarNotification sbn2 = new StatusBarNotification(pkg, pkg, 8, "tag", uid, 0,
                nb2.build(), userHandle, null, 0);
        NotificationRecord toPost = new NotificationRecord(mContext, sbn2, channel);

        // Create system ui-like service.
        ManagedServices.ManagedServiceInfo info = mListeners.new ManagedServiceInfo(
                null, new ComponentName("a", "a"), sbn2.getUserId(), false, null, 33, 33);
        info.isSystemUi = true;
        INotificationListener l1 = mock(INotificationListener.class);
        info.service = l1;
        List<ManagedServices.ManagedServiceInfo> services = ImmutableList.of(info);
        when(mListeners.getServices()).thenReturn(services);

        FieldSetter.setField(mNm,
                NotificationManagerService.class.getDeclaredField("mHandler"),
                mock(NotificationManagerService.WorkerHandler.class));
        doReturn(true).when(mNm).isVisibleToListener(any(), anyInt(), any());
        doReturn(mock(NotificationRankingUpdate.class)).when(mNm).makeRankingUpdateLocked(info);
        doReturn(false).when(mNm).isInLockDownMode(anyInt());
        doNothing().when(mNm).updateUriPermissions(any(), any(), any(), anyInt());
        doReturn(sbn2).when(mListeners).redactStatusBarNotification(sbn2);
        doReturn(sbn2).when(mListeners).redactStatusBarNotification(any());

        // The notification change is posted to the service listener.
        mListeners.notifyPostedLocked(toPost, old);

        // Verify that the post occcurs with the updated notification value.
        ArgumentCaptor<Runnable> runnableCaptor = ArgumentCaptor.forClass(Runnable.class);
        verify(mNm.mHandler, times(1)).post(runnableCaptor.capture());
        runnableCaptor.getValue().run();
        ArgumentCaptor<IStatusBarNotificationHolder> sbnCaptor =
                ArgumentCaptor.forClass(IStatusBarNotificationHolder.class);
        verify(l1, times(1)).onNotificationPosted(sbnCaptor.capture(), any());
        StatusBarNotification sbnResult = sbnCaptor.getValue().get();
        assertThat(sbnResult.getNotification()
                .extras.getCharSequence(Notification.EXTRA_TITLE).toString())
                .isEqualTo("new title");
    }

    /**
    /**
     * Helper method to test the thread safety of some operations.
     * Helper method to test the thread safety of some operations.
     *
     *
+50 −3
Original line number Original line Diff line number Diff line
@@ -106,6 +106,7 @@ import static android.service.notification.NotificationListenerService.Ranking.U
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN;
import static com.android.server.am.PendingIntentRecord.FLAG_ACTIVITY_SENDER;
import static com.android.server.am.PendingIntentRecord.FLAG_ACTIVITY_SENDER;
import static com.android.server.am.PendingIntentRecord.FLAG_BROADCAST_SENDER;
import static com.android.server.am.PendingIntentRecord.FLAG_BROADCAST_SENDER;
@@ -118,11 +119,11 @@ import static com.android.server.notification.NotificationManagerService.TAG;
import static com.android.server.notification.NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_ADJUSTED;
import static com.android.server.notification.NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_ADJUSTED;
import static com.android.server.notification.NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_POSTED;
import static com.android.server.notification.NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_POSTED;
import static com.android.server.notification.NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_UPDATED;
import static com.android.server.notification.NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_UPDATED;
import static com.google.common.collect.Iterables.getOnlyElement;
import static com.google.common.collect.Iterables.getOnlyElement;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
import static com.google.common.truth.Truth.assertWithMessage;
import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertNotNull;
@@ -131,6 +132,7 @@ import static junit.framework.Assert.assertNull;
import static junit.framework.Assert.assertSame;
import static junit.framework.Assert.assertSame;
import static junit.framework.Assert.assertTrue;
import static junit.framework.Assert.assertTrue;
import static junit.framework.Assert.fail;
import static junit.framework.Assert.fail;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertThrows;
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.ArgumentMatchers.isNull;
@@ -157,6 +159,9 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.when;
import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList;
import android.Manifest;
import android.Manifest;
import android.annotation.Nullable;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.annotation.SuppressLint;
@@ -270,8 +275,10 @@ import android.util.Pair;
import android.util.Xml;
import android.util.Xml;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityManager;
import android.widget.RemoteViews;
import android.widget.RemoteViews;
import androidx.test.InstrumentationRegistry;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
import androidx.test.filters.SmallTest;
import com.android.internal.R;
import com.android.internal.R;
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
import com.android.internal.config.sysui.TestableFlagResolver;
import com.android.internal.config.sysui.TestableFlagResolver;
@@ -303,10 +310,12 @@ import com.android.server.uri.UriGrantsManagerInternal;
import com.android.server.utils.quota.MultiRateLimiter;
import com.android.server.utils.quota.MultiRateLimiter;
import com.android.server.wm.ActivityTaskManagerInternal;
import com.android.server.wm.ActivityTaskManagerInternal;
import com.android.server.wm.WindowManagerInternal;
import com.android.server.wm.WindowManagerInternal;
import com.google.android.collect.Lists;
import com.google.android.collect.Lists;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableList;
import libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges;
import libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges;
import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges;
import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges;
import org.junit.After;
import org.junit.After;
import org.junit.Assert;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Before;
@@ -5933,6 +5942,45 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
        assertThat(captor.getValue().shouldPostSilently()).isTrue();
        assertThat(captor.getValue().shouldPostSilently()).isTrue();
    }
    }
    @Test
    @EnableFlags(android.app.Flags.FLAG_LIFETIME_EXTENSION_REFACTOR)
    public void testUpdate_DirectReplyLifetimeExtendedUpdateSucceeds() throws Exception {
        // Creates a lifetime extended notification.
        NotificationRecord original = generateNotificationRecord(mTestNotificationChannel);
        original.getSbn().getNotification().flags |= FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY;
        mService.addNotification(original);
        // Post an update for that notification.
        StatusBarNotification sbn = new StatusBarNotification(mPkg, mPkg, original.getSbn().getId(),
                original.getSbn().getTag(), mUid, 0,
                new Notification.Builder(mContext, mTestNotificationChannel.getId())
                        .setSmallIcon(android.R.drawable.sym_def_app_icon)
                        .setContentTitle("new title").build(),
                UserHandle.getUserHandleForUid(mUid), null, 0);
        NotificationRecord update = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
        mService.addEnqueuedNotification(update);
        NotificationManagerService.PostNotificationRunnable runnable =
                mService.new PostNotificationRunnable(update.getKey(),
                        update.getSbn().getPackageName(),
                        update.getUid(),
                        mPostNotificationTrackerFactory.newTracker(null));
        runnable.run();
        waitForIdle();
        // Checks the update was sent, and that update contains the new title, and does not contain
        // the lifetime extension flag.
        ArgumentCaptor<NotificationRecord> captor =
                ArgumentCaptor.forClass(NotificationRecord.class);
        verify(mListeners, times(1)).prepareNotifyPostedLocked(captor.capture(), any(),
                anyBoolean());
        assertThat(captor.getValue().getNotification().flags
                & FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY).isEqualTo(0);
        assertThat(captor.getValue()
                .getNotification().extras.getCharSequence(Notification.EXTRA_TITLE).toString())
                .isEqualTo("new title");
    }
    @Test
    @Test
    public void testStats_updatedOnUserExpansion() throws Exception {
    public void testStats_updatedOnUserExpansion() throws Exception {
        NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
        NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
@@ -12602,7 +12650,6 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
        // the notifyPostedLocked function is called twice.
        // the notifyPostedLocked function is called twice.
        verify(mWorkerHandler, times(2)).postDelayed(any(Runnable.class), anyLong());
        verify(mWorkerHandler, times(2)).postDelayed(any(Runnable.class), anyLong());
        //verify(mListeners, times(2)).notifyPostedLocked(any(), any());
    }
    }
    @Test
    @Test