1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License
15  */
16 
17 // TODO (b/35202196): move this class out of the root of the package.
18 package com.android.settings.password;
19 
20 import static android.app.Activity.RESULT_FIRST_USER;
21 import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_PROFILE_LOCK_ATTEMPTS_FAILED;
22 
23 import static com.android.settings.Utils.SETTINGS_PACKAGE_NAME;
24 
25 import android.app.Dialog;
26 import android.app.KeyguardManager;
27 import android.app.RemoteLockscreenValidationSession;
28 import android.app.admin.DevicePolicyManager;
29 import android.app.admin.ManagedSubscriptionsPolicy;
30 import android.app.admin.flags.Flags;
31 import android.content.ComponentName;
32 import android.content.Context;
33 import android.content.DialogInterface;
34 import android.content.Intent;
35 import android.content.pm.UserInfo;
36 import android.hardware.biometrics.BiometricManager;
37 import android.os.Bundle;
38 import android.os.Handler;
39 import android.os.UserHandle;
40 import android.os.UserManager;
41 import android.service.remotelockscreenvalidation.RemoteLockscreenValidationClient;
42 import android.telecom.TelecomManager;
43 import android.text.TextUtils;
44 import android.util.FeatureFlagUtils;
45 import android.util.Log;
46 import android.view.View;
47 import android.widget.Button;
48 import android.widget.CheckBox;
49 import android.widget.TextView;
50 
51 import androidx.annotation.Nullable;
52 import androidx.appcompat.app.AlertDialog;
53 import androidx.fragment.app.DialogFragment;
54 import androidx.fragment.app.FragmentManager;
55 
56 import com.android.internal.widget.LockPatternUtils;
57 import com.android.internal.widget.LockscreenCredential;
58 import com.android.settings.R;
59 import com.android.settings.Utils;
60 import com.android.settings.core.InstrumentedFragment;
61 
62 import com.google.android.setupdesign.GlifLayout;
63 
64 /**
65  * Base fragment to be shared for PIN/Pattern/Password confirmation fragments.
66  */
67 public abstract class ConfirmDeviceCredentialBaseFragment extends InstrumentedFragment {
68     public static final String TAG = ConfirmDeviceCredentialBaseFragment.class.getSimpleName();
69     public static final String TITLE_TEXT = SETTINGS_PACKAGE_NAME + ".ConfirmCredentials.title";
70     public static final String HEADER_TEXT = SETTINGS_PACKAGE_NAME + ".ConfirmCredentials.header";
71     public static final String DETAILS_TEXT = SETTINGS_PACKAGE_NAME + ".ConfirmCredentials.details";
72     public static final String DARK_THEME = SETTINGS_PACKAGE_NAME + ".ConfirmCredentials.darkTheme";
73     public static final String SHOW_CANCEL_BUTTON =
74             SETTINGS_PACKAGE_NAME + ".ConfirmCredentials.showCancelButton";
75     public static final String SHOW_WHEN_LOCKED =
76             SETTINGS_PACKAGE_NAME + ".ConfirmCredentials.showWhenLocked";
77     public static final String USE_FADE_ANIMATION =
78             SETTINGS_PACKAGE_NAME + ".ConfirmCredentials.useFadeAnimation";
79     public static final String IS_REMOTE_LOCKSCREEN_VALIDATION =
80             SETTINGS_PACKAGE_NAME + ".ConfirmCredentials.isRemoteLockscreenValidation";
81 
82     protected static final int USER_TYPE_PRIMARY = 1;
83     protected static final int USER_TYPE_MANAGED_PROFILE = 2;
84     protected static final int USER_TYPE_SECONDARY = 3;
85 
86     /** Time we wait before clearing a wrong input attempt (e.g. pattern) and the error message. */
87     protected static final long CLEAR_WRONG_ATTEMPT_TIMEOUT_MS = 3000;
88 
89     protected static final String FRAGMENT_TAG_REMOTE_LOCKSCREEN_VALIDATION =
90             "remote_lockscreen_validation";
91 
92     protected boolean mReturnCredentials = false;
93     protected boolean mReturnGatekeeperPassword = false;
94     protected boolean mForceVerifyPath = false;
95     protected GlifLayout mGlifLayout;
96     protected CheckBox mCheckBox;
97     protected Button mCancelButton;
98     /** Button allowing managed profile password reset, null when is not shown. */
99     @Nullable protected Button mForgotButton;
100     protected int mEffectiveUserId;
101     protected int mUserId;
102     protected UserManager mUserManager;
103     protected LockPatternUtils mLockPatternUtils;
104     protected DevicePolicyManager mDevicePolicyManager;
105     protected TextView mErrorTextView;
106     protected final Handler mHandler = new Handler();
107     protected boolean mFrp;
108     protected boolean mRemoteValidation;
109     protected boolean mRequestWriteRepairModePassword;
110     protected boolean mRepairMode;
111     protected CharSequence mAlternateButtonText;
112     protected BiometricManager mBiometricManager;
113     @Nullable protected RemoteLockscreenValidationSession mRemoteLockscreenValidationSession;
114     /** Credential saved so the credential can be set for device if remote validation passes */
115     @Nullable protected RemoteLockscreenValidationClient mRemoteLockscreenValidationClient;
116     protected RemoteLockscreenValidationFragment mRemoteLockscreenValidationFragment;
117 
isInternalActivity()118     private boolean isInternalActivity() {
119         return (getActivity() instanceof ConfirmLockPassword.InternalActivity)
120                 || (getActivity() instanceof ConfirmLockPattern.InternalActivity);
121     }
122 
123     @Override
onCreate(@ullable Bundle savedInstanceState)124     public void onCreate(@Nullable Bundle savedInstanceState) {
125         super.onCreate(savedInstanceState);
126         final Intent intent = getActivity().getIntent();
127         mAlternateButtonText = intent.getCharSequenceExtra(
128                 KeyguardManager.EXTRA_ALTERNATE_BUTTON_LABEL);
129         mReturnCredentials = intent.getBooleanExtra(
130                 ChooseLockSettingsHelper.EXTRA_KEY_RETURN_CREDENTIALS, false);
131 
132         mReturnGatekeeperPassword = intent.getBooleanExtra(
133                 ChooseLockSettingsHelper.EXTRA_KEY_REQUEST_GK_PW_HANDLE, false);
134         mForceVerifyPath = intent.getBooleanExtra(
135                 ChooseLockSettingsHelper.EXTRA_KEY_FORCE_VERIFY, false);
136         mRequestWriteRepairModePassword = intent.getBooleanExtra(
137                 ChooseLockSettingsHelper.EXTRA_KEY_REQUEST_WRITE_REPAIR_MODE_PW, false);
138 
139         if (intent.getBooleanExtra(IS_REMOTE_LOCKSCREEN_VALIDATION, false)) {
140             if (FeatureFlagUtils.isEnabled(getContext(),
141                     FeatureFlagUtils.SETTINGS_REMOTE_DEVICE_CREDENTIAL_VALIDATION)) {
142                 mRemoteValidation = true;
143             } else {
144                 onRemoteLockscreenValidationFailure(
145                         "Remote lockscreen validation not enabled.");
146             }
147         }
148         if (mRemoteValidation) {
149             mRemoteLockscreenValidationSession = intent.getParcelableExtra(
150                     KeyguardManager.EXTRA_REMOTE_LOCKSCREEN_VALIDATION_SESSION,
151                     RemoteLockscreenValidationSession.class);
152             if (mRemoteLockscreenValidationSession == null
153                     || mRemoteLockscreenValidationSession.getRemainingAttempts() == 0) {
154                 onRemoteLockscreenValidationFailure("RemoteLockscreenValidationSession is null or "
155                         + "no more attempts for remote lockscreen validation.");
156             }
157 
158             ComponentName remoteLockscreenValidationServiceComponent =
159                     intent.getParcelableExtra(Intent.EXTRA_COMPONENT_NAME, ComponentName.class);
160             if (remoteLockscreenValidationServiceComponent == null) {
161                 onRemoteLockscreenValidationFailure(
162                         "RemoteLockscreenValidationService ComponentName is null");
163             }
164             mRemoteLockscreenValidationClient = RemoteLockscreenValidationClient
165                     .create(getContext(), remoteLockscreenValidationServiceComponent);
166             if (!mRemoteLockscreenValidationClient.isServiceAvailable()) {
167                 onRemoteLockscreenValidationFailure(String.format(
168                         "RemoteLockscreenValidationService at %s is not available",
169                         remoteLockscreenValidationServiceComponent.getClassName()));
170             }
171 
172             mRemoteLockscreenValidationFragment =
173                     (RemoteLockscreenValidationFragment) getFragmentManager()
174                             .findFragmentByTag(FRAGMENT_TAG_REMOTE_LOCKSCREEN_VALIDATION);
175             if (mRemoteLockscreenValidationFragment == null) {
176                 mRemoteLockscreenValidationFragment = new RemoteLockscreenValidationFragment();
177                 getFragmentManager().beginTransaction().add(mRemoteLockscreenValidationFragment,
178                         FRAGMENT_TAG_REMOTE_LOCKSCREEN_VALIDATION).commit();
179             }
180         }
181 
182         // Only take this argument into account if it belongs to the current profile.
183         mUserId = Utils.getUserIdFromBundle(getActivity(), intent.getExtras(),
184                 isInternalActivity());
185         mFrp = (mUserId == LockPatternUtils.USER_FRP);
186         mRepairMode = (mUserId == LockPatternUtils.USER_REPAIR_MODE);
187         mUserManager = UserManager.get(getActivity());
188         mEffectiveUserId = mUserManager.getCredentialOwnerProfile(mUserId);
189         mLockPatternUtils = new LockPatternUtils(getActivity());
190         mDevicePolicyManager = (DevicePolicyManager) getActivity().getSystemService(
191                 Context.DEVICE_POLICY_SERVICE);
192         mBiometricManager = getActivity().getSystemService(BiometricManager.class);
193     }
194 
195     @Override
onViewCreated(View view, @Nullable Bundle savedInstanceState)196     public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
197         super.onViewCreated(view, savedInstanceState);
198         mCancelButton = view.findViewById(R.id.cancelButton);
199         boolean showCancelButton = mRemoteValidation || getActivity().getIntent().getBooleanExtra(
200                 SHOW_CANCEL_BUTTON, false);
201         boolean hasAlternateButton = (mFrp || mRemoteValidation) && !TextUtils.isEmpty(
202                 mAlternateButtonText);
203         mCancelButton.setVisibility(showCancelButton || hasAlternateButton
204                 ? View.VISIBLE : View.GONE);
205         if (hasAlternateButton) {
206             mCancelButton.setText(mAlternateButtonText);
207         }
208         mCancelButton.setOnClickListener(v -> {
209             if (hasAlternateButton) {
210                 getActivity().setResult(KeyguardManager.RESULT_ALTERNATE);
211                 getActivity().finish();
212             } else if (mRemoteValidation) {
213                 onRemoteLockscreenValidationFailure("Forgot lockscreen credential button pressed.");
214             }
215         });
216         setupForgotButtonIfManagedProfile(view);
217 
218         mCheckBox = view.findViewById(R.id.checkbox);
219         if (mCheckBox != null && mRemoteValidation) {
220             mCheckBox.setVisibility(View.VISIBLE);
221         }
222         setupEmergencyCallButtonIfManagedSubscription(view);
223     }
224 
setupEmergencyCallButtonIfManagedSubscription(View view)225     private void setupEmergencyCallButtonIfManagedSubscription(View view) {
226         int policyType = getContext().getSystemService(
227                 DevicePolicyManager.class).getManagedSubscriptionsPolicy().getPolicyType();
228 
229         if (policyType == ManagedSubscriptionsPolicy.TYPE_ALL_MANAGED_SUBSCRIPTIONS) {
230             Button emergencyCallButton = view.findViewById(R.id.emergencyCallButton);
231             if (emergencyCallButton == null) {
232                 Log.wtf(TAG,
233                         "Emergency call button not found in managed profile credential dialog");
234                 return;
235             }
236             emergencyCallButton.setVisibility(View.VISIBLE);
237             emergencyCallButton.setOnClickListener(v -> {
238                 final Intent intent = getActivity()
239                         .getSystemService(TelecomManager.class)
240                         .createLaunchEmergencyDialerIntent(null)
241                         .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
242                                 | Intent.FLAG_ACTIVITY_CLEAR_TOP);
243                 getActivity().startActivity(intent);
244                 getActivity().finish();
245             });
246         }
247     }
248 
setupForgotButtonIfManagedProfile(View view)249     private void setupForgotButtonIfManagedProfile(View view) {
250         if (mUserManager.isManagedProfile(mUserId)
251                 && mUserManager.isQuietModeEnabled(UserHandle.of(mUserId))
252                 && mDevicePolicyManager.canProfileOwnerResetPasswordWhenLocked(mUserId)) {
253             mForgotButton = view.findViewById(R.id.forgotButton);
254             if (mForgotButton == null) {
255                 Log.wtf(TAG, "Forgot button not found in managed profile credential dialog");
256                 return;
257             }
258             mForgotButton.setVisibility(View.VISIBLE);
259             mForgotButton.setOnClickListener(v -> {
260                 final Intent intent = new Intent();
261                 intent.setClassName(SETTINGS_PACKAGE_NAME, ForgotPasswordActivity.class.getName());
262                 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
263                 intent.putExtra(Intent.EXTRA_USER_ID, mUserId);
264                 getActivity().startActivity(intent);
265                 getActivity().finish();
266             });
267         }
268     }
269 
270     // User could be locked while Effective user is unlocked even though the effective owns the
271     // credential. Otherwise, fingerprint can't unlock fbe/keystore through
272     // verifyTiedProfileChallenge. In such case, we also wanna show the user message that
273     // fingerprint is disabled due to device restart.
isStrongAuthRequired()274     protected boolean isStrongAuthRequired() {
275         return mFrp || mRepairMode
276                 || !mLockPatternUtils.isBiometricAllowedForUser(mEffectiveUserId)
277                 || !mUserManager.isUserUnlocked(mUserId);
278     }
279 
280     @Override
onResume()281     public void onResume() {
282         super.onResume();
283         refreshLockScreen();
284     }
285 
refreshLockScreen()286     protected void refreshLockScreen() {
287         updateErrorMessage(mLockPatternUtils.getCurrentFailedPasswordAttempts(mEffectiveUserId));
288     }
289 
setAccessibilityTitle(CharSequence supplementalText)290     protected void setAccessibilityTitle(CharSequence supplementalText) {
291         Intent intent = getActivity().getIntent();
292         if (intent != null) {
293             CharSequence titleText = intent.getCharSequenceExtra(
294                     ConfirmDeviceCredentialBaseFragment.TITLE_TEXT);
295             if (supplementalText == null) {
296                 return;
297             }
298             if (titleText == null) {
299                 getActivity().setTitle(supplementalText);
300             } else {
301                 String accessibilityTitle =
302                         new StringBuilder(titleText).append(",").append(supplementalText).toString();
303                 getActivity().setTitle(Utils.createAccessibleSequence(titleText, accessibilityTitle));
304             }
305         }
306     }
307 
308     @Override
onPause()309     public void onPause() {
310         super.onPause();
311     }
312 
313     @Override
onDestroy()314     public void onDestroy() {
315         if (mRemoteLockscreenValidationClient != null) {
316             mRemoteLockscreenValidationClient.disconnect();
317         }
318         super.onDestroy();
319     }
320 
authenticationSucceeded()321     protected abstract void authenticationSucceeded();
322 
prepareEnterAnimation()323     public void prepareEnterAnimation() {
324     }
325 
startEnterAnimation()326     public void startEnterAnimation() {
327     }
328 
reportFailedAttempt()329     protected void reportFailedAttempt() {
330         updateErrorMessage(
331                 mLockPatternUtils.getCurrentFailedPasswordAttempts(mEffectiveUserId) + 1);
332         mLockPatternUtils.reportFailedPasswordAttempt(mEffectiveUserId);
333     }
334 
updateErrorMessage(int numAttempts)335     protected void updateErrorMessage(int numAttempts) {
336         final int maxAttempts =
337                 mLockPatternUtils.getMaximumFailedPasswordsForWipe(mEffectiveUserId);
338         if (maxAttempts <= 0 || numAttempts <= 0) {
339             return;
340         }
341 
342         // Update the on-screen error string
343         if (mErrorTextView != null) {
344             final String message = getActivity().getString(
345                     R.string.lock_failed_attempts_before_wipe, numAttempts, maxAttempts);
346             showError(message, 0);
347         }
348 
349         // Only show popup dialog before the last attempt and before wipe
350         final int remainingAttempts = maxAttempts - numAttempts;
351         if (remainingAttempts > 1) {
352             return;
353         }
354         final FragmentManager fragmentManager = getChildFragmentManager();
355         final int userType = getUserTypeForWipe();
356         if (remainingAttempts == 1) {
357             // Last try
358             final String title = getActivity().getString(
359                     R.string.lock_last_attempt_before_wipe_warning_title);
360             final String overrideMessageId = getLastTryOverrideErrorMessageId(userType);
361             final int defaultMessageId = getLastTryDefaultErrorMessage(userType);
362             final String message = mDevicePolicyManager.getResources().getString(
363                     overrideMessageId, () -> getString(defaultMessageId));
364             LastTryDialog.show(fragmentManager, title, message,
365                     android.R.string.ok, false /* dismiss */);
366         } else {
367             // Device, profile, or secondary user is wiped
368             final String message = getWipeMessage(userType);
369             LastTryDialog.show(fragmentManager, null /* title */, message,
370                     com.android.settingslib.R.string.failed_attempts_now_wiping_dialog_dismiss,
371                     true /* dismiss */);
372         }
373     }
374 
getUserTypeForWipe()375     private int getUserTypeForWipe() {
376         final UserInfo userToBeWiped = mUserManager.getUserInfo(
377                 mDevicePolicyManager.getProfileWithMinimumFailedPasswordsForWipe(mEffectiveUserId));
378         UserHandle primaryUser = UserHandle.SYSTEM;
379         if (Flags.headlessSingleUserFixes()) {
380             UserHandle mainUser = mUserManager.getMainUser();
381             if (mainUser != null ) {
382                 primaryUser = mainUser;
383             }
384         }
385         if (userToBeWiped == null || userToBeWiped.getUserHandle().equals(primaryUser)) {
386             return USER_TYPE_PRIMARY;
387         } else if (userToBeWiped.isManagedProfile()) {
388             return USER_TYPE_MANAGED_PROFILE;
389         } else {
390             return USER_TYPE_SECONDARY;
391         }
392     }
393 
getLastTryOverrideErrorMessageId(int userType)394     protected abstract String getLastTryOverrideErrorMessageId(int userType);
getLastTryDefaultErrorMessage(int userType)395     protected abstract int getLastTryDefaultErrorMessage(int userType);
396 
getWipeMessage(int userType)397     private String getWipeMessage(int userType) {
398         switch (userType) {
399             case USER_TYPE_PRIMARY:
400                 return getString(com.android.settingslib
401                         .R.string.failed_attempts_now_wiping_device);
402             case USER_TYPE_MANAGED_PROFILE:
403                 return mDevicePolicyManager.getResources().getString(
404                         WORK_PROFILE_LOCK_ATTEMPTS_FAILED,
405                         () -> getString(
406                           com.android.settingslib.R.string.failed_attempts_now_wiping_profile));
407             case USER_TYPE_SECONDARY:
408                 return getString(com.android.settingslib.R.string.failed_attempts_now_wiping_user);
409             default:
410                 throw new IllegalArgumentException("Unrecognized user type:" + userType);
411         }
412     }
413 
414     private final Runnable mResetErrorRunnable = new Runnable() {
415         @Override
416         public void run() {
417             mErrorTextView.setText("");
418         }
419     };
420 
showError(CharSequence msg, long timeout)421     protected void showError(CharSequence msg, long timeout) {
422         mErrorTextView.setText(msg);
423         onShowError();
424         mHandler.removeCallbacks(mResetErrorRunnable);
425         if (timeout != 0) {
426             mHandler.postDelayed(mResetErrorRunnable, timeout);
427         }
428     }
429 
clearResetErrorRunnable()430     protected void clearResetErrorRunnable() {
431         mHandler.removeCallbacks(mResetErrorRunnable);
432     }
433 
validateGuess(LockscreenCredential credentialGuess)434     protected void validateGuess(LockscreenCredential credentialGuess) {
435         mRemoteLockscreenValidationFragment.validateLockscreenGuess(
436                 mRemoteLockscreenValidationClient, credentialGuess,
437                 mRemoteLockscreenValidationSession.getSourcePublicKey(), mCheckBox.isChecked());
438     }
439 
updateRemoteLockscreenValidationViews()440     protected void updateRemoteLockscreenValidationViews() {
441         if (!mRemoteValidation || mRemoteLockscreenValidationFragment == null) {
442             return;
443         }
444 
445         boolean enable = mRemoteLockscreenValidationFragment.isRemoteValidationInProgress();
446         mGlifLayout.setProgressBarShown(enable);
447         mCheckBox.setEnabled(!enable);
448         mCancelButton.setEnabled(!enable);
449     }
450 
451     /**
452      * Finishes the activity with result code {@link android.app.Activity#RESULT_FIRST_USER}
453      * after logging the error message.
454      * @param message Optional message to log.
455      */
onRemoteLockscreenValidationFailure(String message)456     public void onRemoteLockscreenValidationFailure(String message) {
457         if (!TextUtils.isEmpty(message)) {
458             Log.w(TAG, message);
459         }
460         getActivity().setResult(RESULT_FIRST_USER);
461         getActivity().finish();
462     }
463 
onShowError()464     protected abstract void onShowError();
465 
showError(int msg, long timeout)466     protected void showError(int msg, long timeout) {
467         showError(getText(msg), timeout);
468     }
469 
470     public static class LastTryDialog extends DialogFragment {
471         private static final String TAG = LastTryDialog.class.getSimpleName();
472 
473         private static final String ARG_TITLE = "title";
474         private static final String ARG_MESSAGE = "message";
475         private static final String ARG_BUTTON = "button";
476         private static final String ARG_DISMISS = "dismiss";
477 
show(FragmentManager from, String title, String message, int button, boolean dismiss)478         static boolean show(FragmentManager from, String title, String message, int button,
479                 boolean dismiss) {
480             LastTryDialog existent = (LastTryDialog) from.findFragmentByTag(TAG);
481             if (existent != null && !existent.isRemoving()) {
482                 return false;
483             }
484             Bundle args = new Bundle();
485             args.putString(ARG_TITLE, title);
486             args.putString(ARG_MESSAGE, message);
487             args.putInt(ARG_BUTTON, button);
488             args.putBoolean(ARG_DISMISS, dismiss);
489 
490             DialogFragment dialog = new LastTryDialog();
491             dialog.setArguments(args);
492             dialog.show(from, TAG);
493             from.executePendingTransactions();
494             return true;
495         }
496 
hide(FragmentManager from)497         static void hide(FragmentManager from) {
498             LastTryDialog dialog = (LastTryDialog) from.findFragmentByTag(TAG);
499             if (dialog != null) {
500                 dialog.dismissAllowingStateLoss();
501                 from.executePendingTransactions();
502             }
503         }
504 
505         /**
506          * Dialog setup.
507          * <p>
508          * To make it less likely that the dialog is dismissed accidentally, for example if the
509          * device is malfunctioning or if the device is in a pocket, we set
510          * {@code setCanceledOnTouchOutside(false)}.
511          */
512         @Override
onCreateDialog(Bundle savedInstanceState)513         public Dialog onCreateDialog(Bundle savedInstanceState) {
514             Dialog dialog = new AlertDialog.Builder(getActivity())
515                     .setTitle(getArguments().getString(ARG_TITLE))
516                     .setMessage(getArguments().getString(ARG_MESSAGE))
517                     .setPositiveButton(getArguments().getInt(ARG_BUTTON), null)
518                     .create();
519             dialog.setCanceledOnTouchOutside(false);
520             return dialog;
521         }
522 
523         @Override
onDismiss(final DialogInterface dialog)524         public void onDismiss(final DialogInterface dialog) {
525             super.onDismiss(dialog);
526             if (getActivity() != null && getArguments().getBoolean(ARG_DISMISS)) {
527                 getActivity().finish();
528             }
529         }
530     }
531 }
532