Home | History | Annotate | Download | only in settings
      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 package com.android.settings;
     18 
     19 import android.annotation.Nullable;
     20 import android.app.Activity;
     21 import android.content.ContentResolver;
     22 import android.content.Context;
     23 import android.content.Intent;
     24 import android.content.res.Resources;
     25 import android.os.Bundle;
     26 import android.os.UserHandle;
     27 import android.os.UserManager;
     28 import android.provider.Settings;
     29 import android.provider.Settings.Global;
     30 import android.telephony.SubscriptionInfo;
     31 import android.telephony.SubscriptionManager;
     32 import android.telephony.euicc.EuiccManager;
     33 import android.text.TextUtils;
     34 import android.view.LayoutInflater;
     35 import android.view.View;
     36 import android.view.View.OnClickListener;
     37 import android.view.ViewGroup;
     38 import android.widget.ArrayAdapter;
     39 import android.widget.Button;
     40 import android.widget.CheckBox;
     41 import android.widget.Spinner;
     42 import android.widget.TextView;
     43 
     44 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
     45 import com.android.internal.telephony.PhoneConstants;
     46 import com.android.settings.core.InstrumentedFragment;
     47 import com.android.settings.core.SubSettingLauncher;
     48 import com.android.settings.enterprise.ActionDisabledByAdminDialogHelper;
     49 import com.android.settings.password.ChooseLockSettingsHelper;
     50 import com.android.settings.password.ConfirmLockPattern;
     51 import com.android.settingslib.RestrictedLockUtils;
     52 import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
     53 
     54 import java.util.ArrayList;
     55 import java.util.List;
     56 
     57 /**
     58  * Confirm and execute a reset of the device's network settings to a clean "just out of the box"
     59  * state.  Multiple confirmations are required: first, a general "are you sure you want to do this?"
     60  * prompt, followed by a keyguard pattern trace if the user has defined one, followed by a final
     61  * strongly-worded "THIS WILL RESET EVERYTHING" prompt.  If at any time the phone is allowed to go
     62  * to sleep, is locked, et cetera, then the confirmation sequence is abandoned.
     63  *
     64  * This is the initial screen.
     65  */
     66 public class ResetNetwork extends InstrumentedFragment {
     67     private static final String TAG = "ResetNetwork";
     68 
     69     // Arbitrary to avoid conficts
     70     private static final int KEYGUARD_REQUEST = 55;
     71 
     72     private List<SubscriptionInfo> mSubscriptions;
     73 
     74     private View mContentView;
     75     private Spinner mSubscriptionSpinner;
     76     private Button mInitiateButton;
     77     private View mEsimContainer;
     78     private CheckBox mEsimCheckbox;
     79 
     80     @Override
     81     public void onCreate(@Nullable Bundle savedInstanceState) {
     82         super.onCreate(savedInstanceState);
     83         getActivity().setTitle(R.string.reset_network_title);
     84     }
     85 
     86     /**
     87      * Keyguard validation is run using the standard {@link ConfirmLockPattern}
     88      * component as a subactivity
     89      * @param request the request code to be returned once confirmation finishes
     90      * @return true if confirmation launched
     91      */
     92     private boolean runKeyguardConfirmation(int request) {
     93         Resources res = getActivity().getResources();
     94         return new ChooseLockSettingsHelper(getActivity(), this).launchConfirmationActivity(
     95                 request, res.getText(R.string.reset_network_title));
     96     }
     97 
     98     @Override
     99     public void onActivityResult(int requestCode, int resultCode, Intent data) {
    100         super.onActivityResult(requestCode, resultCode, data);
    101 
    102         if (requestCode != KEYGUARD_REQUEST) {
    103             return;
    104         }
    105 
    106         // If the user entered a valid keyguard trace, present the final
    107         // confirmation prompt; otherwise, go back to the initial state.
    108         if (resultCode == Activity.RESULT_OK) {
    109             showFinalConfirmation();
    110         } else {
    111             establishInitialState();
    112         }
    113     }
    114 
    115     private void showFinalConfirmation() {
    116         Bundle args = new Bundle();
    117         if (mSubscriptions != null && mSubscriptions.size() > 0) {
    118             int selectedIndex = mSubscriptionSpinner.getSelectedItemPosition();
    119             SubscriptionInfo subscription = mSubscriptions.get(selectedIndex);
    120             args.putInt(PhoneConstants.SUBSCRIPTION_KEY, subscription.getSubscriptionId());
    121         }
    122         args.putBoolean(MasterClear.ERASE_ESIMS_EXTRA, mEsimCheckbox.isChecked());
    123         new SubSettingLauncher(getContext())
    124                 .setDestination(ResetNetworkConfirm.class.getName())
    125                 .setArguments(args)
    126                 .setTitle(R.string.reset_network_confirm_title)
    127                 .setSourceMetricsCategory(getMetricsCategory())
    128                 .launch();
    129     }
    130 
    131     /**
    132      * If the user clicks to begin the reset sequence, we next require a
    133      * keyguard confirmation if the user has currently enabled one.  If there
    134      * is no keyguard available, we simply go to the final confirmation prompt.
    135      */
    136     private final Button.OnClickListener mInitiateListener = new Button.OnClickListener() {
    137 
    138         @Override
    139         public void onClick(View v) {
    140             if (!runKeyguardConfirmation(KEYGUARD_REQUEST)) {
    141                 showFinalConfirmation();
    142             }
    143         }
    144     };
    145 
    146     /**
    147      * In its initial state, the activity presents a button for the user to
    148      * click in order to initiate a confirmation sequence.  This method is
    149      * called from various other points in the code to reset the activity to
    150      * this base state.
    151      *
    152      * <p>Reinflating views from resources is expensive and prevents us from
    153      * caching widget pointers, so we use a single-inflate pattern:  we lazy-
    154      * inflate each view, caching all of the widget pointers we'll need at the
    155      * time, then simply reuse the inflated views directly whenever we need
    156      * to change contents.
    157      */
    158     private void establishInitialState() {
    159         mSubscriptionSpinner = (Spinner) mContentView.findViewById(R.id.reset_network_subscription);
    160         mEsimContainer = mContentView.findViewById(R.id.erase_esim_container);
    161         mEsimCheckbox = mContentView.findViewById(R.id.erase_esim);
    162 
    163         mSubscriptions = SubscriptionManager.from(getActivity()).getActiveSubscriptionInfoList();
    164         if (mSubscriptions != null && mSubscriptions.size() > 0) {
    165             // Get the default subscription in the order of data, voice, sms, first up.
    166             int defaultSubscription = SubscriptionManager.getDefaultDataSubscriptionId();
    167             if (!SubscriptionManager.isUsableSubIdValue(defaultSubscription)) {
    168                 defaultSubscription = SubscriptionManager.getDefaultVoiceSubscriptionId();
    169             }
    170             if (!SubscriptionManager.isUsableSubIdValue(defaultSubscription)) {
    171                 defaultSubscription = SubscriptionManager.getDefaultSmsSubscriptionId();
    172             }
    173             if (!SubscriptionManager.isUsableSubIdValue(defaultSubscription)) {
    174                 defaultSubscription = SubscriptionManager.getDefaultSubscriptionId();
    175             }
    176 
    177             int selectedIndex = 0;
    178             int size = mSubscriptions.size();
    179             List<String> subscriptionNames = new ArrayList<>();
    180             for (SubscriptionInfo record : mSubscriptions) {
    181                 if (record.getSubscriptionId() == defaultSubscription) {
    182                     // Set the first selected value to the default
    183                     selectedIndex = subscriptionNames.size();
    184                 }
    185                 String name = record.getDisplayName().toString();
    186                 if (TextUtils.isEmpty(name)) {
    187                     name = record.getNumber();
    188                 }
    189                 if (TextUtils.isEmpty(name)) {
    190                     name = record.getCarrierName().toString();
    191                 }
    192                 if (TextUtils.isEmpty(name)) {
    193                     name = String.format("MCC:%s MNC:%s Slot:%s Id:%s", record.getMcc(),
    194                             record.getMnc(), record.getSimSlotIndex(), record.getSubscriptionId());
    195                 }
    196                 subscriptionNames.add(name);
    197             }
    198             ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(),
    199                     android.R.layout.simple_spinner_item, subscriptionNames);
    200             adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    201             mSubscriptionSpinner.setAdapter(adapter);
    202             mSubscriptionSpinner.setSelection(selectedIndex);
    203             if (mSubscriptions.size() > 1) {
    204                 mSubscriptionSpinner.setVisibility(View.VISIBLE);
    205             } else {
    206                 mSubscriptionSpinner.setVisibility(View.INVISIBLE);
    207             }
    208         } else {
    209             mSubscriptionSpinner.setVisibility(View.INVISIBLE);
    210         }
    211         mInitiateButton = (Button) mContentView.findViewById(R.id.initiate_reset_network);
    212         mInitiateButton.setOnClickListener(mInitiateListener);
    213         if (showEuiccSettings(getContext())) {
    214             mEsimContainer.setVisibility(View.VISIBLE);
    215             TextView title = mContentView.findViewById(R.id.erase_esim_title);
    216             title.setText(R.string.reset_esim_title);
    217             mEsimContainer.setOnClickListener(new OnClickListener() {
    218                 @Override
    219                 public void onClick(View v) {
    220                     mEsimCheckbox.toggle();
    221                 }
    222             });
    223         } else {
    224             mEsimCheckbox.setChecked(false /* checked */);
    225         }
    226     }
    227 
    228     private boolean showEuiccSettings(Context context) {
    229         EuiccManager euiccManager =
    230                 (EuiccManager) context.getSystemService(Context.EUICC_SERVICE);
    231         if (!euiccManager.isEnabled()) {
    232             return false;
    233         }
    234         ContentResolver resolver = context.getContentResolver();
    235         return Settings.Global.getInt(resolver, Global.EUICC_PROVISIONED, 0) != 0
    236                 || Settings.Global.getInt(resolver, Global.DEVELOPMENT_SETTINGS_ENABLED, 0) != 0;
    237     }
    238 
    239     @Override
    240     public View onCreateView(LayoutInflater inflater, ViewGroup container,
    241             Bundle savedInstanceState) {
    242         final UserManager um = UserManager.get(getActivity());
    243         final EnforcedAdmin admin = RestrictedLockUtils.checkIfRestrictionEnforced(
    244                 getActivity(), UserManager.DISALLOW_NETWORK_RESET, UserHandle.myUserId());
    245         if (!um.isAdminUser() || RestrictedLockUtils.hasBaseUserRestriction(getActivity(),
    246                 UserManager.DISALLOW_NETWORK_RESET, UserHandle.myUserId())) {
    247             return inflater.inflate(R.layout.network_reset_disallowed_screen, null);
    248         } else if (admin != null) {
    249             new ActionDisabledByAdminDialogHelper(getActivity())
    250                     .prepareDialogBuilder(UserManager.DISALLOW_NETWORK_RESET, admin)
    251                     .setOnDismissListener(__ -> getActivity().finish())
    252                     .show();
    253             return new View(getContext());
    254         }
    255 
    256         mContentView = inflater.inflate(R.layout.reset_network, null);
    257 
    258         establishInitialState();
    259         return mContentView;
    260     }
    261 
    262     @Override
    263     public int getMetricsCategory() {
    264         return MetricsEvent.RESET_NETWORK;
    265     }
    266 }
    267