Android 8.1中Settings中恢复出厂设置流程

1、Settings中点击重置选项后进入的布局如下

packages/apps/Settings/res/xml/reset_dashboard_fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:settings="http://schemas.android.com/apk/res/com.android.settings"
    android:title="@string/reset_dashboard_title"
    android:key="reset_dashboard_fragment_screen">

    <!-- Network reset -->
    <com.android.settingslib.RestrictedPreference
        android:key="network_reset_pref"
        android:title="@string/reset_network_title"
        settings:userRestriction="no_network_reset"
        settings:useAdminDisabledSummary="true"
        android:fragment="com.android.settings.ResetNetwork" />

    <!-- Reset app preferences -->
    <Preference
        android:key="reset_app_prefs"
        android:title="@string/reset_app_preferences" />

    <!-- Factory reset -->
    <com.android.settingslib.RestrictedPreference
        android:key="factory_reset"
        android:title="@string/master_clear_title"
        settings:keywords="@string/keywords_factory_data_reset"
        settings:userRestriction="no_factory_reset"
        settings:useAdminDisabledSummary="true"
        android:fragment="com.android.settings.MasterClear" />
</PreferenceScreen>

2、如下是重置应用的逻辑处理

packages/apps/Settings/src/com/android/settings/applications/ResetAppPrefPreferenceController.java
package com.android.settings.applications;

import android.content.Context;
import android.os.Bundle;
import android.support.v7.preference.Preference;
import android.text.TextUtils;

import com.android.settings.core.PreferenceControllerMixin;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnCreate;
import com.android.settingslib.core.lifecycle.events.OnSaveInstanceState;

public class ResetAppPrefPreferenceController extends AbstractPreferenceController
        implements PreferenceControllerMixin, LifecycleObserver, OnCreate, OnSaveInstanceState {

    privat ResetAppsHelper mResetAppsHelper;//ResetAppsHelper的是重点逻辑处理

    public ResetAppPrefPreferenceController(Context context, Lifecycle lifecycle) {
        super(context);
        mResetAppsHelper = new ResetAppsHelper(context);
        if (lifecycle != null) {
            lifecycle.addObserver(this);
        }
    }

    @Override
    public boolean handlePreferenceTreeClick(Preference preference) {
        if (!TextUtils.equals(preference.getKey(), getPreferenceKey())) {
            return false;
        }
        mResetAppsHelper.buildResetDialog();
        return true;
    }

    @Override
    public boolean isAvailable() {
        return true;
    }

    @Override
    public String getPreferenceKey() {
        return "reset_app_prefs";
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        mResetAppsHelper.onRestoreInstanceState(savedInstanceState);
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        mResetAppsHelper.onSaveInstanceState(outState);
    }
}

3、packages/apps/Settings/src/com/android/settings/applications/ResetAppsHelper.java

/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.android.settings.applications;

import static android.net.NetworkPolicyManager.POLICY_NONE;
import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;

import android.app.ActivityManager;
import android.app.AlertDialog;
import android.app.AppOpsManager;
import android.app.INotificationManager;
import android.content.Context;
import android.content.DialogInterface;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.net.NetworkPolicyManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.webkit.IWebViewUpdateService;

import com.android.settings.R;

import java.util.List;

public class ResetAppsHelper implements DialogInterface.OnClickListener,
        DialogInterface.OnDismissListener {

    private static final String EXTRA_RESET_DIALOG = "resetDialog";

    private final PackageManager mPm;
    private final IPackageManager mIPm;
    private final INotificationManager mNm;
    private final IWebViewUpdateService mWvus;
    private final NetworkPolicyManager mNpm;
    private final AppOpsManager mAom;
    private final Context mContext;

    private AlertDialog mResetDialog;

    public ResetAppsHelper(Context context) {
        mContext = context;
        mPm = context.getPackageManager();
        mIPm = IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
        mNm = INotificationManager.Stub.asInterface(
                ServiceManager.getService(Context.NOTIFICATION_SERVICE));
        mWvus = IWebViewUpdateService.Stub.asInterface(ServiceManager.getService("webviewupdate"));
        mNpm = NetworkPolicyManager.from(context);
        mAom = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
    }

    public void onRestoreInstanceState(Bundle savedInstanceState) {
        if (savedInstanceState != null && savedInstanceState.getBoolean(EXTRA_RESET_DIALOG)) {
            buildResetDialog();
        }
    }

    public void onSaveInstanceState(Bundle outState) {
        if (mResetDialog != null) {
            outState.putBoolean(EXTRA_RESET_DIALOG, true);
        }
    }

    public void stop() {
        if (mResetDialog != null) {
            mResetDialog.dismiss();
            mResetDialog = null;
        }
    }

    void buildResetDialog() {
        if (mResetDialog == null) {
            mResetDialog = new AlertDialog.Builder(mContext)
                    .setTitle(R.string.reset_app_preferences_title)
                    .setMessage(R.string.reset_app_preferences_desc)
                    .setPositiveButton(R.string.reset_app_preferences_button, this)
                    .setNegativeButton(R.string.cancel, null)
                    .setOnDismissListener(this)
                    .show();
        }
    }

    @Override
    public void onDismiss(DialogInterface dialog) {
        if (mResetDialog == dialog) {
            mResetDialog = null;
        }
    }

    @Override
    public void onClick(DialogInterface dialog, int which) {
        if (mResetDialog != dialog) {
            return;
        }
        AsyncTask.execute(new Runnable() {
            @Override
            public void run() {
                List<ApplicationInfo> apps = mPm.getInstalledApplications(
                        PackageManager.GET_DISABLED_COMPONENTS);
                for (int i = 0; i < apps.size(); i++) {
                    ApplicationInfo app = apps.get(i);
                    try {
                        mNm.setNotificationsEnabledForPackage(app.packageName, app.uid, true);
                    } catch (android.os.RemoteException ex) {
                    }
                    if (!app.enabled) {
                        if (mPm.getApplicationEnabledSetting(app.packageName)
                                == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER
                                && !isNonEnableableFallback(app.packageName)) {
                            mPm.setApplicationEnabledSetting(app.packageName,
                                    PackageManager.COMPONENT_ENABLED_STATE_DEFAULT,
                                    PackageManager.DONT_KILL_APP);
                        }
                    }
                }
                try {
                    mIPm.resetApplicationPreferences(UserHandle.myUserId());
                } catch (RemoteException e) {
                }
                mAom.resetAllModes();
                final int[] restrictedUids = mNpm.getUidsWithPolicy(
                        POLICY_REJECT_METERED_BACKGROUND);
                final int currentUserId = ActivityManager.getCurrentUser();
                for (int uid : restrictedUids) {
                    // Only reset for current user
                    if (UserHandle.getUserId(uid) == currentUserId) {
                        mNpm.setUidPolicy(uid, POLICY_NONE);
                    }
                }
            }
        });
    }

    private boolean isNonEnableableFallback(String packageName) {
        try {
            return mWvus.isFallbackPackage(packageName);
        } catch (RemoteException e) {
            throw new RuntimeException(e);
        }
    }
}

4、packages/apps/Settings/res/layout/master_clear.xml

   <Button
            android:id="@+id/initiate_master_clear"
            android:layout_gravity="center_horizontal"
            android:layout_marginTop="20dip"
            android:layout_marginBottom="12dip"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/master_clear_button_text"
            android:gravity="center" />

5、packages/apps/Settings/src/com/android/settings/MasterClear.java

mInitiateButton = (Button) mContentView.findViewById(R.id.initiate_master_clear);
mInitiateButton.setOnClickListener(mInitiateListener);
protected final Button.OnClickListener mInitiateListener = new Button.OnClickListener() {

        public void onClick(View view) {
            final Context context = view.getContext();
            if (Utils.isDemoUser(context)) {
                final ComponentName componentName = Utils.getDeviceOwnerComponent(context);
                if (componentName != null) {
                    final Intent requestFactoryReset = new Intent()
                            .setPackage(componentName.getPackageName())
                            .setAction(Intent.ACTION_FACTORY_RESET);
                    context.startActivity(requestFactoryReset);
                }
             /*SPRD added for bug 692488, pop a dialog when low battery */
             } else if (mLevelpower < POWER_LIMIT) {
                   mIsDialogShow = true;
                   dialog();
             } else if (!runKeyguardConfirmation(KEYGUARD_REQUEST)) {
                showFinalConfirmation();
            }
        }
    };

6、packages/apps/Settings/res/layout/master_clear_confirm.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    >

    <TextView
        android:id="@+id/master_clear_confirm"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="12dp"
        android:layout_marginEnd="12dp"
        android:layout_marginTop="12dp"
        android:textSize="20sp"
        android:text="@string/master_clear_final_desc" />

    <Button android:id="@+id/execute_master_clear"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="40dip"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/master_clear_final_button_text"
        android:gravity="center" />
        
</LinearLayout>

7、packages/apps/Settings/src/com/android/settings/MasterClearConfirm.java

 private void establishFinalConfirmationState() {
        mContentView.findViewById(R.id.execute_master_clear)
                .setOnClickListener(mFinalClickListener);
    }
  private Button.OnClickListener mFinalClickListener = new Button.OnClickListener() {

        public void onClick(View v) {
            if (Utils.isMonkeyRunning()) {
                return;
            }

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

            if (pdbManager != null && !oemLockManager.isOemUnlockAllowed() &&
                    Utils.isDeviceProvisioned(getActivity())) {
                // if OEM unlock is allowed, the persistent data block will be wiped during FR
                // process. If disabled, it will be wiped here, unless the device is still being
                // provisioned, in which case the persistent data block will be preserved.
                new AsyncTask<Void, Void, Void>() {
                    int mOldOrientation;
                    ProgressDialog mProgressDialog;

                    @Override
                    protected Void doInBackground(Void... params) {
                        pdbManager.wipe();
                        return null;
                    }

                    @Override
                    protected void onPostExecute(Void aVoid) {
                        mProgressDialog.hide();
                        if (getActivity() != null) {
                            getActivity().setRequestedOrientation(mOldOrientation);
                            doMasterClear();
                        }
                    }

                    @Override
                    protected void onPreExecute() {
                        mProgressDialog = getProgressDialog();
                        mProgressDialog.show();

                        // 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
                        mOldOrientation = getActivity().getRequestedOrientation();
                        getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED);
                    }
                }.execute();
            } else {
                doMasterClear();
            }
        }

        private ProgressDialog getProgressDialog() {
            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));
            return progressDialog;
        }
    };    

8、frameworks/base/services/core/java/com/android/server/MasterClearReceiver.java

public class MasterClearReceiver extends BroadcastReceiver {
    private static final String TAG = "MasterClear";
    private boolean mWipeExternalStorage;
    private boolean mWipeEsims;

    @Override
    public void onReceive(final Context context, final Intent intent) {
        if (intent.getAction().equals(Intent.ACTION_REMOTE_INTENT)) {
            if (!"google.com".equals(intent.getStringExtra("from"))) {
                Slog.w(TAG, "Ignoring master clear request -- not from trusted server.");
                return;
            }
        }
        if (Intent.ACTION_MASTER_CLEAR.equals(intent.getAction())) {
            Slog.w(TAG, "The request uses the deprecated Intent#ACTION_MASTER_CLEAR, "
                    + "Intent#ACTION_FACTORY_RESET should be used instead.");
        }
        if (intent.hasExtra(Intent.EXTRA_FORCE_MASTER_CLEAR)) {
            Slog.w(TAG, "The request uses the deprecated Intent#EXTRA_FORCE_MASTER_CLEAR, "
                    + "Intent#EXTRA_FORCE_FACTORY_RESET should be used instead.");
        }

        final boolean shutdown = intent.getBooleanExtra("shutdown", false);
        final String reason = intent.getStringExtra(Intent.EXTRA_REASON);
        mWipeExternalStorage = intent.getBooleanExtra(Intent.EXTRA_WIPE_EXTERNAL_STORAGE, false);
        mWipeEsims = intent.getBooleanExtra(Intent.EXTRA_WIPE_ESIMS, false);
        final boolean forceWipe = intent.getBooleanExtra(Intent.EXTRA_FORCE_MASTER_CLEAR, false)
                || intent.getBooleanExtra(Intent.EXTRA_FORCE_FACTORY_RESET, false);

        Slog.w(TAG, "!!! FACTORY RESET !!!");
        // The reboot call is blocking, so we need to do it on another thread.
        Thread thr = new Thread("Reboot") {
            @Override
            public void run() {
                try {
                    RecoverySystem
                            .rebootWipeUserData(context, shutdown, reason, forceWipe, mWipeEsims);
                    Log.wtf(TAG, "Still running after master clear?!");
                } catch (IOException e) {
                    Slog.e(TAG, "Can't perform master clear/factory reset", e);
                } catch (SecurityException e) {
                    Slog.e(TAG, "Can't perform master clear/factory reset", e);
                }
            }
        };

        if (mWipeExternalStorage || mWipeEsims) {
            // thr will be started at the end of this task.
            new WipeDataTask(context, thr).execute();
        } else {
            thr.start();
        }
    }

    private class WipeDataTask extends AsyncTask<Void, Void, Void> {
        private final Thread mChainedTask;
        private final Context mContext;
        private final ProgressDialog mProgressDialog;

        public WipeDataTask(Context context, Thread chainedTask) {
            mContext = context;
            mChainedTask = chainedTask;
            mProgressDialog = new ProgressDialog(context);
        }

        @Override
        protected void onPreExecute() {
            mProgressDialog.setIndeterminate(true);
            mProgressDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
            mProgressDialog.setMessage(mContext.getText(R.string.progress_erasing));
            mProgressDialog.show();
        }

        @Override
        protected Void doInBackground(Void... params) {
            Slog.w(TAG, "Wiping adoptable disks");
            if (mWipeExternalStorage) {
                StorageManager sm = (StorageManager) mContext.getSystemService(
                        Context.STORAGE_SERVICE);
                sm.wipeAdoptableDisks();
            }
            return null;
        }

        @Override
        protected void onPostExecute(Void result) {
            mProgressDialog.dismiss();
            mChainedTask.start();
        }

    }
}

9、frameworks/base/core/java/android/os/RecoverySystem.java

 public static void rebootWipeUserData(Context context, boolean shutdown, String reason,
            boolean force, boolean wipeEuicc) throws IOException {
        UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
        if (!force && um.hasUserRestriction(UserManager.DISALLOW_FACTORY_RESET)) {
            throw new SecurityException("Wiping data is not allowed for this user.");
        }
        final ConditionVariable condition = new ConditionVariable();

        Intent intent = new Intent("android.intent.action.MASTER_CLEAR_NOTIFICATION");
        intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND
                | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
        context.sendOrderedBroadcastAsUser(intent, UserHandle.SYSTEM,
                android.Manifest.permission.MASTER_CLEAR,
                new BroadcastReceiver() {
                    @Override
                    public void onReceive(Context context, Intent intent) {
                        condition.open();
                    }
                }, null, 0, null, null);

        // Block until the ordered broadcast has completed.
        condition.block();

        wipeEuiccData(context, wipeEuicc);

        String shutdownArg = null;
        if (shutdown) {
            shutdownArg = "--shutdown_after";
        }

        String reasonArg = null;
        if (!TextUtils.isEmpty(reason)) {
            reasonArg = "--reason=" + sanitizeArg(reason);
        }

        final String localeArg = "--locale=" + Locale.getDefault().toLanguageTag() ;
        bootCommand(context, shutdownArg, "--wipe_data", reasonArg, localeArg);
    }
      private static void bootCommand(Context context, String... args) throws IOException {
        LOG_FILE.delete();

        StringBuilder command = new StringBuilder();
        for (String arg : args) {
            if (!TextUtils.isEmpty(arg)) {
                command.append(arg);
                command.append("\n");
            }
        }

        // Write the command into BCB (bootloader control block) and boot from
        // there. Will not return unless failed.
        RecoverySystem rs = (RecoverySystem) context.getSystemService(Context.RECOVERY_SERVICE);
        rs.rebootRecoveryWithCommand(command.toString());

        throw new IOException("Reboot failed (no permissions?)");
    }
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android 8.1Android操作系统的一个版本,它是在Android 8.0基础上进行了改进和优化的最新版本。Android 8.1引入了一些新的功能和改进,例如:自适应图标,通知渠道,自动填充框架等。自适应图标功能使得应用程序的图标可以适应不同的设备和启动器,提供更好的用户体验。通知渠道则使得用户能够更好地管理和控制应用程序发送的通知,减少了用户被打扰的可能性。自动填充框架则简化了用户在输入表单时填写信息的操作,提高了用户填写表单的效率。 Android Studio是开发Android应用程序的集成开发环境。通过Android Studio,开发者可以创建、编辑、调试和测试Android应用程序。在Android Studio,可以通过“设置”功能对开发环境进行个性化和配置调整。在“设置”菜单,开发者可以选择和配置不同的主题和UI风格,调整代码编辑器的显示和行为,还可以选择不同的编程语言和版本进行开发。此外,开发者还可以设置和管理各种插件和工具,以满足自己的需求。Android Studio的“设置”功能提供了丰富的选项和配置,使得开发者能够根据自己的喜好和需要对开发环境进行个性化定制,提高了开发效率和舒适度。 总而言之,Android 8.1Android操作系统的最新版本,它引入了一些新的功能和改进,提供了更好的用户体验。Android Studio是一款用于开发Android应用程序的集成开发环境,它提供了丰富的个性化和配置选项,使得开发者能够根据自己的需求对开发环境进行调整和优化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值