/* * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.settings.network; import android.app.ProgressDialog; import android.app.settings.SettingsEnums; import android.content.Context; import android.content.DialogInterface; import android.os.Looper; import android.text.TextUtils; import android.util.Log; import android.widget.Toast; import androidx.annotation.VisibleForTesting; import androidx.appcompat.app.AlertDialog; import androidx.preference.Preference; import com.android.settings.R; import com.android.settings.ResetNetworkRequest; import com.android.settings.core.BasePreferenceController; import com.android.settings.overlay.FeatureFactory; import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicReference; /** * This is to show a preference regarding resetting Bluetooth and Wi-Fi. */ public class BluetoothWiFiResetPreferenceController extends BasePreferenceController implements DialogInterface.OnClickListener, DialogInterface.OnDismissListener { private static final String TAG = "BtWiFiResetPreferenceController"; private final NetworkResetRestrictionChecker mRestrictionChecker; private DialogInterface mResetDialog; private ProgressDialog mProgressDialog; private ExecutorService mExecutorService; /** * Constructer. * @param context Context * @param preferenceKey is the key for Preference */ public BluetoothWiFiResetPreferenceController(Context context, String preferenceKey) { super(context, preferenceKey); // restriction check mRestrictionChecker = new NetworkResetRestrictionChecker(context); } @Override public int getAvailabilityStatus() { return mRestrictionChecker.hasUserRestriction() ? CONDITIONALLY_UNAVAILABLE : AVAILABLE; } @Override public boolean handlePreferenceTreeClick(Preference preference) { if (!TextUtils.equals(preference.getKey(), getPreferenceKey())) { return false; } buildResetDialog(preference); return true; } /** * This is a pop-up dialog showing detail of this reset option. */ void buildResetDialog(Preference preference) { if (mResetDialog != null) { return; } mResetDialog = new AlertDialog.Builder(mContext) .setTitle(R.string.reset_bluetooth_wifi_title) .setMessage(R.string.reset_bluetooth_wifi_desc) .setPositiveButton(R.string.reset_bluetooth_wifi_button_text, this) .setNegativeButton(R.string.cancel, null /* OnClickListener */) .setOnDismissListener(this) .show(); } public void onDismiss(DialogInterface dialog) { if (mResetDialog == dialog) { mResetDialog = null; } } /** * User pressed confirmation button, for starting reset operation. */ public void onClick(DialogInterface dialog, int which) { if (mResetDialog != dialog) { return; } // User confirm the reset operation MetricsFeatureProvider provider = FeatureFactory.getFactory(mContext) .getMetricsFeatureProvider(); provider.action(mContext, SettingsEnums.RESET_BLUETOOTH_WIFI_CONFIRM, true); // Non-cancelable progress dialog mProgressDialog = getProgressDialog(mContext); mProgressDialog.show(); // Run reset in background thread mExecutorService = Executors.newSingleThreadExecutor(); mExecutorService.execute(() -> { final AtomicReference exceptionDuringReset = new AtomicReference(); try { resetOperation().run(); } catch (Exception exception) { exceptionDuringReset.set(exception); } mContext.getMainExecutor().execute(() -> endOfReset(exceptionDuringReset.get())); }); } @VisibleForTesting protected ProgressDialog getProgressDialog(Context context) { final ProgressDialog progressDialog = new ProgressDialog(context); progressDialog.setIndeterminate(true); progressDialog.setCancelable(false); progressDialog.setMessage( context.getString(R.string.main_clear_progress_text)); return progressDialog; } @VisibleForTesting protected Runnable resetOperation() throws Exception { if (SubscriptionUtil.isSimHardwareVisible(mContext)) { return new ResetNetworkRequest( ResetNetworkRequest.RESET_WIFI_MANAGER | ResetNetworkRequest.RESET_WIFI_P2P_MANAGER | ResetNetworkRequest.RESET_BLUETOOTH_MANAGER) .toResetNetworkOperationBuilder(mContext, Looper.getMainLooper()) .build(); } /** * For device without SIMs visible to the user */ return new ResetNetworkRequest( ResetNetworkRequest.RESET_CONNECTIVITY_MANAGER | ResetNetworkRequest.RESET_VPN_MANAGER | ResetNetworkRequest.RESET_WIFI_MANAGER | ResetNetworkRequest.RESET_WIFI_P2P_MANAGER | ResetNetworkRequest.RESET_BLUETOOTH_MANAGER) .toResetNetworkOperationBuilder(mContext, Looper.getMainLooper()) .resetTelephonyAndNetworkPolicyManager(ResetNetworkRequest.ALL_SUBSCRIPTION_ID) .build(); } @VisibleForTesting protected void endOfReset(Exception exceptionDuringReset) { if (mExecutorService != null) { mExecutorService.shutdown(); mExecutorService = null; } if (mProgressDialog != null) { mProgressDialog.dismiss(); mProgressDialog = null; } if (exceptionDuringReset == null) { Toast.makeText(mContext, R.string.reset_bluetooth_wifi_complete_toast, Toast.LENGTH_SHORT).show(); } else { Log.e(TAG, "Exception during reset", exceptionDuringReset); } } }