diff options
| author | 2019-03-07 16:46:22 -0500 | |
|---|---|---|
| committer | 2019-03-20 09:09:56 -0400 | |
| commit | ad6dd3575c9fd2cbdf87b26dd2e5de25ebb86dec (patch) | |
| tree | e71e99484b8a7d2093ef9fde2b5c0b9be00e4e2c | |
| parent | 9846076a9b85042c7a71b98bd5d5aa02efbf39af (diff) | |
Add the ability to turn off NAS capabilities individually
Test: atest
Bug: 127825514
Change-Id: Ic59e4be40ec71c70703eacf004ef32333e3356c9
8 files changed, 163 insertions, 1 deletions
diff --git a/api/system-current.txt b/api/system-current.txt index db27647ad71c..3bbcb105c165 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -545,6 +545,7 @@ package android.app { } public class NotificationManager { + method @NonNull public java.util.List<java.lang.String> getAllowedAssistantCapabilities(); method @Nullable public android.content.ComponentName getAllowedNotificationAssistant(); method public boolean isNotificationAssistantAccessGranted(@NonNull android.content.ComponentName); method public void setNotificationAssistantAccessGranted(@Nullable android.content.ComponentName, boolean); @@ -6646,6 +6647,7 @@ package android.service.notification { method public final void adjustNotifications(@NonNull java.util.List<android.service.notification.Adjustment>); method public void onActionInvoked(@NonNull String, @NonNull android.app.Notification.Action, int); method @NonNull public final android.os.IBinder onBind(@Nullable android.content.Intent); + method public void onCapabilitiesChanged(); method public void onNotificationDirectReplied(@NonNull String); method @Nullable public abstract android.service.notification.Adjustment onNotificationEnqueued(@NonNull android.service.notification.StatusBarNotification); method @Nullable public android.service.notification.Adjustment onNotificationEnqueued(@NonNull android.service.notification.StatusBarNotification, @NonNull android.app.NotificationChannel); diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl index 15084de0d7dd..2058d56b25d5 100644 --- a/core/java/android/app/INotificationManager.aidl +++ b/core/java/android/app/INotificationManager.aidl @@ -70,6 +70,10 @@ interface INotificationManager boolean areNotificationsEnabled(String pkg); int getPackageImportance(String pkg); + List<String> getAllowedAssistantCapabilities(String pkg); + void allowAssistantCapability(String adjustmentType); + void disallowAssistantCapability(String adjustmentType); + boolean shouldHideSilentStatusIcons(String callingPkg); void setHideSilentStatusIcons(boolean hide); diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java index 6a301c91bb06..361cf83de0c7 100644 --- a/core/java/android/app/NotificationManager.java +++ b/core/java/android/app/NotificationManager.java @@ -42,6 +42,7 @@ import android.os.ServiceManager; import android.os.StrictMode; import android.os.UserHandle; import android.provider.Settings.Global; +import android.service.notification.Adjustment; import android.service.notification.Condition; import android.service.notification.StatusBarNotification; import android.service.notification.ZenModeConfig; @@ -1182,6 +1183,25 @@ public class NotificationManager { } } + /** + * Returns the list of {@link android.service.notification.Adjustment adjustment keys} that can + * be modified by the current {@link android.service.notification.NotificationAssistantService}. + * + * <p>Only callable by the current + * {@link android.service.notification.NotificationAssistantService}. + * See {@link #isNotificationAssistantAccessGranted(ComponentName)}</p> + * @hide + */ + @SystemApi + public @NonNull @Adjustment.Keys List<String> getAllowedAssistantCapabilities() { + INotificationManager service = getService(); + try { + return service.getAllowedAssistantCapabilities(mContext.getOpPackageName()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + /** @hide */ public boolean isNotificationPolicyAccessGrantedForPackage(String pkg) { INotificationManager service = getService(); diff --git a/core/java/android/service/notification/Adjustment.java b/core/java/android/service/notification/Adjustment.java index 1cdb62fe8934..8ba9a8357c65 100644 --- a/core/java/android/service/notification/Adjustment.java +++ b/core/java/android/service/notification/Adjustment.java @@ -16,6 +16,7 @@ package android.service.notification; import android.annotation.NonNull; +import android.annotation.StringDef; import android.annotation.SystemApi; import android.app.Notification; import android.os.Bundle; @@ -23,6 +24,9 @@ import android.os.Parcel; import android.os.Parcelable; import android.os.UserHandle; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + /** * Ranking updates from the Assistant. * @@ -43,6 +47,14 @@ public final class Adjustment implements Parcelable { private final Bundle mSignals; private final int mUser; + /** @hide */ + @StringDef (prefix = { "KEY_" }, value = { + KEY_CONTEXTUAL_ACTIONS, KEY_GROUP_KEY, KEY_IMPORTANCE, KEY_PEOPLE, KEY_SNOOZE_CRITERIA, + KEY_TEXT_REPLIES, KEY_USER_SENTIMENT + }) + @Retention(RetentionPolicy.SOURCE) + public @interface Keys {} + /** * Data type: ArrayList of {@code String}, where each is a representation of a * {@link android.provider.ContactsContract.Contacts#CONTENT_LOOKUP_URI}. diff --git a/core/java/android/service/notification/NotificationAssistantService.java b/core/java/android/service/notification/NotificationAssistantService.java index 780b576d71f3..a1932b8861b0 100644 --- a/core/java/android/service/notification/NotificationAssistantService.java +++ b/core/java/android/service/notification/NotificationAssistantService.java @@ -25,6 +25,7 @@ import android.annotation.SdkConstant; import android.annotation.SystemApi; import android.app.Notification; import android.app.NotificationChannel; +import android.app.NotificationManager; import android.app.admin.DevicePolicyManager; import android.content.ComponentName; import android.content.Context; @@ -141,7 +142,6 @@ public abstract class NotificationAssistantService extends NotificationListenerS return onNotificationEnqueued(sbn); } - /** * Implement this method to learn when notifications are removed, how they were interacted with * before removal, and why they were removed. @@ -216,6 +216,15 @@ public abstract class NotificationAssistantService extends NotificationListenerS } /** + * Implement this to know when a user has changed which features of + * their notifications the assistant can modify. + * <p> Query {@link NotificationManager#getAllowedAssistantCapabilities()} to see what + * {@link Adjustment adjustments} you are currently allowed to make.</p> + */ + public void onCapabilitiesChanged() { + } + + /** * Updates a notification. N.B. this won’t cause * an existing notification to alert, but might allow a future update to * this notification to alert. diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java index 0c0c23a47999..0488d3a822ad 100644 --- a/services/core/java/com/android/server/notification/ManagedServices.java +++ b/services/core/java/com/android/server/notification/ManagedServices.java @@ -347,6 +347,9 @@ abstract public class ManagedServices { } } } + + writeExtraXmlTags(out); + out.endTag(null, getConfig().xmlTag); } @@ -355,6 +358,16 @@ abstract public class ManagedServices { */ protected void writeExtraAttributes(XmlSerializer out, int userId) throws IOException {} + /** + * Writes extra xml tags within the parent tag specified in {@link Config#xmlTag}. + */ + protected void writeExtraXmlTags(XmlSerializer out) throws IOException {} + + /** + * This is called to process tags other than {@link #TAG_MANAGED_SERVICES}. + */ + protected void readExtraTag(String tag, XmlPullParser parser) throws IOException {} + protected void migrateToXml() { loadAllowedComponentsFromSettings(); } @@ -391,6 +404,8 @@ abstract public class ManagedServices { } mUseXml = true; } + } else { + readExtraTag(tag, parser); } } } diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 4a215cf7febb..ce6c7d998956 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -294,6 +294,12 @@ public class NotificationManagerService extends SystemService { static final boolean ENABLE_BLOCKED_TOASTS = true; + static final String[] DEFAULT_ALLOWED_ADJUSTMENTS = new String[] { + Adjustment.KEY_IMPORTANCE, + Adjustment.KEY_CONTEXTUAL_ACTIONS, + Adjustment.KEY_TEXT_REPLIES, + Adjustment.KEY_USER_SENTIMENT}; + // When #matchesCallFilter is called from the ringer, wait at most // 3s to resolve the contacts. This timeout is required since // ContactsProvider might take a long time to start up. @@ -2790,6 +2796,33 @@ public class NotificationManagerService extends SystemService { handleSavePolicyFile(); } + @Override + public List<String> getAllowedAssistantCapabilities(String pkg) { + checkCallerIsSystemOrSameApp(pkg); + + if (!isCallerSystemOrPhone() + && !mAssistants.isPackageAllowed(pkg, UserHandle.getCallingUserId())) { + throw new SecurityException("Not currently an assistant"); + } + + return mAssistants.getAllowedAssistantCapabilities(); + } + + @Override + public void allowAssistantCapability(String adjustmentType) { + checkCallerIsSystemOrShell(); + mAssistants.allowAdjustmentType(adjustmentType); + + handleSavePolicyFile(); + } + + @Override + public void disallowAssistantCapability(String adjustmentType) { + checkCallerIsSystemOrShell(); + mAssistants.disallowAdjustmentType(adjustmentType); + + handleSavePolicyFile(); + } /** * System-only API for getting a list of current (i.e. not cleared) notifications. @@ -7143,15 +7176,26 @@ public class NotificationManagerService extends SystemService { static final String TAG_ENABLED_NOTIFICATION_ASSISTANTS = "enabled_assistants"; private static final String ATT_USER_SET = "user_set"; + // TODO: STOPSHIP (b/127994217) switch to final value when onboarding flow is implemented + private static final String TAG_ALLOWED_ADJUSTMENT_TYPES = "allowed_adjustments_tmp"; + private static final String ATT_TYPES = "types"; private final Object mLock = new Object(); @GuardedBy("mLock") private ArrayMap<Integer, Boolean> mUserSetMap = new ArrayMap<>(); + private List<String> mAllowedAdjustments = new ArrayList<>(); public NotificationAssistants(Context context, Object lock, UserProfiles up, IPackageManager pm) { super(context, lock, up, pm); + + // TODO: STOPSHIP (b/127994217) remove when the onboarding flow is implemented + // Add all default allowed adjustment types. Will be overwritten by values in xml, + // if they exist + for (int i = 0; i < DEFAULT_ALLOWED_ADJUSTMENTS.length; i++) { + mAllowedAdjustments.add(DEFAULT_ALLOWED_ADJUSTMENTS[i]); + } } @Override @@ -7202,6 +7246,48 @@ public class NotificationManagerService extends SystemService { return android.Manifest.permission.REQUEST_NOTIFICATION_ASSISTANT_SERVICE; } + @Override + protected void writeExtraXmlTags(XmlSerializer out) throws IOException { + synchronized (mLock) { + out.startTag(null, TAG_ALLOWED_ADJUSTMENT_TYPES); + out.attribute(null, ATT_TYPES, TextUtils.join(",", mAllowedAdjustments)); + out.endTag(null, TAG_ALLOWED_ADJUSTMENT_TYPES); + } + } + + @Override + protected void readExtraTag(String tag, XmlPullParser parser) throws IOException { + if (TAG_ALLOWED_ADJUSTMENT_TYPES.equals(tag)) { + final String types = XmlUtils.readStringAttribute(parser, ATT_TYPES); + if (!TextUtils.isEmpty(types)) { + synchronized (mLock) { + mAllowedAdjustments.clear(); + mAllowedAdjustments.addAll(Arrays.asList(types.split(","))); + } + } + } + } + + protected void allowAdjustmentType(String type) { + synchronized (mLock) { + mAllowedAdjustments.add(type); + } + } + + protected void disallowAdjustmentType(String type) { + synchronized (mLock) { + mAllowedAdjustments.remove(type); + } + } + + protected List<String> getAllowedAssistantCapabilities() { + synchronized (mLock) { + List<String> types = new ArrayList<>(); + types.addAll(mAllowedAdjustments); + return types; + } + } + protected void onNotificationsSeenLocked(ArrayList<NotificationRecord> records) { // There should be only one, but it's a list, so while we enforce // singularity elsewhere, we keep it general here, to avoid surprises. 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 6f967593e6f1..bf0a498b5ceb 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java @@ -4264,4 +4264,18 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { componentName, false); } + + public void testGetAllowedAssistantCapabilities() throws Exception { + List<String> capabilities = mBinderService.getAllowedAssistantCapabilities(null); + assertNotNull(capabilities); + + for (int i = capabilities.size() - 1; i >= 0; i--) { + String capability = capabilities.get(i); + mBinderService.disallowAssistantCapability(capability); + assertEquals(i + 1, mBinderService.getAllowedAssistantCapabilities(null).size()); + List<String> currentCapabilities = mBinderService.getAllowedAssistantCapabilities(null); + assertNotNull(currentCapabilities); + assertFalse(currentCapabilities.contains(capability)); + } + } } |