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