From 469144c3e87ccf9f25a6d46aee55e89260fa8976 Mon Sep 17 00:00:00 2001 From: Julia Reynolds Date: Fri, 21 Jun 2019 14:30:28 -0400 Subject: [PATCH] Record initial app given importance To allow users an easy way to 'go back to how it was' (also migrate some tests to other files) Test: atest, cts Bug: 135751328 (cherry picked from commit 03de363ce278b6d708a6d30f83468584a14a65d5) Change-Id: I949f366410d2cb2ab424b1b03222743e6e60d867 --- api/test-current.txt | 6 ++ .../java/android/app/NotificationChannel.java | 38 +++++++- .../notification/PreferencesHelper.java | 8 +- .../notification/NotificationChannelTest.java | 97 ------------------- .../NotificationManagerServiceTest.java | 36 +++++++ 5 files changed, 83 insertions(+), 102 deletions(-) delete mode 100644 services/tests/uiservicestests/src/com/android/server/notification/NotificationChannelTest.java diff --git a/api/test-current.txt b/api/test-current.txt index 0127dfe192538..bf2730abcb993 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -318,10 +318,16 @@ package android.app { } public final class NotificationChannel implements android.os.Parcelable { + method public int getOriginalImportance(); + method public boolean isBlockableSystem(); method public boolean isImportanceLockedByCriticalDeviceFunction(); method public boolean isImportanceLockedByOEM(); + method public void setBlockableSystem(boolean); + method public void setDeleted(boolean); + method public void setFgServiceShown(boolean); method public void setImportanceLockedByCriticalDeviceFunction(boolean); method public void setImportanceLockedByOEM(boolean); + method public void setOriginalImportance(int); } public final class NotificationChannelGroup implements android.os.Parcelable { diff --git a/core/java/android/app/NotificationChannel.java b/core/java/android/app/NotificationChannel.java index 69ec831b5d1d8..3effd11798fbf 100644 --- a/core/java/android/app/NotificationChannel.java +++ b/core/java/android/app/NotificationChannel.java @@ -15,8 +15,6 @@ */ package android.app; -import static android.app.NotificationManager.IMPORTANCE_HIGH; - import android.annotation.Nullable; import android.annotation.SystemApi; import android.annotation.TestApi; @@ -86,6 +84,7 @@ public final class NotificationChannel implements Parcelable { private static final String ATT_GROUP = "group"; private static final String ATT_BLOCKABLE_SYSTEM = "blockable_system"; private static final String ATT_ALLOW_BUBBLE = "can_bubble"; + private static final String ATT_ORIG_IMP = "orig_imp"; private static final String DELIMITER = ","; /** @@ -151,6 +150,7 @@ public final class NotificationChannel implements Parcelable { private String mName; private String mDesc; private int mImportance = DEFAULT_IMPORTANCE; + private int mOriginalImportance = DEFAULT_IMPORTANCE; private boolean mBypassDnd; private int mLockscreenVisibility = DEFAULT_VISIBILITY; private Uri mSound = Settings.System.DEFAULT_NOTIFICATION_URI; @@ -234,6 +234,7 @@ public final class NotificationChannel implements Parcelable { mBlockableSystem = in.readBoolean(); mAllowBubbles = in.readBoolean(); mImportanceLockedByOEM = in.readBoolean(); + mOriginalImportance = in.readInt(); } @Override @@ -288,6 +289,7 @@ public final class NotificationChannel implements Parcelable { dest.writeBoolean(mBlockableSystem); dest.writeBoolean(mAllowBubbles); dest.writeBoolean(mImportanceLockedByOEM); + dest.writeInt(mOriginalImportance); } /** @@ -307,6 +309,7 @@ public final class NotificationChannel implements Parcelable { /** * @hide */ + @TestApi public void setFgServiceShown(boolean shown) { mFgServiceShown = shown; } @@ -314,6 +317,7 @@ public final class NotificationChannel implements Parcelable { /** * @hide */ + @TestApi public void setDeleted(boolean deleted) { mDeleted = deleted; } @@ -322,6 +326,7 @@ public final class NotificationChannel implements Parcelable { * @hide */ @UnsupportedAppUsage + @TestApi public void setBlockableSystem(boolean blockableSystem) { mBlockableSystem = blockableSystem; } @@ -641,6 +646,7 @@ public final class NotificationChannel implements Parcelable { /** * @hide */ + @TestApi public boolean isBlockableSystem() { return mBlockableSystem; } @@ -677,6 +683,22 @@ public final class NotificationChannel implements Parcelable { return mImportanceLockedDefaultApp; } + /** + * @hide + */ + @TestApi + public int getOriginalImportance() { + return mOriginalImportance; + } + + /** + * @hide + */ + @TestApi + public void setOriginalImportance(int importance) { + mOriginalImportance = importance; + } + /** * Returns whether the user has chosen the importance of this channel, either to affirm the * initial selection from the app, or changed it to be higher or lower. @@ -729,6 +751,7 @@ public final class NotificationChannel implements Parcelable { setFgServiceShown(safeBool(parser, ATT_FG_SERVICE_SHOWN, false)); setBlockableSystem(safeBool(parser, ATT_BLOCKABLE_SYSTEM, false)); setAllowBubbles(safeBool(parser, ATT_ALLOW_BUBBLE, DEFAULT_ALLOW_BUBBLE)); + setOriginalImportance(safeInt(parser, ATT_ORIG_IMP, DEFAULT_IMPORTANCE)); } @Nullable @@ -850,6 +873,9 @@ public final class NotificationChannel implements Parcelable { if (canBubble() != DEFAULT_ALLOW_BUBBLE) { out.attribute(null, ATT_ALLOW_BUBBLE, Boolean.toString(canBubble())); } + if (getOriginalImportance() != DEFAULT_IMPORTANCE) { + out.attribute(null, ATT_ORIG_IMP, Integer.toString(getOriginalImportance())); + } // mImportanceLockedDefaultApp and mImportanceLockedByOEM have a different source of // truth and so aren't written to this xml file @@ -896,6 +922,7 @@ public final class NotificationChannel implements Parcelable { record.put(ATT_GROUP, getGroup()); record.put(ATT_BLOCKABLE_SYSTEM, isBlockableSystem()); record.put(ATT_ALLOW_BUBBLE, canBubble()); + // TODO: original importance return record; } @@ -1005,7 +1032,8 @@ public final class NotificationChannel implements Parcelable { && Objects.equals(getGroup(), that.getGroup()) && Objects.equals(getAudioAttributes(), that.getAudioAttributes()) && mImportanceLockedByOEM == that.mImportanceLockedByOEM - && mImportanceLockedDefaultApp == that.mImportanceLockedDefaultApp; + && mImportanceLockedDefaultApp == that.mImportanceLockedDefaultApp + && mOriginalImportance == that.mOriginalImportance; } @Override @@ -1015,7 +1043,7 @@ public final class NotificationChannel implements Parcelable { getUserLockedFields(), isFgServiceShown(), mVibrationEnabled, mShowBadge, isDeleted(), getGroup(), getAudioAttributes(), isBlockableSystem(), mAllowBubbles, - mImportanceLockedByOEM, mImportanceLockedDefaultApp); + mImportanceLockedByOEM, mImportanceLockedDefaultApp, mOriginalImportance); result = 31 * result + Arrays.hashCode(mVibration); return result; } @@ -1045,6 +1073,7 @@ public final class NotificationChannel implements Parcelable { + ", mAllowBubbles=" + mAllowBubbles + ", mImportanceLockedByOEM=" + mImportanceLockedByOEM + ", mImportanceLockedDefaultApp=" + mImportanceLockedDefaultApp + + ", mOriginalImp=" + mOriginalImportance + '}'; pw.println(prefix + output); } @@ -1073,6 +1102,7 @@ public final class NotificationChannel implements Parcelable { + ", mAllowBubbles=" + mAllowBubbles + ", mImportanceLockedByOEM=" + mImportanceLockedByOEM + ", mImportanceLockedDefaultApp=" + mImportanceLockedDefaultApp + + ", mOriginalImp=" + mOriginalImportance + '}'; } diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java index 7b45a1b1997c5..92ac1d48d7848 100644 --- a/services/core/java/com/android/server/notification/PreferencesHelper.java +++ b/services/core/java/com/android/server/notification/PreferencesHelper.java @@ -17,6 +17,7 @@ package com.android.server.notification; import static android.app.NotificationManager.IMPORTANCE_NONE; +import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED; import android.annotation.IntDef; import android.annotation.NonNull; @@ -686,6 +687,11 @@ public class PreferencesHelper implements RankingConfig { } } + if (existing.getOriginalImportance() == IMPORTANCE_UNSPECIFIED) { + existing.setOriginalImportance(channel.getImportance()); + needsPolicyFileChange = true; + } + updateConfig(); return needsPolicyFileChange; } @@ -719,7 +725,7 @@ public class PreferencesHelper implements RankingConfig { if (!r.showBadge) { channel.setShowBadge(false); } - + channel.setOriginalImportance(channel.getImportance()); r.channels.put(channel.getId(), channel); if (channel.canBypassDnd() != mAreChannelsBypassingDnd) { updateChannelsBypassingDnd(mContext.getUserId()); diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationChannelTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationChannelTest.java deleted file mode 100644 index 1408749fa4fe0..0000000000000 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationChannelTest.java +++ /dev/null @@ -1,97 +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.server.notification; - -import static android.app.NotificationManager.IMPORTANCE_DEFAULT; - -import static junit.framework.Assert.assertEquals; -import static junit.framework.Assert.assertNull; - -import android.app.NotificationChannel; -import android.net.Uri; -import android.os.Parcel; -import android.test.suitebuilder.annotation.SmallTest; -import android.util.Xml; - -import androidx.test.runner.AndroidJUnit4; - -import com.android.internal.util.FastXmlSerializer; -import com.android.server.UiServiceTestCase; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlSerializer; - -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; - -@SmallTest -@RunWith(AndroidJUnit4.class) -public class NotificationChannelTest extends UiServiceTestCase { - - @Test - public void testWriteToParcel() { - NotificationChannel channel = - new NotificationChannel("1", "one", IMPORTANCE_DEFAULT); - Parcel parcel = Parcel.obtain(); - channel.writeToParcel(parcel, 0); - parcel.setDataPosition(0); - NotificationChannel channel1 = NotificationChannel.CREATOR.createFromParcel(parcel); - assertEquals(channel, channel1); - } - - @Test - public void testSystemBlockable() { - NotificationChannel channel = new NotificationChannel("a", "ab", IMPORTANCE_DEFAULT); - assertEquals(false, channel.isBlockableSystem()); - channel.setBlockableSystem(true); - assertEquals(true, channel.isBlockableSystem()); - } - - @Test - public void testEmptyVibration_noException() throws Exception { - NotificationChannel channel = new NotificationChannel("a", "ab", IMPORTANCE_DEFAULT); - channel.setVibrationPattern(new long[0]); - - XmlSerializer serializer = new FastXmlSerializer(); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - serializer.setOutput(new BufferedOutputStream(baos), "utf-8"); - channel.writeXml(serializer); - } - - @Test - public void testBackupEmptySound() throws Exception { - NotificationChannel channel = new NotificationChannel("a", "ab", IMPORTANCE_DEFAULT); - channel.setSound(Uri.EMPTY, null); - - XmlSerializer serializer = new FastXmlSerializer(); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - serializer.setOutput(new BufferedOutputStream(baos), "utf-8"); - channel.writeXmlForBackup(serializer, getContext()); - - XmlPullParser parser = Xml.newPullParser(); - parser.setInput(new BufferedInputStream( - new ByteArrayInputStream(baos.toByteArray())), null); - NotificationChannel restored = new NotificationChannel("a", "ab", IMPORTANCE_DEFAULT); - restored.populateFromXmlForRestore(parser, getContext()); - - assertNull(restored.getSound()); - } -} diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java index 677705d877360..1a4a43485df95 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java @@ -131,6 +131,7 @@ import android.text.Html; import android.util.ArrayMap; import android.util.ArraySet; import android.util.AtomicFile; +import android.util.Xml; import androidx.annotation.Nullable; import androidx.test.InstrumentationRegistry; @@ -138,6 +139,7 @@ import androidx.test.InstrumentationRegistry; import com.android.internal.R; import com.android.internal.config.sysui.SystemUiDeviceConfigFlags; import com.android.internal.statusbar.NotificationVisibility; +import com.android.internal.util.FastXmlSerializer; import com.android.server.LocalServices; import com.android.server.SystemService; import com.android.server.UiServiceTestCase; @@ -156,9 +158,13 @@ import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.mockito.stubbing.Answer; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlSerializer; import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import java.util.ArrayList; @@ -3059,6 +3065,25 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { assertEquals(1, mService.countSystemChecks - systemChecks); } + @Test + public void testBackupEmptySound() throws Exception { + NotificationChannel channel = new NotificationChannel("a", "ab", IMPORTANCE_DEFAULT); + channel.setSound(Uri.EMPTY, null); + + XmlSerializer serializer = new FastXmlSerializer(); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + serializer.setOutput(new BufferedOutputStream(baos), "utf-8"); + channel.writeXmlForBackup(serializer, getContext()); + + XmlPullParser parser = Xml.newPullParser(); + parser.setInput(new BufferedInputStream( + new ByteArrayInputStream(baos.toByteArray())), null); + NotificationChannel restored = new NotificationChannel("a", "ab", IMPORTANCE_DEFAULT); + restored.populateFromXmlForRestore(parser, getContext()); + + assertNull(restored.getSound()); + } + @Test public void testBackup() throws Exception { int systemChecks = mService.countSystemChecks; @@ -3066,6 +3091,17 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { assertEquals(1, mService.countSystemChecks - systemChecks); } + @Test + public void testEmptyVibration_noException() throws Exception { + NotificationChannel channel = new NotificationChannel("a", "ab", IMPORTANCE_DEFAULT); + channel.setVibrationPattern(new long[0]); + + XmlSerializer serializer = new FastXmlSerializer(); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + serializer.setOutput(new BufferedOutputStream(baos), "utf-8"); + channel.writeXml(serializer); + } + @Test public void updateUriPermissions_update() throws Exception { NotificationChannel c = new NotificationChannel(