Merge "Introduce RecoverableSecurityException."
This commit is contained in:
@@ -5583,6 +5583,18 @@ package android.app {
|
||||
field public static final int STYLE_SPINNER = 0; // 0x0
|
||||
}
|
||||
|
||||
public final class RecoverableSecurityException extends java.lang.SecurityException implements android.os.Parcelable {
|
||||
ctor public RecoverableSecurityException(java.lang.Throwable, java.lang.CharSequence, java.lang.CharSequence, android.app.PendingIntent);
|
||||
method public int describeContents();
|
||||
method public android.app.PendingIntent getUserAction();
|
||||
method public java.lang.CharSequence getUserActionTitle();
|
||||
method public java.lang.CharSequence getUserMessage();
|
||||
method public void showAsDialog(android.app.Activity);
|
||||
method public void showAsNotification(android.content.Context);
|
||||
method public void writeToParcel(android.os.Parcel, int);
|
||||
field public static final android.os.Parcelable.Creator<android.app.RecoverableSecurityException> CREATOR;
|
||||
}
|
||||
|
||||
public final class RemoteAction implements android.os.Parcelable {
|
||||
ctor public RemoteAction(android.graphics.drawable.Icon, java.lang.CharSequence, java.lang.CharSequence, android.app.RemoteAction.OnActionListener);
|
||||
method public android.app.RemoteAction clone();
|
||||
|
||||
@@ -5772,6 +5772,18 @@ package android.app {
|
||||
field public static final int STYLE_SPINNER = 0; // 0x0
|
||||
}
|
||||
|
||||
public final class RecoverableSecurityException extends java.lang.SecurityException implements android.os.Parcelable {
|
||||
ctor public RecoverableSecurityException(java.lang.Throwable, java.lang.CharSequence, java.lang.CharSequence, android.app.PendingIntent);
|
||||
method public int describeContents();
|
||||
method public android.app.PendingIntent getUserAction();
|
||||
method public java.lang.CharSequence getUserActionTitle();
|
||||
method public java.lang.CharSequence getUserMessage();
|
||||
method public void showAsDialog(android.app.Activity);
|
||||
method public void showAsNotification(android.content.Context);
|
||||
method public void writeToParcel(android.os.Parcel, int);
|
||||
field public static final android.os.Parcelable.Creator<android.app.RecoverableSecurityException> CREATOR;
|
||||
}
|
||||
|
||||
public final class RemoteAction implements android.os.Parcelable {
|
||||
ctor public RemoteAction(android.graphics.drawable.Icon, java.lang.CharSequence, java.lang.CharSequence, android.app.RemoteAction.OnActionListener);
|
||||
method public android.app.RemoteAction clone();
|
||||
|
||||
@@ -5594,6 +5594,18 @@ package android.app {
|
||||
field public static final int STYLE_SPINNER = 0; // 0x0
|
||||
}
|
||||
|
||||
public final class RecoverableSecurityException extends java.lang.SecurityException implements android.os.Parcelable {
|
||||
ctor public RecoverableSecurityException(java.lang.Throwable, java.lang.CharSequence, java.lang.CharSequence, android.app.PendingIntent);
|
||||
method public int describeContents();
|
||||
method public android.app.PendingIntent getUserAction();
|
||||
method public java.lang.CharSequence getUserActionTitle();
|
||||
method public java.lang.CharSequence getUserMessage();
|
||||
method public void showAsDialog(android.app.Activity);
|
||||
method public void showAsNotification(android.content.Context);
|
||||
method public void writeToParcel(android.os.Parcel, int);
|
||||
field public static final android.os.Parcelable.Creator<android.app.RecoverableSecurityException> CREATOR;
|
||||
}
|
||||
|
||||
public final class RemoteAction implements android.os.Parcelable {
|
||||
ctor public RemoteAction(android.graphics.drawable.Icon, java.lang.CharSequence, java.lang.CharSequence, android.app.RemoteAction.OnActionListener);
|
||||
method public android.app.RemoteAction clone();
|
||||
|
||||
201
core/java/android/app/RecoverableSecurityException.java
Normal file
201
core/java/android/app/RecoverableSecurityException.java
Normal file
@@ -0,0 +1,201 @@
|
||||
/*
|
||||
* 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 android.app;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import com.android.internal.util.Preconditions;
|
||||
|
||||
/**
|
||||
* Specialization of {@link SecurityException} that contains additional
|
||||
* information about how to involve the end user to recover from the exception.
|
||||
* <p>
|
||||
* This exception is only appropriate where there is a concrete action the user
|
||||
* can take to recover and make forward progress, such as confirming or entering
|
||||
* authentication credentials.
|
||||
* <p class="note">
|
||||
* Note: legacy code that receives this exception may treat it as a general
|
||||
* {@link SecurityException}, and thus there is no guarantee that the messages
|
||||
* contained will be shown to the end user.
|
||||
* </p>
|
||||
*/
|
||||
public final class RecoverableSecurityException extends SecurityException implements Parcelable {
|
||||
private static final String TAG = "RecoverableSecurityException";
|
||||
|
||||
private final CharSequence mUserMessage;
|
||||
private final CharSequence mUserActionTitle;
|
||||
private final PendingIntent mUserAction;
|
||||
|
||||
/** {@hide} */
|
||||
public RecoverableSecurityException(Parcel in) {
|
||||
this(new SecurityException(in.readString()), in.readCharSequence(), in.readCharSequence(),
|
||||
PendingIntent.CREATOR.createFromParcel(in));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance ready to be thrown.
|
||||
*
|
||||
* @param cause original cause with details designed for engineering
|
||||
* 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
|
||||
* {@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) {
|
||||
super(cause.getMessage());
|
||||
mUserMessage = Preconditions.checkNotNull(userMessage);
|
||||
mUserActionTitle = Preconditions.checkNotNull(userActionTitle);
|
||||
mUserAction = Preconditions.checkNotNull(userAction);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return short message describing the issue for end user audiences, which
|
||||
* may be shown in a notification or dialog.
|
||||
*/
|
||||
public CharSequence getUserMessage() {
|
||||
return mUserMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return short title describing the primary action.
|
||||
*/
|
||||
public CharSequence getUserActionTitle() {
|
||||
return mUserActionTitle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return primary action that will initiate the recovery.
|
||||
*/
|
||||
public PendingIntent getUserAction() {
|
||||
return mUserAction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method that will show a very simple notification populated
|
||||
* with the details from this exception.
|
||||
* <p>
|
||||
* If you want more flexibility over retrying your original operation once
|
||||
* the user action has finished, consider presenting your own UI that uses
|
||||
* {@link Activity#startIntentSenderForResult} to launch the
|
||||
* {@link PendingIntent#getIntentSender()} from {@link #getUserAction()}
|
||||
* when requested. If the result of that activity is
|
||||
* {@link Activity#RESULT_OK}, you should consider retrying.
|
||||
* <p>
|
||||
* This method will only display the most recent exception from any single
|
||||
* remote UID; notifications from older exceptions will always be replaced.
|
||||
*/
|
||||
public void showAsNotification(Context context) {
|
||||
final Notification.Builder builder = new Notification.Builder(context)
|
||||
.setSmallIcon(com.android.internal.R.drawable.ic_print_error)
|
||||
.setContentTitle(mUserActionTitle)
|
||||
.setContentText(mUserMessage)
|
||||
.setContentIntent(mUserAction)
|
||||
.setCategory(Notification.CATEGORY_ERROR);
|
||||
|
||||
final NotificationManager nm = context.getSystemService(NotificationManager.class);
|
||||
nm.notify(TAG, mUserAction.getCreatorUid(), builder.build());
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method that will show a very simple dialog populated with the
|
||||
* details from this exception.
|
||||
* <p>
|
||||
* If you want more flexibility over retrying your original operation once
|
||||
* the user action has finished, consider presenting your own UI that uses
|
||||
* {@link Activity#startIntentSenderForResult} to launch the
|
||||
* {@link PendingIntent#getIntentSender()} from {@link #getUserAction()}
|
||||
* when requested. If the result of that activity is
|
||||
* {@link Activity#RESULT_OK}, you should consider retrying.
|
||||
* <p>
|
||||
* This method will only display the most recent exception from any single
|
||||
* remote UID; dialogs from older exceptions will always be replaced.
|
||||
*/
|
||||
public void showAsDialog(Activity activity) {
|
||||
final LocalDialog dialog = new LocalDialog();
|
||||
final Bundle args = new Bundle();
|
||||
args.putParcelable(TAG, this);
|
||||
dialog.setArguments(args);
|
||||
|
||||
final String tag = TAG + "_" + mUserAction.getCreatorUid();
|
||||
final FragmentManager fm = activity.getFragmentManager();
|
||||
final FragmentTransaction ft = fm.beginTransaction();
|
||||
final Fragment old = fm.findFragmentByTag(tag);
|
||||
if (old != null) {
|
||||
ft.remove(old);
|
||||
}
|
||||
ft.add(dialog, tag);
|
||||
ft.commitAllowingStateLoss();
|
||||
}
|
||||
|
||||
/** {@hide} */
|
||||
public static class LocalDialog extends DialogFragment {
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
final RecoverableSecurityException e = getArguments().getParcelable(TAG);
|
||||
return new AlertDialog.Builder(getActivity())
|
||||
.setMessage(e.mUserMessage)
|
||||
.setPositiveButton(e.mUserActionTitle, (dialog, which) -> {
|
||||
try {
|
||||
e.mUserAction.send();
|
||||
} catch (PendingIntent.CanceledException ignored) {
|
||||
}
|
||||
})
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.create();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeString(getMessage());
|
||||
dest.writeCharSequence(mUserMessage);
|
||||
dest.writeCharSequence(mUserActionTitle);
|
||||
mUserAction.writeToParcel(dest, flags);
|
||||
}
|
||||
|
||||
public static final Creator<RecoverableSecurityException> CREATOR =
|
||||
new Creator<RecoverableSecurityException>() {
|
||||
@Override
|
||||
public RecoverableSecurityException createFromParcel(Parcel source) {
|
||||
return new RecoverableSecurityException(source);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RecoverableSecurityException[] newArray(int size) {
|
||||
return new RecoverableSecurityException[size];
|
||||
}
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user