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