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
This commit is contained in:
Julia Reynolds
2019-06-21 14:30:28 -04:00
parent 1077ae03f3
commit 469144c3e8
5 changed files with 83 additions and 102 deletions

View File

@@ -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 {

View File

@@ -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
+ '}';
}

View File

@@ -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());

View File

@@ -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());
}
}

View File

@@ -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(