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.app.Activity; 20 import android.app.ProgressDialog; 21 import android.app.settings.SettingsEnums; 22 import android.content.Context; 23 import android.os.AsyncTask; 24 import android.os.Bundle; 25 import android.os.Looper; 26 import android.telephony.SubscriptionManager; 27 import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener; 28 import android.util.Log; 29 import android.view.LayoutInflater; 30 import android.view.View; 31 import android.view.ViewGroup; 32 import android.widget.Button; 33 import android.widget.TextView; 34 import android.widget.Toast; 35 36 import androidx.annotation.VisibleForTesting; 37 import androidx.appcompat.app.AlertDialog; 38 39 import com.android.settings.core.InstrumentedFragment; 40 import com.android.settings.network.ResetNetworkOperationBuilder; 41 import com.android.settings.network.ResetNetworkRestrictionViewBuilder; 42 43 import java.util.concurrent.atomic.AtomicBoolean; 44 45 /** 46 * Confirm and execute a reset of the network settings to a clean "just out of the box" 47 * state. Multiple confirmations are required: first, a general "are you sure 48 * you want to do this?" prompt, followed by a keyguard pattern trace if the user 49 * has defined one, followed by a final strongly-worded "THIS WILL RESET EVERYTHING" 50 * prompt. If at any time the phone is allowed to go to sleep, is 51 * locked, et cetera, then the confirmation sequence is abandoned. 52 * 53 * This is the confirmation screen. 54 */ 55 public class ResetNetworkConfirm extends InstrumentedFragment { 56 private static final String TAG = "ResetNetworkConfirm"; 57 58 @VisibleForTesting View mContentView; 59 @VisibleForTesting ResetNetworkTask mResetNetworkTask; 60 @VisibleForTesting Activity mActivity; 61 @VisibleForTesting ResetNetworkRequest mResetNetworkRequest; 62 private ProgressDialog mProgressDialog; 63 private AlertDialog mAlertDialog; 64 @VisibleForTesting ResetSubscriptionContract mResetSubscriptionContract; 65 private OnSubscriptionsChangedListener mSubscriptionsChangedListener; 66 67 /** 68 * Async task used to do all reset task. If error happens during 69 * erasing eSIM profiles or timeout, an error msg is shown. 70 */ 71 private class ResetNetworkTask extends AsyncTask<Void, Void, Boolean> { 72 private static final String TAG = "ResetNetworkTask"; 73 74 private final Context mContext; 75 ResetNetworkTask(Context context)76 ResetNetworkTask(Context context) { 77 mContext = context; 78 } 79 80 @Override doInBackground(Void... params)81 protected Boolean doInBackground(Void... params) { 82 final AtomicBoolean resetEsimSuccess = new AtomicBoolean(true); 83 84 String resetEsimPackageName = mResetNetworkRequest.getResetEsimPackageName(); 85 ResetNetworkOperationBuilder builder = mResetNetworkRequest 86 .toResetNetworkOperationBuilder(mContext, Looper.getMainLooper()); 87 if (resetEsimPackageName != null) { 88 // Override reset eSIM option for the result of reset operation 89 builder = builder.resetEsim(resetEsimPackageName, 90 success -> { resetEsimSuccess.set(success); } 91 ); 92 } 93 builder.build().run(); 94 95 boolean isResetSucceed = resetEsimSuccess.get(); 96 Log.d(TAG, "network factoryReset complete. succeeded: " 97 + String.valueOf(isResetSucceed)); 98 return isResetSucceed; 99 } 100 101 @Override onPostExecute(Boolean succeeded)102 protected void onPostExecute(Boolean succeeded) { 103 if (mProgressDialog != null && mProgressDialog.isShowing()) { 104 mProgressDialog.dismiss(); 105 } 106 107 if (succeeded) { 108 Toast.makeText(mContext, R.string.reset_network_complete_toast, Toast.LENGTH_SHORT) 109 .show(); 110 } else { 111 mAlertDialog = new AlertDialog.Builder(mContext) 112 .setTitle(R.string.reset_esim_error_title) 113 .setMessage(R.string.reset_esim_error_msg) 114 .setPositiveButton(android.R.string.ok, null /* listener */) 115 .show(); 116 } 117 } 118 } 119 120 /** 121 * The user has gone through the multiple confirmation, so now we go ahead 122 * and reset the network settings to its factory-default state. 123 */ 124 @VisibleForTesting 125 Button.OnClickListener mFinalClickListener = new Button.OnClickListener() { 126 127 @Override 128 public void onClick(View v) { 129 if (Utils.isMonkeyRunning()) { 130 return; 131 } 132 133 // abandon execution if subscription no longer active 134 Integer subId = mResetSubscriptionContract.getAnyMissingSubscriptionId(); 135 if (subId != null) { 136 Log.w(TAG, "subId " + subId + " no longer active"); 137 getActivity().onBackPressed(); 138 return; 139 } 140 141 // Should dismiss the progress dialog firstly if it is showing 142 // Or not the progress dialog maybe not dismissed in fast clicking. 143 if (mProgressDialog != null && mProgressDialog.isShowing()) { 144 mProgressDialog.dismiss(); 145 } 146 147 mProgressDialog = getProgressDialog(mActivity); 148 mProgressDialog.show(); 149 150 mResetNetworkTask = new ResetNetworkTask(mActivity); 151 mResetNetworkTask.execute(); 152 } 153 }; 154 getProgressDialog(Context context)155 private ProgressDialog getProgressDialog(Context context) { 156 final ProgressDialog progressDialog = new ProgressDialog(context); 157 progressDialog.setIndeterminate(true); 158 progressDialog.setCancelable(false); 159 progressDialog.setMessage( 160 context.getString(R.string.main_clear_progress_text)); 161 return progressDialog; 162 } 163 164 /** 165 * Configure the UI for the final confirmation interaction 166 */ establishFinalConfirmationState()167 private void establishFinalConfirmationState() { 168 mContentView.findViewById(R.id.execute_reset_network) 169 .setOnClickListener(mFinalClickListener); 170 } 171 172 @VisibleForTesting setSubtitle()173 void setSubtitle() { 174 if (mResetNetworkRequest.getResetEsimPackageName() != null) { 175 ((TextView) mContentView.findViewById(R.id.reset_network_confirm)) 176 .setText(R.string.reset_network_final_desc_esim); 177 } 178 } 179 180 @Override onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)181 public View onCreateView(LayoutInflater inflater, ViewGroup container, 182 Bundle savedInstanceState) { 183 View view = (new ResetNetworkRestrictionViewBuilder(mActivity)).build(); 184 if (view != null) { 185 mResetSubscriptionContract.close(); 186 Log.w(TAG, "Access deny."); 187 return view; 188 } 189 mContentView = inflater.inflate(R.layout.reset_network_confirm, null); 190 establishFinalConfirmationState(); 191 setSubtitle(); 192 return mContentView; 193 } 194 195 @Override onCreate(Bundle savedInstanceState)196 public void onCreate(Bundle savedInstanceState) { 197 super.onCreate(savedInstanceState); 198 199 Bundle args = getArguments(); 200 if (args == null) { 201 args = savedInstanceState; 202 } 203 mResetNetworkRequest = new ResetNetworkRequest(args); 204 205 mActivity = getActivity(); 206 207 mResetSubscriptionContract = new ResetSubscriptionContract(getContext(), 208 mResetNetworkRequest) { 209 @Override 210 public void onSubscriptionInactive(int subscriptionId) { 211 // close UI if subscription no longer active 212 Log.w(TAG, "subId " + subscriptionId + " no longer active."); 213 getActivity().onBackPressed(); 214 } 215 }; 216 } 217 218 @Override onSaveInstanceState(Bundle outState)219 public void onSaveInstanceState(Bundle outState) { 220 super.onSaveInstanceState(outState); 221 mResetNetworkRequest.writeIntoBundle(outState); 222 } 223 224 @Override onDestroy()225 public void onDestroy() { 226 if (mResetNetworkTask != null) { 227 mResetNetworkTask.cancel(true /* mayInterruptIfRunning */); 228 mResetNetworkTask = null; 229 } 230 if (mResetSubscriptionContract != null) { 231 mResetSubscriptionContract.close(); 232 mResetSubscriptionContract = null; 233 } 234 if (mProgressDialog != null) { 235 mProgressDialog.dismiss(); 236 } 237 if (mAlertDialog != null) { 238 mAlertDialog.dismiss(); 239 } 240 super.onDestroy(); 241 } 242 243 @Override getMetricsCategory()244 public int getMetricsCategory() { 245 return SettingsEnums.RESET_NETWORK_CONFIRM; 246 } 247 } 248