diff options
| author | 2018-12-17 16:19:52 -0500 | |
|---|---|---|
| committer | 2018-12-19 10:29:36 -0500 | |
| commit | 33ab8a0cdae2685b4ad3730d3bfa1e0be8ab3acf (patch) | |
| tree | 61d87c20bd386dac5df1fc6f78ebd5d24f974066 | |
| parent | 2ec8b910261ffceb80bf4c11dc7cf1d1fd63949e (diff) | |
Move app overlay permission to app level
Test: cts, atest
Bug: 111236845
Change-Id: I21c52cc7ce6d8e48354a7f258ee8b07d96dcef47
9 files changed, 109 insertions, 89 deletions
diff --git a/api/current.txt b/api/current.txt index de4e82416193..4fa007a3f1b0 100644 --- a/api/current.txt +++ b/api/current.txt @@ -5730,7 +5730,6 @@ package android.app { public final class NotificationChannelGroup implements android.os.Parcelable { ctor public NotificationChannelGroup(java.lang.String, java.lang.CharSequence); - method public boolean canOverlayApps(); method public android.app.NotificationChannelGroup clone(); method public int describeContents(); method public java.util.List<android.app.NotificationChannel> getChannels(); @@ -5738,7 +5737,6 @@ package android.app { method public java.lang.String getId(); method public java.lang.CharSequence getName(); method public boolean isBlocked(); - method public void setAllowAppOverlay(boolean); method public void setDescription(java.lang.String); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.app.NotificationChannelGroup> CREATOR; @@ -5746,6 +5744,7 @@ package android.app { public class NotificationManager { method public java.lang.String addAutomaticZenRule(android.app.AutomaticZenRule); + method public boolean areAppOverlaysAllowed(); method public boolean areNotificationsEnabled(); method public boolean canNotifyAsPackage(java.lang.String); method public void cancel(int); diff --git a/api/test-current.txt b/api/test-current.txt index 46e7683c3cb7..fda6004946bc 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -182,7 +182,6 @@ package android.app { method public int getUserLockedFields(); method public void lockFields(int); method public void setBlocked(boolean); - field public static final int USER_LOCKED_ALLOW_APP_OVERLAY = 2; // 0x2 } public class NotificationManager { diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl index 00567523e393..163be8efc8fd 100644 --- a/core/java/android/app/INotificationManager.aidl +++ b/core/java/android/app/INotificationManager.aidl @@ -65,6 +65,10 @@ interface INotificationManager boolean areNotificationsEnabled(String pkg); int getPackageImportance(String pkg); + void setAppOverlaysAllowed(String pkg, int uid, boolean allowed); + boolean areAppOverlaysAllowed(String pkg); + boolean areAppOverlaysAllowedForPackage(String pkg, int uid); + void createNotificationChannelGroups(String pkg, in ParceledListSlice channelGroupList); void createNotificationChannels(String pkg, in ParceledListSlice channelsList); void createNotificationChannelsForPackage(String pkg, int uid, in ParceledListSlice channelsList); diff --git a/core/java/android/app/NotificationChannelGroup.java b/core/java/android/app/NotificationChannelGroup.java index 2322a42c93d5..34cd9f029746 100644 --- a/core/java/android/app/NotificationChannelGroup.java +++ b/core/java/android/app/NotificationChannelGroup.java @@ -50,20 +50,12 @@ public final class NotificationChannelGroup implements Parcelable { private static final String ATT_DESC = "desc"; private static final String ATT_ID = "id"; private static final String ATT_BLOCKED = "blocked"; - private static final String ATT_ALLOW_APP_OVERLAY = "app_overlay"; private static final String ATT_USER_LOCKED = "locked"; - private static final boolean DEFAULT_ALLOW_APP_OVERLAY = true; - /** * @hide */ public static final int USER_LOCKED_BLOCKED_STATE = 0x00000001; - /** - * @hide - */ - @TestApi - public static final int USER_LOCKED_ALLOW_APP_OVERLAY = 0x00000002; /** * @see #getId() @@ -74,7 +66,6 @@ public final class NotificationChannelGroup implements Parcelable { private String mDescription; private boolean mBlocked; private List<NotificationChannel> mChannels = new ArrayList<>(); - private boolean mAllowAppOverlay = DEFAULT_ALLOW_APP_OVERLAY; // Bitwise representation of fields that have been changed by the user private int mUserLockedFields; @@ -110,7 +101,6 @@ public final class NotificationChannelGroup implements Parcelable { } in.readParcelableList(mChannels, NotificationChannel.class.getClassLoader()); mBlocked = in.readBoolean(); - mAllowAppOverlay = in.readBoolean(); mUserLockedFields = in.readInt(); } @@ -138,7 +128,6 @@ public final class NotificationChannelGroup implements Parcelable { } dest.writeParcelableList(mChannels, flags); dest.writeBoolean(mBlocked); - dest.writeBoolean(mAllowAppOverlay); dest.writeInt(mUserLockedFields); } @@ -181,15 +170,6 @@ public final class NotificationChannelGroup implements Parcelable { } /** - * Returns whether notifications posted to this channel group can display outside of the - * notification shade, in a floating window on top of other apps. These may additionally be - * blocked at the notification channel level, see {@link NotificationChannel#canOverlayApps()}. - */ - public boolean canOverlayApps() { - return mAllowAppOverlay; - } - - /** * Sets the user visible description of this group. * * <p>The recommended maximum length is 300 characters; the value may be truncated if it is too @@ -200,21 +180,6 @@ public final class NotificationChannelGroup implements Parcelable { } /** - * Sets whether notifications posted to this channel group can appear outside of the - * notification shade, floating over other apps' content. - * - * <p>This value will be ignored for notifications that are posted to channels that do not - * allow app overlays ({@link NotificationChannel#canOverlayApps()}. - * - * <p>Only modifiable before the channel is submitted to - * {@link NotificationManager#createNotificationChannelGroup(NotificationChannelGroup)}.</p> - * @see Notification#getAppOverlayIntent() - */ - public void setAllowAppOverlay(boolean allowAppOverlay) { - mAllowAppOverlay = allowAppOverlay; - } - - /** * @hide */ @TestApi @@ -266,7 +231,6 @@ public final class NotificationChannelGroup implements Parcelable { // Name, id, and importance are set in the constructor. setDescription(parser.getAttributeValue(null, ATT_DESC)); setBlocked(safeBool(parser, ATT_BLOCKED, false)); - setAllowAppOverlay(safeBool(parser, ATT_ALLOW_APP_OVERLAY, DEFAULT_ALLOW_APP_OVERLAY)); } private static boolean safeBool(XmlPullParser parser, String att, boolean defValue) { @@ -289,9 +253,6 @@ public final class NotificationChannelGroup implements Parcelable { out.attribute(null, ATT_DESC, getDescription().toString()); } out.attribute(null, ATT_BLOCKED, Boolean.toString(isBlocked())); - if (canOverlayApps() != DEFAULT_ALLOW_APP_OVERLAY) { - out.attribute(null, ATT_ALLOW_APP_OVERLAY, Boolean.toString(canOverlayApps())); - } out.attribute(null, ATT_USER_LOCKED, Integer.toString(mUserLockedFields)); out.endTag(null, TAG_GROUP); @@ -307,7 +268,6 @@ public final class NotificationChannelGroup implements Parcelable { record.put(ATT_NAME, getName()); record.put(ATT_DESC, getDescription()); record.put(ATT_BLOCKED, isBlocked()); - record.put(ATT_ALLOW_APP_OVERLAY, canOverlayApps()); record.put(ATT_USER_LOCKED, mUserLockedFields); return record; } @@ -336,7 +296,6 @@ public final class NotificationChannelGroup implements Parcelable { if (o == null || getClass() != o.getClass()) return false; NotificationChannelGroup that = (NotificationChannelGroup) o; return isBlocked() == that.isBlocked() && - mAllowAppOverlay == that.mAllowAppOverlay && mUserLockedFields == that.mUserLockedFields && Objects.equals(getId(), that.getId()) && Objects.equals(getName(), that.getName()) && @@ -347,7 +306,7 @@ public final class NotificationChannelGroup implements Parcelable { @Override public int hashCode() { return Objects.hash(getId(), getName(), getDescription(), isBlocked(), getChannels(), - mAllowAppOverlay, mUserLockedFields); + mUserLockedFields); } @Override @@ -356,7 +315,6 @@ public final class NotificationChannelGroup implements Parcelable { cloned.setDescription(getDescription()); cloned.setBlocked(isBlocked()); cloned.setChannels(getChannels()); - cloned.setAllowAppOverlay(canOverlayApps()); cloned.lockFields(mUserLockedFields); return cloned; } @@ -369,7 +327,6 @@ public final class NotificationChannelGroup implements Parcelable { + ", mDescription=" + (!TextUtils.isEmpty(mDescription) ? "hasDescription " : "") + ", mBlocked=" + mBlocked + ", mChannels=" + mChannels - + ", mAllowAppOverlay=" + mAllowAppOverlay + ", mUserLockedFields=" + mUserLockedFields + '}'; } @@ -385,7 +342,6 @@ public final class NotificationChannelGroup implements Parcelable { for (NotificationChannel channel : mChannels) { channel.writeToProto(proto, NotificationChannelGroupProto.CHANNELS); } - proto.write(NotificationChannelGroupProto.ALLOW_APP_OVERLAY, mAllowAppOverlay); proto.end(token); } } diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java index 306c366a86e4..9590782009eb 100644 --- a/core/java/android/app/NotificationManager.java +++ b/core/java/android/app/NotificationManager.java @@ -1074,6 +1074,25 @@ public class NotificationManager { } } + + /** + * Sets whether notifications posted by this app can appear outside of the + * notification shade, floating over other apps' content. + * + * <p>This value will be ignored for notifications that are posted to channels that do not + * allow app overlays ({@link NotificationChannel#canOverlayApps()}. + * + * @see Notification#getAppOverlayIntent() + */ + public boolean areAppOverlaysAllowed() { + INotificationManager service = getService(); + try { + return service.areAppOverlaysAllowed(mContext.getPackageName()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + /** * Checks the ability to modify notification do not disturb policy for the calling package. * diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 405edd216f0f..8e2186374e89 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -2279,6 +2279,26 @@ public class NotificationManagerService extends SystemService { } @Override + public boolean areAppOverlaysAllowed(String pkg) { + return areAppOverlaysAllowedForPackage(pkg, Binder.getCallingUid()); + } + + @Override + public boolean areAppOverlaysAllowedForPackage(String pkg, int uid) { + checkCallerIsSystemOrSameApp(pkg); + + return mPreferencesHelper.areAppOverlaysAllowed(pkg, uid); + } + + @Override + public void setAppOverlaysAllowed(String pkg, int uid, boolean allowed) { + checkCallerIsSystem(); + + mPreferencesHelper.setAppOverlaysAllowed(pkg, uid, allowed); + handleSavePolicyFile(); + } + + @Override public int getPackageImportance(String pkg) { checkCallerIsSystemOrSameApp(pkg); return mPreferencesHelper.getImportance(pkg, Binder.getCallingUid()); diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java index eb46d53b5157..7c0e0b0983fb 100644 --- a/services/core/java/com/android/server/notification/PreferencesHelper.java +++ b/services/core/java/com/android/server/notification/PreferencesHelper.java @@ -80,6 +80,7 @@ public class PreferencesHelper implements RankingConfig { private static final String ATT_NAME = "name"; private static final String ATT_UID = "uid"; private static final String ATT_ID = "id"; + private static final String ATT_APP_OVERLAY = "overlay"; private static final String ATT_PRIORITY = "priority"; private static final String ATT_VISIBILITY = "visibility"; private static final String ATT_IMPORTANCE = "importance"; @@ -92,6 +93,7 @@ public class PreferencesHelper implements RankingConfig { private static final int DEFAULT_VISIBILITY = NotificationManager.VISIBILITY_NO_OVERRIDE; private static final int DEFAULT_IMPORTANCE = NotificationManager.IMPORTANCE_UNSPECIFIED; private static final boolean DEFAULT_SHOW_BADGE = true; + private static final boolean DEFAULT_ALLOW_APP_OVERLAY = true; /** * Default value for what fields are user locked. See {@link LockableAppFields} for all lockable * fields. @@ -104,6 +106,7 @@ public class PreferencesHelper implements RankingConfig { @IntDef({LockableAppFields.USER_LOCKED_IMPORTANCE}) public @interface LockableAppFields { int USER_LOCKED_IMPORTANCE = 0x00000001; + int USER_LOCKED_APP_OVERLAY = 0x00000002; } // pkg|uid => PackagePreferences @@ -169,7 +172,9 @@ public class PreferencesHelper implements RankingConfig { XmlUtils.readIntAttribute( parser, ATT_VISIBILITY, DEFAULT_VISIBILITY), XmlUtils.readBooleanAttribute( - parser, ATT_SHOW_BADGE, DEFAULT_SHOW_BADGE)); + parser, ATT_SHOW_BADGE, DEFAULT_SHOW_BADGE), + XmlUtils.readBooleanAttribute( + parser, ATT_APP_OVERLAY, DEFAULT_ALLOW_APP_OVERLAY)); r.importance = XmlUtils.readIntAttribute( parser, ATT_IMPORTANCE, DEFAULT_IMPORTANCE); r.priority = XmlUtils.readIntAttribute( @@ -264,11 +269,12 @@ public class PreferencesHelper implements RankingConfig { private PackagePreferences getOrCreatePackagePreferences(String pkg, int uid) { return getOrCreatePackagePreferences(pkg, uid, - DEFAULT_IMPORTANCE, DEFAULT_PRIORITY, DEFAULT_VISIBILITY, DEFAULT_SHOW_BADGE); + DEFAULT_IMPORTANCE, DEFAULT_PRIORITY, DEFAULT_VISIBILITY, DEFAULT_SHOW_BADGE, + DEFAULT_ALLOW_APP_OVERLAY); } private PackagePreferences getOrCreatePackagePreferences(String pkg, int uid, int importance, - int priority, int visibility, boolean showBadge) { + int priority, int visibility, boolean showBadge, boolean allowAppOverlay) { final String key = packagePreferencesKey(pkg, uid); synchronized (mPackagePreferences) { PackagePreferences @@ -282,6 +288,7 @@ public class PreferencesHelper implements RankingConfig { r.priority = priority; r.visibility = visibility; r.showBadge = showBadge; + r.appOverlay = allowAppOverlay; try { createDefaultChannelIfNeeded(r); @@ -382,7 +389,8 @@ public class PreferencesHelper implements RankingConfig { || r.lockedAppFields != DEFAULT_LOCKED_APP_FIELDS || r.channels.size() > 0 || r.groups.size() > 0 - || r.delegate != null; + || r.delegate != null + || r.appOverlay != DEFAULT_ALLOW_APP_OVERLAY; if (hasNonDefaultSettings) { out.startTag(null, TAG_PACKAGE); out.attribute(null, ATT_NAME, r.pkg); @@ -395,6 +403,9 @@ public class PreferencesHelper implements RankingConfig { if (r.visibility != DEFAULT_VISIBILITY) { out.attribute(null, ATT_VISIBILITY, Integer.toString(r.visibility)); } + if (r.appOverlay != DEFAULT_ALLOW_APP_OVERLAY) { + out.attribute(null, ATT_APP_OVERLAY, Boolean.toString(r.appOverlay)); + } out.attribute(null, ATT_SHOW_BADGE, Boolean.toString(r.showBadge)); out.attribute(null, ATT_APP_USER_LOCKED_FIELDS, Integer.toString(r.lockedAppFields)); @@ -439,6 +450,20 @@ public class PreferencesHelper implements RankingConfig { out.endTag(null, TAG_RANKING); } + public void setAppOverlaysAllowed(String pkg, int uid, boolean allowed) { + PackagePreferences p = getOrCreatePackagePreferences(pkg, uid); + p.appOverlay = allowed; + p.lockedAppFields = p.lockedAppFields | LockableAppFields.USER_LOCKED_APP_OVERLAY; + } + + public boolean areAppOverlaysAllowed(String pkg, int uid) { + return getOrCreatePackagePreferences(pkg, uid).appOverlay; + } + + public int getAppLockedFields(String pkg, int uid) { + return getOrCreatePackagePreferences(pkg, uid).lockedAppFields; + } + /** * Gets importance. */ @@ -512,7 +537,6 @@ public class PreferencesHelper implements RankingConfig { // apps can't update the blocked status or app overlay permission if (fromTargetApp) { group.setBlocked(oldGroup.isBlocked()); - group.setAllowAppOverlay(oldGroup.canOverlayApps()); group.unlockFields(group.getUserLockedFields()); group.lockFields(oldGroup.getUserLockedFields()); } else { @@ -521,9 +545,6 @@ public class PreferencesHelper implements RankingConfig { group.lockFields(NotificationChannelGroup.USER_LOCKED_BLOCKED_STATE); updateChannelsBypassingDnd(mContext.getUserId()); } - if (group.canOverlayApps() != oldGroup.canOverlayApps()) { - group.lockFields(NotificationChannelGroup.USER_LOCKED_ALLOW_APP_OVERLAY); - } } } r.groups.put(group.getId(), group); @@ -1581,6 +1602,7 @@ public class PreferencesHelper implements RankingConfig { int priority = DEFAULT_PRIORITY; int visibility = DEFAULT_VISIBILITY; boolean showBadge = DEFAULT_SHOW_BADGE; + boolean appOverlay = DEFAULT_ALLOW_APP_OVERLAY; int lockedAppFields = DEFAULT_LOCKED_APP_FIELDS; Delegate delegate = null; 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 527a1eef7b0f..fdf6c03fa9fe 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java @@ -3507,6 +3507,12 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { } @Test + public void testAppOverlay() throws Exception { + mBinderService.setAppOverlaysAllowed(PKG, mUid, false); + assertFalse(mBinderService.areAppOverlaysAllowedForPackage(PKG, mUid)); + } + + @Test public void testIsCallerInstantApp_primaryUser() throws Exception { ApplicationInfo info = new ApplicationInfo(); info.privateFlags = ApplicationInfo.PRIVATE_FLAG_INSTANT; diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java index b0279357d372..0b7348194b26 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java @@ -1584,39 +1584,6 @@ public class PreferencesHelperTest extends UiServiceTestCase { } @Test - public void testUpdateGroup_fromSystem_appOverlay() { - NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1"); - mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg, true); - - // from system, allowed - NotificationChannelGroup update = ncg.clone(); - update.setAllowAppOverlay(false); - - mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, update, false); - NotificationChannelGroup updated = - mHelper.getNotificationChannelGroup("group1", PKG_N_MR1, UID_N_MR1); - assertFalse(updated.canOverlayApps()); - assertEquals(NotificationChannelGroup.USER_LOCKED_ALLOW_APP_OVERLAY, - updated.getUserLockedFields()); - } - - @Test - public void testUpdateGroup_fromApp_appOverlay() { - NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1"); - mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg, true); - - // from app, not allowed - NotificationChannelGroup update = new NotificationChannelGroup("group1", "name1"); - update.setAllowAppOverlay(false); - - mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg, true); - NotificationChannelGroup updated = - mHelper.getNotificationChannelGroup("group1", PKG_N_MR1, UID_N_MR1); - assertTrue(updated.canOverlayApps()); - assertEquals(0, updated.getUserLockedFields()); - } - - @Test public void testCannotCreateChannel_badGroup() { NotificationChannel channel1 = new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH); @@ -2192,4 +2159,32 @@ public class PreferencesHelperTest extends UiServiceTestCase { mHelper.toggleNotificationDelegate(PKG_O, UID_O, true); assertEquals("other", mHelper.getNotificationDelegate(PKG_O, UID_O)); } + + @Test + public void testAllowAppOverlay_defaults() throws Exception { + assertTrue(mHelper.areAppOverlaysAllowed(PKG_O, UID_O)); + + ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false); + mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper); + loadStreamXml(baos, false); + + assertTrue(mHelper.areAppOverlaysAllowed(PKG_O, UID_O)); + assertEquals(0, mHelper.getAppLockedFields(PKG_O, UID_O)); + } + + @Test + public void testAllowAppOverlay_xml() throws Exception { + mHelper.setAppOverlaysAllowed(PKG_O, UID_O, false); + assertFalse(mHelper.areAppOverlaysAllowed(PKG_O, UID_O)); + assertEquals(PreferencesHelper.LockableAppFields.USER_LOCKED_APP_OVERLAY, + mHelper.getAppLockedFields(PKG_O, UID_O)); + + ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false); + mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper); + loadStreamXml(baos, false); + + assertFalse(mHelper.areAppOverlaysAllowed(PKG_O, UID_O)); + assertEquals(PreferencesHelper.LockableAppFields.USER_LOCKED_APP_OVERLAY, + mHelper.getAppLockedFields(PKG_O, UID_O)); + } } |