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