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