Adjust testapis/permissions for CTS tests
Test: cts
Bug: 127341023
Change-Id: Ice19dc337a06a3f20edca583ecbe5ef3148fd96d
diff --git a/api/test-current.txt b/api/test-current.txt
index f76881d..7121a54 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -328,8 +328,14 @@
}
public class NotificationManager {
+ method public void allowAssistantCapability(String);
+ method public void disallowAssistantCapability(String);
+ method @NonNull public java.util.List<java.lang.String> getAllowedAssistantCapabilities();
+ method @Nullable public android.content.ComponentName getAllowedNotificationAssistant();
method public android.content.ComponentName getEffectsSuppressor();
+ method public boolean isNotificationAssistantAccessGranted(@NonNull android.content.ComponentName);
method public boolean matchesCallFilter(android.os.Bundle);
+ method public void setNotificationAssistantAccessGranted(@Nullable android.content.ComponentName, boolean);
}
public final class PictureInPictureParams implements android.os.Parcelable {
@@ -2454,10 +2460,49 @@
package android.service.notification {
+ public final class Adjustment implements android.os.Parcelable {
+ ctor public Adjustment(String, String, android.os.Bundle, CharSequence, int);
+ ctor public Adjustment(@NonNull String, @NonNull String, @NonNull android.os.Bundle, @NonNull CharSequence, @NonNull android.os.UserHandle);
+ method public int describeContents();
+ method @NonNull public CharSequence getExplanation();
+ method @NonNull public String getKey();
+ method @NonNull public String getPackage();
+ method @NonNull public android.os.Bundle getSignals();
+ method public int getUser();
+ method @NonNull public android.os.UserHandle getUserHandle();
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.service.notification.Adjustment> CREATOR;
+ field public static final String KEY_CONTEXTUAL_ACTIONS = "key_contextual_actions";
+ field public static final String KEY_IMPORTANCE = "key_importance";
+ field public static final String KEY_SNOOZE_CRITERIA = "key_snooze_criteria";
+ field public static final String KEY_TEXT_REPLIES = "key_text_replies";
+ field public static final String KEY_USER_SENTIMENT = "key_user_sentiment";
+ }
+
@Deprecated public abstract class ConditionProviderService extends android.app.Service {
method @Deprecated public boolean isBound();
}
+ public abstract class NotificationAssistantService extends android.service.notification.NotificationListenerService {
+ ctor public NotificationAssistantService();
+ method public final void adjustNotification(@NonNull android.service.notification.Adjustment);
+ 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);
+ method public void onNotificationExpansionChanged(@NonNull String, boolean, boolean);
+ method public abstract void onNotificationSnoozedUntilContext(@NonNull android.service.notification.StatusBarNotification, @NonNull String);
+ method public void onNotificationsSeen(@NonNull java.util.List<java.lang.String>);
+ method public void onSuggestedReplySent(@NonNull String, @NonNull CharSequence, int);
+ method public final void unsnoozeNotification(@NonNull String);
+ field public static final String SERVICE_INTERFACE = "android.service.notification.NotificationAssistantService";
+ field public static final int SOURCE_FROM_APP = 0; // 0x0
+ field public static final int SOURCE_FROM_ASSISTANT = 1; // 0x1
+ }
+
public abstract class NotificationListenerService extends android.app.Service {
method public void onNotificationRemoved(@NonNull android.service.notification.StatusBarNotification, @NonNull android.service.notification.NotificationListenerService.RankingMap, @NonNull android.service.notification.NotificationStats, int);
}
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index 0bec21f..d54aca8 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -1169,6 +1169,7 @@
* @hide
*/
@SystemApi
+ @TestApi
public boolean isNotificationAssistantAccessGranted(@NonNull ComponentName assistant) {
INotificationManager service = getService();
try {
@@ -1204,6 +1205,7 @@
* @hide
*/
@SystemApi
+ @TestApi
public @NonNull @Adjustment.Keys List<String> getAllowedAssistantCapabilities() {
INotificationManager service = getService();
try {
@@ -1213,6 +1215,32 @@
}
}
+ /**
+ * @hide
+ */
+ @TestApi
+ public void allowAssistantCapability(String capability) {
+ INotificationManager service = getService();
+ try {
+ service.allowAssistantCapability(capability);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * @hide
+ */
+ @TestApi
+ public void disallowAssistantCapability(String capability) {
+ INotificationManager service = getService();
+ try {
+ service.disallowAssistantCapability(capability);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
/** @hide */
public boolean isNotificationPolicyAccessGrantedForPackage(String pkg) {
INotificationManager service = getService();
@@ -1310,6 +1338,7 @@
* @hide
*/
@SystemApi
+ @TestApi
public void setNotificationAssistantAccessGranted(@Nullable ComponentName assistant,
boolean granted) {
INotificationManager service = getService();
@@ -1332,6 +1361,7 @@
/** @hide */
@SystemApi
+ @TestApi
public @Nullable ComponentName getAllowedNotificationAssistant() {
INotificationManager service = getService();
try {
diff --git a/core/java/android/service/notification/Adjustment.java b/core/java/android/service/notification/Adjustment.java
index 8ba9a83..e81ce7f 100644
--- a/core/java/android/service/notification/Adjustment.java
+++ b/core/java/android/service/notification/Adjustment.java
@@ -18,6 +18,7 @@
import android.annotation.NonNull;
import android.annotation.StringDef;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.app.Notification;
import android.os.Bundle;
import android.os.Parcel;
@@ -40,6 +41,7 @@
* @hide
*/
@SystemApi
+@TestApi
public final class Adjustment implements Parcelable {
private final String mPackage;
private final String mKey;
@@ -130,6 +132,7 @@
* @hide
*/
@SystemApi
+ @TestApi
public Adjustment(String pkg, String key, Bundle signals, CharSequence explanation, int user) {
mPackage = pkg;
mKey = key;
@@ -212,6 +215,7 @@
/** @hide */
@SystemApi
+ @TestApi
public int getUser() {
return mUser;
}
diff --git a/core/java/android/service/notification/INotificationListener.aidl b/core/java/android/service/notification/INotificationListener.aidl
index 22104b5..8bb5f97 100644
--- a/core/java/android/service/notification/INotificationListener.aidl
+++ b/core/java/android/service/notification/INotificationListener.aidl
@@ -53,4 +53,5 @@
void onNotificationDirectReply(String key);
void onSuggestedReplySent(String key, in CharSequence reply, int source);
void onActionClicked(String key, in Notification.Action action, int source);
+ void onCapabilitiesChanged();
}
diff --git a/core/java/android/service/notification/NotificationAssistantService.java b/core/java/android/service/notification/NotificationAssistantService.java
index b81725d..b4fd397 100644
--- a/core/java/android/service/notification/NotificationAssistantService.java
+++ b/core/java/android/service/notification/NotificationAssistantService.java
@@ -23,6 +23,7 @@
import android.annotation.Nullable;
import android.annotation.SdkConstant;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
@@ -65,6 +66,7 @@
* @hide
*/
@SystemApi
+@TestApi
public abstract class NotificationAssistantService extends NotificationListenerService {
private static final String TAG = "NotificationAssistants";
@@ -357,6 +359,11 @@
args.argi2 = source;
mHandler.obtainMessage(MyHandler.MSG_ON_ACTION_INVOKED, args).sendToTarget();
}
+
+ @Override
+ public void onCapabilitiesChanged() {
+ mHandler.obtainMessage(MyHandler.MSG_ON_CAPABILITIES_CHANGED).sendToTarget();
+ }
}
private final class MyHandler extends Handler {
@@ -367,6 +374,7 @@
public static final int MSG_ON_NOTIFICATION_DIRECT_REPLY_SENT = 5;
public static final int MSG_ON_SUGGESTED_REPLY_SENT = 6;
public static final int MSG_ON_ACTION_INVOKED = 7;
+ public static final int MSG_ON_CAPABILITIES_CHANGED = 8;
public MyHandler(Looper looper) {
super(looper, null, false);
@@ -448,6 +456,10 @@
onActionInvoked(key, action, source);
break;
}
+ case MSG_ON_CAPABILITIES_CHANGED: {
+ onCapabilitiesChanged();
+ break;
+ }
}
}
}
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index 333868a..016f4aa 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -1399,6 +1399,11 @@
}
@Override
+ public void onCapabilitiesChanged() {
+ // no-op in the listener
+ }
+
+ @Override
public void onNotificationChannelModification(String pkgName, UserHandle user,
NotificationChannel channel,
@ChannelOrGroupModificationTypes int modificationType) {
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index ed198e6..e4a93e7 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -309,6 +309,7 @@
<permission name="android.permission.CONTROL_KEYGUARD_SECURE_NOTIFICATIONS"/>
<permission name="android.permission.SET_WALLPAPER" />
<permission name="android.permission.SET_WALLPAPER_COMPONENT" />
+ <permission name="android.permission.REQUEST_NOTIFICATION_ASSISTANT_SERVICE" />
</privapp-permissions>
<privapp-permissions package="com.android.statementservice">
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 3a9a993..314b74a 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -154,6 +154,7 @@
<uses-permission android:name="android.permission.STATUS_BAR_SERVICE" />
<!-- Permission needed to rename bugreport notifications (so they're not shown as Shell) -->
<uses-permission android:name="android.permission.SUBSTITUTE_NOTIFICATION_APP_NAME" />
+ <uses-permission android:name="android.permission.REQUEST_NOTIFICATION_ASSISTANT_SERVICE" />
<!-- Permission needed to hold a wakelock in dumpstate.cpp (drop_root_user()) -->
<uses-permission android:name="android.permission.WAKE_LOCK" />
<!-- Permission needed to enable/disable overlays -->
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index f2e56b5..d8db1d5 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -2868,7 +2868,7 @@
@Override
public void allowAssistantCapability(String adjustmentType) {
- checkCallerIsSystemOrShell();
+ checkCallerIsSystemOrSystemUiOrShell();
mAssistants.allowAdjustmentType(adjustmentType);
handleSavePolicyFile();
@@ -2876,7 +2876,7 @@
@Override
public void disallowAssistantCapability(String adjustmentType) {
- checkCallerIsSystemOrShell();
+ checkCallerIsSystemOrSystemUiOrShell();
mAssistants.disallowAdjustmentType(adjustmentType);
handleSavePolicyFile();
@@ -3806,7 +3806,7 @@
@Override
public ComponentName getAllowedNotificationAssistantForUser(int userId) {
- checkCallerIsSystem();
+ checkCallerIsSystemOrSystemUiOrShell();
List<ComponentName> allowedComponents = mAssistants.getAllowedComponents(userId);
if (allowedComponents.size() > 1) {
throw new IllegalStateException(
@@ -3889,7 +3889,7 @@
@Override
public void setNotificationAssistantAccessGrantedForUser(ComponentName assistant,
int userId, boolean granted) {
- checkCallerIsSystemOrShell();
+ checkCallerIsSystemOrSystemUiOrShell();
mAssistants.setUserSet(userId, true);
final long identity = Binder.clearCallingIdentity();
try {
@@ -3924,10 +3924,6 @@
}
}
if (!foundEnqueued) {
- // adjustment arrived too late to apply to enqueued; apply to posted
- // However, since the notification is now posted and may have alerted,
- // ignore any importance related adjustments
- adjustment.getSignals().remove(Adjustment.KEY_IMPORTANCE);
applyAdjustmentFromAssistant(token, adjustment);
}
}
@@ -4118,7 +4114,7 @@
}
return;
}
- if (mAllowedManagedServicePackages.test(assistant.getPackageName(), userId,
+ if (!granted || mAllowedManagedServicePackages.test(assistant.getPackageName(), userId,
mAssistants.getRequiredPermission())) {
mConditionProviders.setPackageOrComponentEnabled(assistant.flattenToString(),
userId, false, granted);
@@ -6990,6 +6986,16 @@
throw new SecurityException("Disallowed call for uid " + Binder.getCallingUid());
}
+ private void checkCallerIsSystemOrSystemUiOrShell() {
+ if (Binder.getCallingUid() == Process.SHELL_UID) {
+ return;
+ }
+ if (isCallerSystemOrPhone()) {
+ return;
+ }
+ getContext().enforceCallingPermission(android.Manifest.permission.STATUS_BAR_SERVICE, null);
+ }
+
private void checkCallerIsSystemOrSameApp(String pkg) {
if (isCallerSystemOrPhone()) {
return;
@@ -7297,7 +7303,7 @@
@GuardedBy("mLock")
private ArrayMap<Integer, Boolean> mUserSetMap = new ArrayMap<>();
- private List<String> mAllowedAdjustments = new ArrayList<>();
+ private Set<String> mAllowedAdjustments = new ArraySet<>();
public NotificationAssistants(Context context, Object lock, UserProfiles up,
IPackageManager pm) {
@@ -7385,12 +7391,18 @@
synchronized (mLock) {
mAllowedAdjustments.add(type);
}
+ for (final ManagedServiceInfo info : NotificationAssistants.this.getServices()) {
+ mHandler.post(() -> notifyCapabilitiesChanged(info));
+ }
}
protected void disallowAdjustmentType(String type) {
synchronized (mLock) {
mAllowedAdjustments.remove(type);
}
+ for (final ManagedServiceInfo info : NotificationAssistants.this.getServices()) {
+ mHandler.post(() -> notifyCapabilitiesChanged(info));
+ }
}
protected List<String> getAllowedAssistantCapabilities() {
@@ -7450,6 +7462,15 @@
setUserSet(userId, userSet);
}
+ private void notifyCapabilitiesChanged(final ManagedServiceInfo info) {
+ final INotificationListener assistant = (INotificationListener) info.service;
+ try {
+ assistant.onCapabilitiesChanged();
+ } catch (RemoteException ex) {
+ Slog.e(TAG, "unable to notify assistant (capabilities): " + assistant, ex);
+ }
+ }
+
private void notifySeen(final ManagedServiceInfo info,
final ArrayList<String> keys) {
final INotificationListener assistant = (INotificationListener) info.service;
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 ca7a71e..62f73bf 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -2887,7 +2887,7 @@
}
@Test
- public void testApplyEnqueuedAdjustmentFromAssistant_importance_onTime() throws Exception {
+ public void testApplyEnqueuedAdjustmentFromAssistant_importance() throws Exception {
final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
mService.addEnqueuedNotification(r);
NotificationManagerService.WorkerHandler handler = mock(
@@ -2905,25 +2905,6 @@
}
@Test
- public void testApplyEnqueuedAdjustmentFromAssistant_importance_tooLate() throws Exception {
- final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
- mService.addNotification(r);
- NotificationManagerService.WorkerHandler handler = mock(
- NotificationManagerService.WorkerHandler.class);
- mService.setHandler(handler);
- when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
-
- Bundle signals = new Bundle();
- signals.putInt(KEY_IMPORTANCE, IMPORTANCE_LOW);
- Adjustment adjustment = new Adjustment(
- r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
- mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
-
- assertEquals(IMPORTANCE_DEFAULT, r.getImportance());
- assertFalse(r.hasAdjustment(KEY_IMPORTANCE));
- }
-
- @Test
public void testApplyEnqueuedAdjustmentFromAssistant_crossUser() throws Exception {
final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
mService.addEnqueuedNotification(r);