1 /* 2 * Copyright (C) 2023 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.network 18 19 import android.app.settings.SettingsEnums 20 import android.content.Context 21 import android.os.Looper 22 import android.os.UserManager 23 import android.util.Log 24 import android.widget.Toast 25 import androidx.annotation.VisibleForTesting 26 import androidx.compose.material3.Text 27 import androidx.compose.runtime.Composable 28 import androidx.compose.runtime.rememberCoroutineScope 29 import androidx.compose.ui.res.stringResource 30 import com.android.settings.R 31 import com.android.settings.ResetNetworkRequest 32 import com.android.settings.overlay.FeatureFactory.Companion.featureFactory 33 import com.android.settings.spa.preference.ComposePreferenceController 34 import com.android.settingslib.spa.widget.dialog.AlertDialogButton 35 import com.android.settingslib.spa.widget.dialog.rememberAlertDialogPresenter 36 import com.android.settingslib.spa.widget.preference.PreferenceModel 37 import com.android.settingslib.spaprivileged.model.enterprise.Restrictions 38 import com.android.settingslib.spaprivileged.template.preference.RestrictedPreference 39 import kotlinx.coroutines.CoroutineScope 40 import kotlinx.coroutines.Dispatchers 41 import kotlinx.coroutines.launch 42 import kotlinx.coroutines.withContext 43 44 /** 45 * This is to show a preference regarding resetting Bluetooth and Wi-Fi. 46 */ 47 class BluetoothWiFiResetPreferenceController(context: Context, preferenceKey: String) : 48 ComposePreferenceController(context, preferenceKey) { 49 50 private val restrictionChecker = NetworkResetRestrictionChecker(context) 51 getAvailabilityStatusnull52 override fun getAvailabilityStatus() = 53 if (restrictionChecker.hasUserRestriction()) CONDITIONALLY_UNAVAILABLE else AVAILABLE 54 55 @Composable 56 override fun Content() { 57 val coroutineScope = rememberCoroutineScope() 58 val dialogPresenter = rememberAlertDialogPresenter( 59 confirmButton = AlertDialogButton( 60 text = stringResource(R.string.reset_bluetooth_wifi_button_text), 61 ) { reset(coroutineScope) }, 62 dismissButton = AlertDialogButton(text = stringResource(R.string.cancel)), 63 title = stringResource(R.string.reset_bluetooth_wifi_title), 64 ) { 65 Text(stringResource(R.string.reset_bluetooth_wifi_desc)) 66 } 67 68 RestrictedPreference( 69 model = object : PreferenceModel { 70 override val title = stringResource(R.string.reset_bluetooth_wifi_title) 71 override val onClick = dialogPresenter::open 72 }, 73 restrictions = Restrictions(keys = listOf(UserManager.DISALLOW_NETWORK_RESET)), 74 ) 75 } 76 77 /** 78 * User pressed confirmation button, for starting reset operation. 79 */ resetnull80 private fun reset(coroutineScope: CoroutineScope) { 81 // User confirm the reset operation 82 featureFactory.metricsFeatureProvider 83 .action(mContext, SettingsEnums.RESET_BLUETOOTH_WIFI_CONFIRM, true) 84 85 // Run reset in background thread 86 coroutineScope.launch { 87 try { 88 withContext(Dispatchers.Default) { 89 resetOperation().run() 90 } 91 } catch (e: Exception) { 92 Log.e(TAG, "Exception during reset", e) 93 return@launch 94 } 95 Toast.makeText( 96 mContext, 97 R.string.reset_bluetooth_wifi_complete_toast, 98 Toast.LENGTH_SHORT, 99 ).show() 100 } 101 } 102 103 @VisibleForTesting resetOperationnull104 fun resetOperation(): Runnable = if (SubscriptionUtil.isSimHardwareVisible(mContext)) { 105 ResetNetworkRequest( 106 ResetNetworkRequest.RESET_WIFI_MANAGER or 107 ResetNetworkRequest.RESET_WIFI_P2P_MANAGER or 108 ResetNetworkRequest.RESET_BLUETOOTH_MANAGER 109 ) 110 .toResetNetworkOperationBuilder(mContext, Looper.getMainLooper()) 111 } else { // For device without SIMs visible to the user 112 ResetNetworkRequest( 113 ResetNetworkRequest.RESET_CONNECTIVITY_MANAGER or 114 ResetNetworkRequest.RESET_VPN_MANAGER or 115 ResetNetworkRequest.RESET_WIFI_MANAGER or 116 ResetNetworkRequest.RESET_WIFI_P2P_MANAGER or 117 ResetNetworkRequest.RESET_BLUETOOTH_MANAGER 118 ) 119 .toResetNetworkOperationBuilder(mContext, Looper.getMainLooper()) 120 .resetTelephonyAndNetworkPolicyManager(ResetNetworkRequest.ALL_SUBSCRIPTION_ID) 121 }.build() 122 123 private companion object { 124 private const val TAG = "BluetoothWiFiResetPref" 125 } 126 } 127