Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e942793b authored by Roman Birg's avatar Roman Birg Committed by Gerrit Code Review
Browse files

MasterClear: fix FRP wipe crash



Requesting setRequestedOrientation() right after showing a custom dialog
in a DialogFragment does not play nice. It forces the activity to be
recreated instantly, so when the task finishes, there original activity
the AsyncTask is tied to is no longer valid.

However, if we let fragment manager keep track of all the dialogs, it
doesn't break the expected behavior.

REF: CYNGNOS-427
Change-Id: I0609816182a6b5319d2a88ff0075d53e3c2fed16
Signed-off-by: default avatarRoman Birg <roman@cyngn.com>
(cherry picked from commit c8ccfc83)
parent df880d8b
Loading
Loading
Loading
Loading
+89 −38
Original line number Diff line number Diff line
@@ -17,15 +17,21 @@

package com.android.settings;

import android.annotation.Nullable;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.app.Fragment;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.pm.ActivityInfo;
import android.os.AsyncTask;
import android.service.persistentdata.PersistentDataBlockManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import com.android.internal.os.storage.ExternalStorageFormatter;

import android.content.Intent;
@@ -44,81 +50,126 @@ import android.os.UserManager;
 */
public class MasterClearConfirm extends DialogFragment {

    private static final String REASON_MASTER_CLEAR_CONFIRM = "MasterClearConfirm";

    private boolean mEraseSdCard;
    private boolean mEraseInternal;

    public static MasterClearConfirm createInstance(boolean wipeInternal, boolean wipeExternal) {
    public static class FrpDialog extends DialogFragment {

        private int mOriginalOrientation;

        public static FrpDialog createInstance(boolean wipeInternal, boolean wipeExternal) {
            Bundle b = new Bundle();
            b.putBoolean(MasterClear.EXTRA_WIPE_MEDIA, wipeInternal);
            b.putBoolean(MasterClear.EXTRA_WIPE_SDCARD, wipeExternal);
        MasterClearConfirm fragment = new MasterClearConfirm();
            FrpDialog fragment = new FrpDialog();
            fragment.setArguments(b);

            return fragment;
        }

    /**
     * The user has gone through the multiple confirmation, so now we go ahead
     * and invoke the Checkin Service to reset the device to its factory-default
     * state (rebooting in the process).
     */
    private void onResetConfirmed() {
        if (Utils.isMonkeyRunning()) {
            return;
        @Override
        public Dialog onCreateDialog(Bundle savedInstanceState) {
            final ProgressDialog progressDialog = new ProgressDialog(getActivity(), getTheme());
            progressDialog.setIndeterminate(true);
            progressDialog.setCancelable(false);
            progressDialog.setTitle(getActivity().getString(R.string.master_clear_progress_title));
            progressDialog.setMessage(getActivity().getString(R.string.master_clear_progress_text));
            return progressDialog;
        }

        final PersistentDataBlockManager pdbManager = (PersistentDataBlockManager)
                getActivity().getSystemService(Context.PERSISTENT_DATA_BLOCK_SERVICE);

        if (pdbManager != null && !pdbManager.getOemUnlockEnabled()) {
            // if OEM unlock is enabled, this will be wiped during FR process.
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setShowsDialog(true);
        }

            final ProgressDialog progressDialog = new ProgressDialog(getActivity());
            progressDialog.setIndeterminate(true);
            progressDialog.setCancelable(false);
            progressDialog.setTitle(
                    getActivity().getString(R.string.master_clear_progress_title));
            progressDialog.setMessage(
                    getActivity().getString(R.string.master_clear_progress_text));
            progressDialog.show();
        @Override
        public void onStart() {
            super.onStart();

            // need to prevent orientation changes as we're about to go into
            // a long IO request, so we won't be able to access inflate resources on flash
            final int oldOrientation = getActivity().getRequestedOrientation();
            mOriginalOrientation = getActivity().getRequestedOrientation();
            getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED);
        }

        @Override
        public void onStop() {
            super.onStop();
            getActivity().setRequestedOrientation(mOriginalOrientation);
        }

        @Override
        public void onResume() {
            super.onResume();
            new AsyncTask<Void, Void, Void>() {
                @Override
                protected Void doInBackground(Void... params) {
                    pdbManager.wipe();
                    final PersistentDataBlockManager pdbManager = (PersistentDataBlockManager)
                            getActivity().getSystemService(Context.PERSISTENT_DATA_BLOCK_SERVICE);
                    if (pdbManager != null) pdbManager.wipe();
                    return null;
                }

                @Override
                protected void onPostExecute(Void aVoid) {
                    progressDialog.hide();
                    getActivity().setRequestedOrientation(oldOrientation);
                    doMasterClear();
                    doMasterClear(getActivity(),
                            getArguments().getBoolean(MasterClear.EXTRA_WIPE_MEDIA),
                            getArguments().getBoolean(MasterClear.EXTRA_WIPE_SDCARD));
                    FrpDialog.this.dismiss();
                }
            }.execute();
        }
    }

    public static MasterClearConfirm createInstance(boolean wipeInternal, boolean wipeExternal) {
        Bundle b = new Bundle();
        b.putBoolean(MasterClear.EXTRA_WIPE_MEDIA, wipeInternal);
        b.putBoolean(MasterClear.EXTRA_WIPE_SDCARD, wipeExternal);
        MasterClearConfirm fragment = new MasterClearConfirm();
        fragment.setArguments(b);

        return fragment;
    }

    /**
     * The user has gone through the multiple confirmation, so now we go ahead
     * and invoke the Checkin Service to reset the device to its factory-default
     * state (rebooting in the process).
     */
    private void onResetConfirmed() {
        if (Utils.isMonkeyRunning()) {
            return;
        }

        final PersistentDataBlockManager pdbManager = (PersistentDataBlockManager)
                getActivity().getSystemService(Context.PERSISTENT_DATA_BLOCK_SERVICE);

        if (pdbManager != null && !pdbManager.getOemUnlockEnabled()) {
            // if OEM unlock is enabled, this will be wiped during FR process.
            FrpDialog.createInstance(mEraseInternal, mEraseSdCard)
                    .show(getFragmentManager(), "frp_dialog");
        } else {
            doMasterClear();
            doMasterClear(getActivity(), mEraseInternal, mEraseSdCard);
        }
    }

    private void doMasterClear() {
        if (mEraseSdCard) {
    private static void doMasterClear(Context context, boolean eraseInternal, boolean eraseSdCard) {
        if (eraseSdCard) {
            Intent intent = new Intent(ExternalStorageFormatter.FORMAT_AND_FACTORY_RESET);
            intent.putExtra(Intent.EXTRA_REASON, "MasterClearConfirm");
            intent.putExtra(MasterClear.EXTRA_WIPE_MEDIA, mEraseInternal);
            intent.putExtra(MasterClear.EXTRA_WIPE_SDCARD, mEraseSdCard);
            intent.putExtra(Intent.EXTRA_REASON, REASON_MASTER_CLEAR_CONFIRM);
            intent.putExtra(MasterClear.EXTRA_WIPE_MEDIA, eraseInternal);
            intent.putExtra(MasterClear.EXTRA_WIPE_SDCARD, eraseSdCard);
            intent.setComponent(ExternalStorageFormatter.COMPONENT_NAME);
            getActivity().startService(intent);
            context.startService(intent);
        } else {
            Intent intent = new Intent(Intent.ACTION_MASTER_CLEAR);
            intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
            intent.putExtra(MasterClear.EXTRA_WIPE_MEDIA, mEraseInternal);
            intent.putExtra(Intent.EXTRA_REASON, "MasterClearConfirm");
            getActivity().sendBroadcast(intent);
            intent.putExtra(MasterClear.EXTRA_WIPE_MEDIA, eraseInternal);
            intent.putExtra(Intent.EXTRA_REASON, REASON_MASTER_CLEAR_CONFIRM);
            context.sendBroadcast(intent);
            // Intent handling is asynchronous -- assume it will happen soon.
        }
    }