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

Commit 8a3b4597 authored by Julia Reynolds's avatar Julia Reynolds
Browse files

Strip extenders on android go devices.

Test: runtest notification-systemui
Bug: 35219985
Change-Id: I5a2d25c4ea33510c397b351d3604bd3f23f81521
parent 8aebf358
Loading
Loading
Loading
Loading
+12 −5
Original line number Diff line number Diff line
@@ -4937,7 +4937,6 @@ public class Notification implements Parcelable
            if (mStyle != null) {
                mStyle.buildStyled(mN);
            }

            if (mContext.getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.N
                    && (useExistingRemoteView())) {
                if (mN.contentView == null) {
@@ -4980,18 +4979,20 @@ public class Notification implements Parcelable

        /**
         * Removes RemoteViews that were created for compatibility from {@param n}, if they did not
         * change.
         * change. Also removes extenders on low ram devices, as
         * {@link android.service.notification.NotificationListenerService} services are disabled.
         *
         * @return {@param n}, if no stripping is needed, otherwise a stripped clone of {@param n}.
         *
         * @hide
         */
        public static Notification maybeCloneStrippedForDelivery(Notification n) {
        public static Notification maybeCloneStrippedForDelivery(Notification n, boolean isLowRam) {
            String templateClass = n.extras.getString(EXTRA_TEMPLATE);

            // Only strip views for known Styles because we won't know how to
            // re-create them otherwise.
            if (!TextUtils.isEmpty(templateClass)
            if (!isLowRam
                    && !TextUtils.isEmpty(templateClass)
                    && getNotificationStyleClass(templateClass) == null) {
                return n;
            }
@@ -5008,7 +5009,8 @@ public class Notification implements Parcelable
                            n.headsUpContentView.getSequenceNumber();

            // Nothing to do here, no need to clone.
            if (!stripContentView && !stripBigContentView && !stripHeadsUpContentView) {
            if (!isLowRam
                    && !stripContentView && !stripBigContentView && !stripHeadsUpContentView) {
                return n;
            }

@@ -5025,6 +5027,11 @@ public class Notification implements Parcelable
                clone.headsUpContentView = null;
                clone.extras.remove(EXTRA_REBUILD_HEADS_UP_CONTENT_VIEW_ACTION_COUNT);
            }
            if (isLowRam) {
                clone.extras.remove(Notification.TvExtender.EXTRA_TV_EXTENDER);
                clone.extras.remove(WearableExtender.EXTRA_WEARABLE_EXTENSIONS);
                clone.extras.remove(CarExtender.EXTRA_CAR_EXTENDER);
            }
            return clone;
        }

+3 −1
Original line number Diff line number Diff line
@@ -307,7 +307,9 @@ public class NotificationManager {
            }
        }
        if (localLOGV) Log.v(TAG, pkg + ": notify(" + id + ", " + notification + ")");
        final Notification copy = Builder.maybeCloneStrippedForDelivery(notification);
        ActivityManager am = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
        boolean isLowRam = am.isLowRamDevice();
        final Notification copy = Builder.maybeCloneStrippedForDelivery(notification, isLowRam);
        try {
            service.enqueueNotificationWithTag(pkg, mContext.getOpPackageName(), tag, id,
                    copy, user.getIdentifier());
+114 −0
Original line number 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.server.notification;

import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertNull;

import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;

import android.app.ActivityManager;
import android.app.Notification;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.graphics.Color;
import android.os.Build;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

@RunWith(AndroidJUnit4.class)
@SmallTest
public class NotificationTest extends NotificationTestCase {

    @Mock
    ActivityManager mAm;

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void testStripsExtendersInLowRamMode() {
        Notification.Builder nb = new Notification.Builder(mContext, "channel");
        nb.extend(new Notification.CarExtender().setColor(Color.RED));
        nb.extend(new Notification.TvExtender().setChannelId("different channel"));
        nb.extend(new Notification.WearableExtender().setDismissalId("dismiss"));
        Notification before = nb.build();

        Notification after = Notification.Builder.maybeCloneStrippedForDelivery(before, true);

        assertEquals("different channel", new Notification.TvExtender(before).getChannelId());
        assertNull(new Notification.TvExtender(after).getChannelId());

        assertEquals(Color.RED, new Notification.CarExtender(before).getColor());
        assertEquals(Notification.COLOR_DEFAULT, new Notification.CarExtender(after).getColor());

        assertEquals("dismiss", new Notification.WearableExtender(before).getDismissalId());
        assertNull(new Notification.WearableExtender(after).getDismissalId());
    }

    @Test
    public void testStripsRemoteViewsInLowRamMode() {
        Context context = spy(getContext());
        ApplicationInfo ai = new ApplicationInfo();
        ai.targetSdkVersion = Build.VERSION_CODES.M;
        when(context.getApplicationInfo()).thenReturn(ai);

        final Notification.BigTextStyle style = new Notification.BigTextStyle()
                .bigText("hello")
                .setSummaryText("And the summary");
        Notification before = new Notification.Builder(context, "channel")
                .setContentText("hi")
                .setStyle(style)
                .build();

        Notification after = Notification.Builder.maybeCloneStrippedForDelivery(before, true);
        assertNotNull(before.contentView);
        assertNotNull(before.bigContentView);
        assertNotNull(before.headsUpContentView);
        assertNull(after.contentView);
        assertNull(after.bigContentView);
        assertNull(after.headsUpContentView);
    }

    @Test
    public void testDoesNotStripsExtendersInNormalRamMode() {
        Notification.Builder nb = new Notification.Builder(mContext, "channel");
        nb.extend(new Notification.CarExtender().setColor(Color.RED));
        nb.extend(new Notification.TvExtender().setChannelId("different channel"));
        nb.extend(new Notification.WearableExtender().setDismissalId("dismiss"));
        Notification before = nb.build();
        Notification after = Notification.Builder.maybeCloneStrippedForDelivery(before, false);

        assertTrue(before == after);

        assertEquals("different channel", new Notification.TvExtender(before).getChannelId());
        assertEquals(Color.RED, new Notification.CarExtender(before).getColor());
        assertEquals("dismiss", new Notification.WearableExtender(before).getDismissalId());
    }
}