summaryrefslogtreecommitdiff
path: root/core/java/android/app/RecoverableSecurityException.java
diff options
context:
space:
mode:
authorJeff Sharkey <jsharkey@android.com>2017-02-12 03:21:25 -0700
committerJeff Sharkey <jsharkey@android.com>2017-02-12 03:21:39 -0700
commit72ec44830708f8bc6607be20f47ddc26291c2e44 (patch)
tree9f983921649e4c9a1efcd7033c44e8cdeae55d66 /core/java/android/app/RecoverableSecurityException.java
parentaab4e11c0ac5a73cd5ab7f6e6fb6b9de8c9ffd84 (diff)
Switch RecoverableSE over to using RemoteAction.
Now that RemoteAction supports PendingIntent, we should be using it instead of rolling our own fields. Continue offering legacy constructor for some existing unit tests. Create a notification channel for each remote app that throws at a client app. All apps targeting O must now use channels, which give the user better control over notifications. Mention in docs that strings should be localized. Test: builds Bug: 33749182, 35012253, 34676491 Change-Id: Ic57e32025bc6caf784d3746d9f97f6595b0edb69
Diffstat (limited to 'core/java/android/app/RecoverableSecurityException.java')
-rw-r--r--core/java/android/app/RecoverableSecurityException.java70
1 files changed, 39 insertions, 31 deletions
diff --git a/core/java/android/app/RecoverableSecurityException.java b/core/java/android/app/RecoverableSecurityException.java
index 1f015a607be8..540d1cda1edd 100644
--- a/core/java/android/app/RecoverableSecurityException.java
+++ b/core/java/android/app/RecoverableSecurityException.java
@@ -17,6 +17,8 @@
package android.app;
import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.drawable.Icon;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
@@ -40,13 +42,12 @@ public final class RecoverableSecurityException extends SecurityException implem
private static final String TAG = "RecoverableSecurityException";
private final CharSequence mUserMessage;
- private final CharSequence mUserActionTitle;
- private final PendingIntent mUserAction;
+ private final RemoteAction mUserAction;
/** {@hide} */
public RecoverableSecurityException(Parcel in) {
- this(new SecurityException(in.readString()), in.readCharSequence(), in.readCharSequence(),
- PendingIntent.CREATOR.createFromParcel(in));
+ this(new SecurityException(in.readString()), in.readCharSequence(),
+ RemoteAction.CREATOR.createFromParcel(in));
}
/**
@@ -56,26 +57,35 @@ public final class RecoverableSecurityException extends SecurityException implem
* audiences.
* @param userMessage short message describing the issue for end user
* audiences, which may be shown in a notification or dialog.
- * This should be less than 64 characters. For example: <em>PIN
- * required to access Document.pdf</em>
- * @param userActionTitle short title describing the primary action. This
- * should be less than 24 characters. For example: <em>Enter
- * PIN</em>
- * @param userAction primary action that will initiate the recovery. This
- * must launch an activity that is expected to set
+ * This should be localized and less than 64 characters. For
+ * example: <em>PIN required to access Document.pdf</em>
+ * @param userAction primary action that will initiate the recovery. The
+ * title should be localized and less than 24 characters. For
+ * example: <em>Enter PIN</em>. This action must launch an
+ * activity that is expected to set
* {@link Activity#setResult(int)} before finishing to
* communicate the final status of the recovery. For example,
* apps that observe {@link Activity#RESULT_OK} may choose to
* immediately retry their operation.
*/
public RecoverableSecurityException(Throwable cause, CharSequence userMessage,
- CharSequence userActionTitle, PendingIntent userAction) {
+ RemoteAction userAction) {
super(cause.getMessage());
mUserMessage = Preconditions.checkNotNull(userMessage);
- mUserActionTitle = Preconditions.checkNotNull(userActionTitle);
mUserAction = Preconditions.checkNotNull(userAction);
}
+ /** {@hide} */
+ @Deprecated
+ public RecoverableSecurityException(Throwable cause, CharSequence userMessage,
+ CharSequence userActionTitle, PendingIntent userAction) {
+ this(cause, userMessage,
+ new RemoteAction(
+ Icon.createWithResource("android",
+ com.android.internal.R.drawable.ic_restart),
+ userActionTitle, userActionTitle, userAction));
+ }
+
/**
* Return short message describing the issue for end user audiences, which
* may be shown in a notification or dialog.
@@ -85,16 +95,9 @@ public final class RecoverableSecurityException extends SecurityException implem
}
/**
- * Return short title describing the primary action.
- */
- public CharSequence getUserActionTitle() {
- return mUserActionTitle;
- }
-
- /**
* Return primary action that will initiate the recovery.
*/
- public PendingIntent getUserAction() {
+ public RemoteAction getUserAction() {
return mUserAction;
}
@@ -113,15 +116,21 @@ public final class RecoverableSecurityException extends SecurityException implem
* remote UID; notifications from older exceptions will always be replaced.
*/
public void showAsNotification(Context context) {
- final Notification.Builder builder = new Notification.Builder(context)
+ final NotificationManager nm = context.getSystemService(NotificationManager.class);
+
+ // Create a channel per-sender, since we don't want one poorly behaved
+ // remote app to cause all of our notifications to be blocked
+ final String tag = TAG + "_" + mUserAction.getActionIntent().getCreatorUid();
+ nm.createNotificationChannel(new NotificationChannel(tag, TAG,
+ NotificationManager.IMPORTANCE_DEFAULT));
+
+ final Notification.Builder builder = new Notification.Builder(context, tag)
.setSmallIcon(com.android.internal.R.drawable.ic_print_error)
- .setContentTitle(mUserActionTitle)
+ .setContentTitle(mUserAction.getTitle())
.setContentText(mUserMessage)
- .setContentIntent(mUserAction)
+ .setContentIntent(mUserAction.getActionIntent())
.setCategory(Notification.CATEGORY_ERROR);
-
- final NotificationManager nm = context.getSystemService(NotificationManager.class);
- nm.notify(TAG, mUserAction.getCreatorUid(), builder.build());
+ nm.notify(tag, 0, builder.build());
}
/**
@@ -144,7 +153,7 @@ public final class RecoverableSecurityException extends SecurityException implem
args.putParcelable(TAG, this);
dialog.setArguments(args);
- final String tag = TAG + "_" + mUserAction.getCreatorUid();
+ final String tag = TAG + "_" + mUserAction.getActionIntent().getCreatorUid();
final FragmentManager fm = activity.getFragmentManager();
final FragmentTransaction ft = fm.beginTransaction();
final Fragment old = fm.findFragmentByTag(tag);
@@ -162,9 +171,9 @@ public final class RecoverableSecurityException extends SecurityException implem
final RecoverableSecurityException e = getArguments().getParcelable(TAG);
return new AlertDialog.Builder(getActivity())
.setMessage(e.mUserMessage)
- .setPositiveButton(e.mUserActionTitle, (dialog, which) -> {
+ .setPositiveButton(e.mUserAction.getTitle(), (dialog, which) -> {
try {
- e.mUserAction.send();
+ e.mUserAction.getActionIntent().send();
} catch (PendingIntent.CanceledException ignored) {
}
})
@@ -182,7 +191,6 @@ public final class RecoverableSecurityException extends SecurityException implem
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(getMessage());
dest.writeCharSequence(mUserMessage);
- dest.writeCharSequence(mUserActionTitle);
mUserAction.writeToParcel(dest, flags);
}