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 61 private MenuItem mResetButton; 62 63 @Override 64 @XmlRes getPreferenceScreenResId()65 protected int getPreferenceScreenResId() { 66 return R.xml.reset_network_confirm_fragment; 67 } 68 69 @Override getToolbarMenuItems()70 public List<MenuItem> getToolbarMenuItems() { 71 return Collections.singletonList(mResetButton); 72 } 73 74 @Override onCreate(Bundle savedInstanceState)75 public void onCreate(Bundle savedInstanceState) { 76 super.onCreate(savedInstanceState); 77 78 mResetButton = new MenuItem.Builder(getContext()) 79 .setTitle(R.string.reset_network_confirm_button_text) 80 .setOnClickListener(i -> resetNetwork()) 81 .build(); 82 } 83 resetNetwork()84 private void resetNetwork() { 85 if (ActivityManager.isUserAMonkey()) { 86 return; 87 } 88 89 Context context = requireActivity().getApplicationContext(); 90 91 ConnectivityManager connectivityManager = (ConnectivityManager) 92 context.getSystemService(Context.CONNECTIVITY_SERVICE); 93 if (connectivityManager != null) { 94 connectivityManager.factoryReset(); 95 } 96 97 WifiManager wifiManager = (WifiManager) 98 context.getSystemService(Context.WIFI_SERVICE); 99 if (wifiManager != null) { 100 wifiManager.factoryReset(); 101 } 102 103 BluetoothManager btManager = (BluetoothManager) 104 context.getSystemService(Context.BLUETOOTH_SERVICE); 105 if (btManager != null) { 106 BluetoothAdapter btAdapter = btManager.getAdapter(); 107 if (btAdapter != null) { 108 btAdapter.factoryReset(); 109 } 110 } 111 112 int networkSubscriptionId = getNetworkSubscriptionId(); 113 TelephonyManager telephonyManager = (TelephonyManager) 114 context.getSystemService(Context.TELEPHONY_SERVICE); 115 if (telephonyManager != null) { 116 telephonyManager.factoryReset(networkSubscriptionId); 117 } 118 119 NetworkPolicyManager policyManager = (NetworkPolicyManager) 120 context.getSystemService(Context.NETWORK_POLICY_SERVICE); 121 if (policyManager != null) { 122 String subscriberId = telephonyManager.getSubscriberId(networkSubscriptionId); 123 policyManager.factoryReset(subscriberId); 124 } 125 126 restoreDefaultApn(context, networkSubscriptionId); 127 128 // There has been issues when Sms raw table somehow stores orphan 129 // fragments. They lead to garbled message when new fragments come 130 // in and combined with those stale ones. In case this happens again, 131 // user can reset all network settings which will clean up this table. 132 cleanUpSmsRawTable(context); 133 134 if (shouldResetEsim()) { 135 new EraseEsimAsyncTask(getContext(), context.getPackageName(), this).execute(); 136 } else { 137 showCompletionToast(getContext()); 138 } 139 } 140 shouldResetEsim()141 private boolean shouldResetEsim() { 142 SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences( 143 requireContext()); 144 return sharedPreferences.getBoolean(requireContext().getString(R.string.pk_reset_esim), 145 false); 146 } 147 getNetworkSubscriptionId()148 private int getNetworkSubscriptionId() { 149 SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences( 150 requireContext()); 151 String stringId = sharedPreferences.getString( 152 requireContext().getString(R.string.pk_reset_network_subscription), null); 153 if (TextUtils.isEmpty(stringId)) { 154 return SubscriptionManager.INVALID_SUBSCRIPTION_ID; 155 } 156 return Integer.parseInt(stringId); 157 } 158 restoreDefaultApn(Context context, int subscriptionId)159 private void restoreDefaultApn(Context context, int subscriptionId) { 160 Uri uri = Uri.parse(RESTORE_CARRIERS_URI); 161 162 if (SubscriptionManager.isUsableSubIdValue(subscriptionId)) { 163 uri = Uri.withAppendedPath(uri, "subId/" + subscriptionId); 164 } 165 166 ContentResolver resolver = context.getContentResolver(); 167 resolver.delete(uri, null, null); 168 } 169 cleanUpSmsRawTable(Context context)170 private void cleanUpSmsRawTable(Context context) { 171 ContentResolver resolver = context.getContentResolver(); 172 Uri uri = Uri.withAppendedPath(Telephony.Sms.CONTENT_URI, "raw/permanentDelete"); 173 resolver.delete(uri, null, null); 174 } 175 showCompletionToast(Context context)176 private static void showCompletionToast(Context context) { 177 Toast.makeText(context, R.string.reset_network_complete_toast, 178 Toast.LENGTH_SHORT).show(); 179 } 180 181 private static class EraseEsimAsyncTask extends AsyncTask<Void, Void, Boolean> { 182 183 private final Context mContext; 184 private final String mPackageName; 185 private final Fragment mFragment; 186 EraseEsimAsyncTask(Context context, String packageName, Fragment parent)187 EraseEsimAsyncTask(Context context, String packageName, Fragment parent) { 188 mContext = context; 189 mPackageName = packageName; 190 mFragment = parent; 191 } 192 193 @Override doInBackground(Void... voids)194 protected Boolean doInBackground(Void... voids) { 195 return RecoverySystem.wipeEuiccData(mContext, mPackageName); 196 } 197 198 @Override onPostExecute(Boolean succeeded)199 protected void onPostExecute(Boolean succeeded) { 200 if (succeeded) { 201 showCompletionToast(mContext); 202 } else { 203 ErrorDialog.show(mFragment, R.string.reset_esim_error_title); 204 } 205 } 206 } 207 } 208