1 /* 2 * Copyright (C) 2018 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.car.settings.system; 18 19 import android.app.ActivityManager; 20 import android.bluetooth.BluetoothAdapter; 21 import android.bluetooth.BluetoothManager; 22 import android.content.ContentResolver; 23 import android.content.Context; 24 import android.content.SharedPreferences; 25 import android.net.ConnectivityManager; 26 import android.net.NetworkPolicyManager; 27 import android.net.Uri; 28 import android.net.wifi.WifiManager; 29 import android.os.AsyncTask; 30 import android.os.Bundle; 31 import android.os.RecoverySystem; 32 import android.provider.Telephony; 33 import android.telephony.SubscriptionManager; 34 import android.telephony.TelephonyManager; 35 import android.text.TextUtils; 36 import android.widget.Toast; 37 38 import androidx.annotation.VisibleForTesting; 39 import androidx.annotation.XmlRes; 40 import androidx.fragment.app.Fragment; 41 import androidx.preference.PreferenceManager; 42 43 import com.android.car.settings.R; 44 import com.android.car.settings.common.ErrorDialog; 45 import com.android.car.settings.common.SettingsFragment; 46 import com.android.car.ui.toolbar.MenuItem; 47 48 import java.util.Collections; 49 import java.util.List; 50 51 /** 52 * Final warning presented to user to confirm restoring network settings to the factory default. 53 * If a user confirms, all settings are reset for connectivity, Wi-Fi, and Bluetooth. 54 */ 55 public class ResetNetworkConfirmFragment extends SettingsFragment { 56 57 // Copied from com.android.settings.network.ApnSettings. 58 @VisibleForTesting 59 static final String RESTORE_CARRIERS_URI = "content://telephony/carriers/restore"; 60 @VisibleForTesting 61 AsyncTask<Void, Void, Boolean> mEraseEsimAsyncTask; 62 63 private MenuItem mResetButton; 64 65 @Override 66 @XmlRes getPreferenceScreenResId()67 protected int getPreferenceScreenResId() { 68 return R.xml.reset_network_confirm_fragment; 69 } 70 71 @Override getToolbarMenuItems()72 public List<MenuItem> getToolbarMenuItems() { 73 return Collections.singletonList(mResetButton); 74 } 75 76 @Override onCreate(Bundle savedInstanceState)77 public void onCreate(Bundle savedInstanceState) { 78 super.onCreate(savedInstanceState); 79 80 mResetButton = new MenuItem.Builder(getContext()) 81 .setTitle(R.string.reset_network_confirm_button_text) 82 .setOnClickListener(i -> resetNetwork()) 83 .build(); 84 } 85 resetNetwork()86 private void resetNetwork() { 87 if (ActivityManager.isUserAMonkey()) { 88 return; 89 } 90 91 Context context = getApplicationContext(); 92 93 ConnectivityManager connectivityManager = (ConnectivityManager) 94 context.getSystemService(Context.CONNECTIVITY_SERVICE); 95 if (connectivityManager != null) { 96 connectivityManager.factoryReset(); 97 } 98 99 WifiManager wifiManager = (WifiManager) 100 context.getSystemService(Context.WIFI_SERVICE); 101 if (wifiManager != null) { 102 wifiManager.factoryReset(); 103 } 104 105 BluetoothManager btManager = (BluetoothManager) 106 context.getSystemService(Context.BLUETOOTH_SERVICE); 107 if (btManager != null) { 108 BluetoothAdapter btAdapter = btManager.getAdapter(); 109 if (btAdapter != null) { 110 btAdapter.clearBluetooth(); 111 } 112 } 113 114 int networkSubscriptionId = getNetworkSubscriptionId(); 115 TelephonyManager telephonyManager = (TelephonyManager) 116 context.getSystemService(Context.TELEPHONY_SERVICE); 117 if (telephonyManager != null) { 118 telephonyManager.factoryReset(networkSubscriptionId); 119 } 120 121 NetworkPolicyManager policyManager = (NetworkPolicyManager) 122 context.getSystemService(Context.NETWORK_POLICY_SERVICE); 123 if (policyManager != null) { 124 String subscriberId = telephonyManager.getSubscriberId(networkSubscriptionId); 125 policyManager.factoryReset(subscriberId); 126 } 127 128 restoreDefaultApn(context, networkSubscriptionId); 129 130 // There has been issues when Sms raw table somehow stores orphan 131 // fragments. They lead to garbled message when new fragments come 132 // in and combined with those stale ones. In case this happens again, 133 // user can reset all network settings which will clean up this table. 134 cleanUpSmsRawTable(context); 135 136 if (shouldResetEsim()) { 137 mEraseEsimAsyncTask = new EraseEsimAsyncTask(getContext(), context.getPackageName(), 138 this); 139 mEraseEsimAsyncTask.execute(); 140 } else { 141 showCompletionToast(getContext()); 142 } 143 } 144 shouldResetEsim()145 private boolean shouldResetEsim() { 146 SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences( 147 requireContext()); 148 return sharedPreferences.getBoolean(requireContext().getString(R.string.pk_reset_esim), 149 false); 150 } 151 getNetworkSubscriptionId()152 private int getNetworkSubscriptionId() { 153 SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences( 154 requireContext()); 155 String stringId = sharedPreferences.getString( 156 requireContext().getString(R.string.pk_reset_network_subscription), null); 157 if (TextUtils.isEmpty(stringId)) { 158 return SubscriptionManager.INVALID_SUBSCRIPTION_ID; 159 } 160 return Integer.parseInt(stringId); 161 } 162 restoreDefaultApn(Context context, int subscriptionId)163 private void restoreDefaultApn(Context context, int subscriptionId) { 164 Uri uri = Uri.parse(RESTORE_CARRIERS_URI); 165 166 if (SubscriptionManager.isUsableSubIdValue(subscriptionId)) { 167 uri = Uri.withAppendedPath(uri, "subId/" + subscriptionId); 168 } 169 170 ContentResolver resolver = context.getContentResolver(); 171 resolver.delete(uri, null, null); 172 } 173 cleanUpSmsRawTable(Context context)174 private void cleanUpSmsRawTable(Context context) { 175 ContentResolver resolver = context.getContentResolver(); 176 Uri uri = Uri.withAppendedPath(Telephony.Sms.CONTENT_URI, "raw/permanentDelete"); 177 resolver.delete(uri, null, null); 178 } 179 showCompletionToast(Context context)180 private static void showCompletionToast(Context context) { 181 Toast.makeText(context, R.string.reset_network_complete_toast, 182 Toast.LENGTH_SHORT).show(); 183 } 184 185 @VisibleForTesting getApplicationContext()186 Context getApplicationContext() { 187 return requireActivity().getApplicationContext(); 188 } 189 190 private static class EraseEsimAsyncTask extends AsyncTask<Void, Void, Boolean> { 191 192 private final Context mContext; 193 private final String mPackageName; 194 private final Fragment mFragment; 195 EraseEsimAsyncTask(Context context, String packageName, Fragment parent)196 EraseEsimAsyncTask(Context context, String packageName, Fragment parent) { 197 mContext = context; 198 mPackageName = packageName; 199 mFragment = parent; 200 } 201 202 @Override doInBackground(Void... voids)203 protected Boolean doInBackground(Void... voids) { 204 return RecoverySystem.wipeEuiccData(mContext, mPackageName); 205 } 206 207 @Override onPostExecute(Boolean succeeded)208 protected void onPostExecute(Boolean succeeded) { 209 if (succeeded) { 210 showCompletionToast(mContext); 211 } else { 212 ErrorDialog.show(mFragment, R.string.reset_esim_error_title); 213 } 214 } 215 } 216 } 217