156f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey/* 256f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey * Copyright (C) 2017 The Android Open Source Project 356f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey * 456f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License"); 556f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey * you may not use this file except in compliance with the License. 656f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey * You may obtain a copy of the License at 756f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey * 856f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey * http://www.apache.org/licenses/LICENSE-2.0 956f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey * 1056f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey * Unless required by applicable law or agreed to in writing, software 1156f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS, 1256f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1356f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey * See the License for the specific language governing permissions and 1456f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey * limitations under the License. 1556f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey */ 1656f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey 1756f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkeypackage android.app; 1856f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey 19780861f2452b519c128289dac836e5a756100e1dJeff Sharkeyimport android.content.ContentProvider; 20780861f2452b519c128289dac836e5a756100e1dJeff Sharkeyimport android.content.ContentResolver; 2156f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkeyimport android.content.Context; 2272ec44830708f8bc6607be20f47ddc26291c2e44Jeff Sharkeyimport android.graphics.drawable.Icon; 2356f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkeyimport android.os.Bundle; 2456f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkeyimport android.os.Parcel; 2556f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkeyimport android.os.Parcelable; 2656f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey 2756f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkeyimport com.android.internal.util.Preconditions; 2856f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey 2956f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey/** 3056f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey * Specialization of {@link SecurityException} that contains additional 3156f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey * information about how to involve the end user to recover from the exception. 3256f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey * <p> 3356f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey * This exception is only appropriate where there is a concrete action the user 3456f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey * can take to recover and make forward progress, such as confirming or entering 35780861f2452b519c128289dac836e5a756100e1dJeff Sharkey * authentication credentials, or granting access. 36780861f2452b519c128289dac836e5a756100e1dJeff Sharkey * <p> 37780861f2452b519c128289dac836e5a756100e1dJeff Sharkey * If the receiving app is actively involved with the user, it should present 38780861f2452b519c128289dac836e5a756100e1dJeff Sharkey * the contained recovery details to help the user make forward progress. The 39780861f2452b519c128289dac836e5a756100e1dJeff Sharkey * {@link #showAsDialog(Activity)} and 40780861f2452b519c128289dac836e5a756100e1dJeff Sharkey * {@link #showAsNotification(Context, String)} methods are provided as a 41780861f2452b519c128289dac836e5a756100e1dJeff Sharkey * convenience, but receiving apps are encouraged to use 42780861f2452b519c128289dac836e5a756100e1dJeff Sharkey * {@link #getUserMessage()} and {@link #getUserAction()} to integrate in a more 43780861f2452b519c128289dac836e5a756100e1dJeff Sharkey * natural way if relevant. 4456f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey * <p class="note"> 4556f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey * Note: legacy code that receives this exception may treat it as a general 4656f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey * {@link SecurityException}, and thus there is no guarantee that the messages 4756f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey * contained will be shown to the end user. 48df6d37e50442cb453a7e0d9e383c45bba848db70Ben Lin * 49df6d37e50442cb453a7e0d9e383c45bba848db70Ben Lin * @hide 5056f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey */ 5156f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkeypublic final class RecoverableSecurityException extends SecurityException implements Parcelable { 5256f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey private static final String TAG = "RecoverableSecurityException"; 5356f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey 5456f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey private final CharSequence mUserMessage; 5572ec44830708f8bc6607be20f47ddc26291c2e44Jeff Sharkey private final RemoteAction mUserAction; 5656f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey 5756f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey /** {@hide} */ 5856f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey public RecoverableSecurityException(Parcel in) { 5972ec44830708f8bc6607be20f47ddc26291c2e44Jeff Sharkey this(new SecurityException(in.readString()), in.readCharSequence(), 6072ec44830708f8bc6607be20f47ddc26291c2e44Jeff Sharkey RemoteAction.CREATOR.createFromParcel(in)); 6156f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey } 6256f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey 6356f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey /** 6456f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey * Create an instance ready to be thrown. 6556f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey * 6656f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey * @param cause original cause with details designed for engineering 6756f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey * audiences. 6856f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey * @param userMessage short message describing the issue for end user 6956f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey * audiences, which may be shown in a notification or dialog. 7072ec44830708f8bc6607be20f47ddc26291c2e44Jeff Sharkey * This should be localized and less than 64 characters. For 7172ec44830708f8bc6607be20f47ddc26291c2e44Jeff Sharkey * example: <em>PIN required to access Document.pdf</em> 7272ec44830708f8bc6607be20f47ddc26291c2e44Jeff Sharkey * @param userAction primary action that will initiate the recovery. The 7372ec44830708f8bc6607be20f47ddc26291c2e44Jeff Sharkey * title should be localized and less than 24 characters. For 7472ec44830708f8bc6607be20f47ddc26291c2e44Jeff Sharkey * example: <em>Enter PIN</em>. This action must launch an 7572ec44830708f8bc6607be20f47ddc26291c2e44Jeff Sharkey * activity that is expected to set 7656f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey * {@link Activity#setResult(int)} before finishing to 7756f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey * communicate the final status of the recovery. For example, 7856f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey * apps that observe {@link Activity#RESULT_OK} may choose to 79dac516ef326e9849d1fef06b314053e4d2081284Ben Lin * immediately retry their operation. 8056f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey */ 8156f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey public RecoverableSecurityException(Throwable cause, CharSequence userMessage, 8272ec44830708f8bc6607be20f47ddc26291c2e44Jeff Sharkey RemoteAction userAction) { 8356f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey super(cause.getMessage()); 8456f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey mUserMessage = Preconditions.checkNotNull(userMessage); 8556f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey mUserAction = Preconditions.checkNotNull(userAction); 8656f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey } 8756f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey 8872ec44830708f8bc6607be20f47ddc26291c2e44Jeff Sharkey /** {@hide} */ 8972ec44830708f8bc6607be20f47ddc26291c2e44Jeff Sharkey @Deprecated 9072ec44830708f8bc6607be20f47ddc26291c2e44Jeff Sharkey public RecoverableSecurityException(Throwable cause, CharSequence userMessage, 9172ec44830708f8bc6607be20f47ddc26291c2e44Jeff Sharkey CharSequence userActionTitle, PendingIntent userAction) { 9272ec44830708f8bc6607be20f47ddc26291c2e44Jeff Sharkey this(cause, userMessage, 9372ec44830708f8bc6607be20f47ddc26291c2e44Jeff Sharkey new RemoteAction( 9472ec44830708f8bc6607be20f47ddc26291c2e44Jeff Sharkey Icon.createWithResource("android", 9572ec44830708f8bc6607be20f47ddc26291c2e44Jeff Sharkey com.android.internal.R.drawable.ic_restart), 9672ec44830708f8bc6607be20f47ddc26291c2e44Jeff Sharkey userActionTitle, userActionTitle, userAction)); 9772ec44830708f8bc6607be20f47ddc26291c2e44Jeff Sharkey } 9872ec44830708f8bc6607be20f47ddc26291c2e44Jeff Sharkey 9956f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey /** 10056f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey * Return short message describing the issue for end user audiences, which 10156f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey * may be shown in a notification or dialog. 10256f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey */ 10356f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey public CharSequence getUserMessage() { 10456f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey return mUserMessage; 10556f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey } 10656f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey 10756f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey /** 10856f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey * Return primary action that will initiate the recovery. 10956f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey */ 11072ec44830708f8bc6607be20f47ddc26291c2e44Jeff Sharkey public RemoteAction getUserAction() { 11156f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey return mUserAction; 11256f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey } 11356f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey 114780861f2452b519c128289dac836e5a756100e1dJeff Sharkey /** @removed */ 115780861f2452b519c128289dac836e5a756100e1dJeff Sharkey @Deprecated 116780861f2452b519c128289dac836e5a756100e1dJeff Sharkey public void showAsNotification(Context context) { 117780861f2452b519c128289dac836e5a756100e1dJeff Sharkey final NotificationManager nm = context.getSystemService(NotificationManager.class); 118780861f2452b519c128289dac836e5a756100e1dJeff Sharkey 119780861f2452b519c128289dac836e5a756100e1dJeff Sharkey // Create a channel per-sender, since we don't want one poorly behaved 120780861f2452b519c128289dac836e5a756100e1dJeff Sharkey // remote app to cause all of our notifications to be blocked 121780861f2452b519c128289dac836e5a756100e1dJeff Sharkey final String channelId = TAG + "_" + mUserAction.getActionIntent().getCreatorUid(); 122780861f2452b519c128289dac836e5a756100e1dJeff Sharkey nm.createNotificationChannel(new NotificationChannel(channelId, TAG, 123780861f2452b519c128289dac836e5a756100e1dJeff Sharkey NotificationManager.IMPORTANCE_DEFAULT)); 124780861f2452b519c128289dac836e5a756100e1dJeff Sharkey 125780861f2452b519c128289dac836e5a756100e1dJeff Sharkey showAsNotification(context, channelId); 126780861f2452b519c128289dac836e5a756100e1dJeff Sharkey } 127780861f2452b519c128289dac836e5a756100e1dJeff Sharkey 12856f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey /** 12956f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey * Convenience method that will show a very simple notification populated 13056f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey * with the details from this exception. 13156f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey * <p> 13256f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey * If you want more flexibility over retrying your original operation once 13356f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey * the user action has finished, consider presenting your own UI that uses 13456f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey * {@link Activity#startIntentSenderForResult} to launch the 13556f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey * {@link PendingIntent#getIntentSender()} from {@link #getUserAction()} 13656f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey * when requested. If the result of that activity is 13756f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey * {@link Activity#RESULT_OK}, you should consider retrying. 13856f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey * <p> 13956f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey * This method will only display the most recent exception from any single 14056f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey * remote UID; notifications from older exceptions will always be replaced. 141780861f2452b519c128289dac836e5a756100e1dJeff Sharkey * 142780861f2452b519c128289dac836e5a756100e1dJeff Sharkey * @param channelId the {@link NotificationChannel} to use, which must have 143780861f2452b519c128289dac836e5a756100e1dJeff Sharkey * been already created using 144780861f2452b519c128289dac836e5a756100e1dJeff Sharkey * {@link NotificationManager#createNotificationChannel}. 14556f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey */ 146780861f2452b519c128289dac836e5a756100e1dJeff Sharkey public void showAsNotification(Context context, String channelId) { 14772ec44830708f8bc6607be20f47ddc26291c2e44Jeff Sharkey final NotificationManager nm = context.getSystemService(NotificationManager.class); 148780861f2452b519c128289dac836e5a756100e1dJeff Sharkey final Notification.Builder builder = new Notification.Builder(context, channelId) 14956f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey .setSmallIcon(com.android.internal.R.drawable.ic_print_error) 15072ec44830708f8bc6607be20f47ddc26291c2e44Jeff Sharkey .setContentTitle(mUserAction.getTitle()) 15156f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey .setContentText(mUserMessage) 15272ec44830708f8bc6607be20f47ddc26291c2e44Jeff Sharkey .setContentIntent(mUserAction.getActionIntent()) 15356f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey .setCategory(Notification.CATEGORY_ERROR); 154780861f2452b519c128289dac836e5a756100e1dJeff Sharkey nm.notify(TAG, mUserAction.getActionIntent().getCreatorUid(), builder.build()); 15556f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey } 15656f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey 15756f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey /** 15856f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey * Convenience method that will show a very simple dialog populated with the 15956f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey * details from this exception. 16056f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey * <p> 16156f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey * If you want more flexibility over retrying your original operation once 16256f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey * the user action has finished, consider presenting your own UI that uses 16356f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey * {@link Activity#startIntentSenderForResult} to launch the 16456f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey * {@link PendingIntent#getIntentSender()} from {@link #getUserAction()} 16556f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey * when requested. If the result of that activity is 16656f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey * {@link Activity#RESULT_OK}, you should consider retrying. 16756f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey * <p> 16856f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey * This method will only display the most recent exception from any single 16956f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey * remote UID; dialogs from older exceptions will always be replaced. 17056f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey */ 17156f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey public void showAsDialog(Activity activity) { 17256f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey final LocalDialog dialog = new LocalDialog(); 17356f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey final Bundle args = new Bundle(); 17456f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey args.putParcelable(TAG, this); 17556f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey dialog.setArguments(args); 17656f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey 17772ec44830708f8bc6607be20f47ddc26291c2e44Jeff Sharkey final String tag = TAG + "_" + mUserAction.getActionIntent().getCreatorUid(); 17856f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey final FragmentManager fm = activity.getFragmentManager(); 17956f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey final FragmentTransaction ft = fm.beginTransaction(); 18056f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey final Fragment old = fm.findFragmentByTag(tag); 18156f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey if (old != null) { 18256f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey ft.remove(old); 18356f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey } 18456f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey ft.add(dialog, tag); 18556f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey ft.commitAllowingStateLoss(); 18656f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey } 18756f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey 188780861f2452b519c128289dac836e5a756100e1dJeff Sharkey /** 189780861f2452b519c128289dac836e5a756100e1dJeff Sharkey * Implementation detail for 190780861f2452b519c128289dac836e5a756100e1dJeff Sharkey * {@link RecoverableSecurityException#showAsDialog(Activity)}; needs to 191780861f2452b519c128289dac836e5a756100e1dJeff Sharkey * remain static to be recreated across orientation changes. 192780861f2452b519c128289dac836e5a756100e1dJeff Sharkey * 193780861f2452b519c128289dac836e5a756100e1dJeff Sharkey * @hide 194780861f2452b519c128289dac836e5a756100e1dJeff Sharkey */ 19556f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey public static class LocalDialog extends DialogFragment { 19656f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey @Override 19756f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey public Dialog onCreateDialog(Bundle savedInstanceState) { 19856f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey final RecoverableSecurityException e = getArguments().getParcelable(TAG); 19956f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey return new AlertDialog.Builder(getActivity()) 20056f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey .setMessage(e.mUserMessage) 20172ec44830708f8bc6607be20f47ddc26291c2e44Jeff Sharkey .setPositiveButton(e.mUserAction.getTitle(), (dialog, which) -> { 20256f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey try { 20372ec44830708f8bc6607be20f47ddc26291c2e44Jeff Sharkey e.mUserAction.getActionIntent().send(); 20456f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey } catch (PendingIntent.CanceledException ignored) { 20556f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey } 20656f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey }) 20756f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey .setNegativeButton(android.R.string.cancel, null) 20856f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey .create(); 20956f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey } 21056f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey } 21156f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey 21256f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey @Override 21356f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey public int describeContents() { 21456f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey return 0; 21556f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey } 21656f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey 21756f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey @Override 21856f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey public void writeToParcel(Parcel dest, int flags) { 21956f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey dest.writeString(getMessage()); 22056f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey dest.writeCharSequence(mUserMessage); 22156f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey mUserAction.writeToParcel(dest, flags); 22256f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey } 22356f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey 22456f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey public static final Creator<RecoverableSecurityException> CREATOR = 22556f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey new Creator<RecoverableSecurityException>() { 22656f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey @Override 22756f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey public RecoverableSecurityException createFromParcel(Parcel source) { 22856f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey return new RecoverableSecurityException(source); 22956f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey } 23056f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey 23156f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey @Override 23256f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey public RecoverableSecurityException[] newArray(int size) { 23356f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey return new RecoverableSecurityException[size]; 23456f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey } 23556f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey }; 23656f0368fb78c304789cdd5ab25f1e223a674f2c1Jeff Sharkey} 237