Snap for 12765415 from 6c0260c0ec to 25Q1-release

Change-Id: Ia2d341cf854f697972a42750620a6cc18b7648eb
This commit is contained in:
Android Build Coastguard Worker
2024-12-07 23:19:14 +00:00
7 changed files with 263 additions and 7 deletions

View File

@@ -28,8 +28,7 @@
android:title="@string/wifi_hotspot_checkbox_text"
android:summary="@string/wifi_hotspot_off_subtext"
android:fragment="com.android.settings.wifi.tether.WifiTetherSettings"
settings:allowDividerAbove="true"
settings:maxLines="2"/>
settings:allowDividerAbove="true"/>
<com.android.settingslib.RestrictedSwitchPreference
android:key="usb_tether_settings"

View File

@@ -18,6 +18,7 @@ package com.android.settings.fuelgauge;
import android.content.Context;
import android.text.TextUtils;
import android.text.method.LinkMovementMethod;
import android.util.AttributeSet;
import android.widget.TextView;
@@ -44,6 +45,7 @@ public class BatteryHeaderTextPreference extends Preference implements GroupSect
public void onBindViewHolder(PreferenceViewHolder view) {
final TextView textView = (TextView) view.findViewById(R.id.text);
textView.setText(mText);
textView.setMovementMethod(LinkMovementMethod.getInstance());
if (!TextUtils.isEmpty(mContentDescription)) {
textView.setContentDescription(mContentDescription);
}

View File

@@ -22,6 +22,7 @@ import com.android.settings.PreferenceRestrictionMixin
import com.android.settings.R
import com.android.settings.flags.Flags
import com.android.settings.network.TetherPreferenceController
import com.android.settings.wifi.tether.WifiHotspotSwitchPreference
import com.android.settingslib.TetherUtil
import com.android.settingslib.Utils
import com.android.settingslib.metadata.PreferenceAvailabilityProvider
@@ -63,7 +64,9 @@ class TetherScreen :
override fun fragmentClass() = TetherSettings::class.java
override fun getPreferenceHierarchy(context: Context) = preferenceHierarchy(this) {}
override fun getPreferenceHierarchy(context: Context) = preferenceHierarchy(this) {
+WifiHotspotSwitchPreference(context)
}
companion object {
const val KEY = "tether_settings"

View File

@@ -205,7 +205,9 @@ public class TetherSettings extends RestrictedDashboardFragment
getPreferenceScreen().removePreference(mUsbTether);
}
mWifiTetherPreferenceController.displayPreference(getPreferenceScreen());
if (!isCatalystEnabled() && mWifiTetherPreferenceController != null) {
mWifiTetherPreferenceController.displayPreference(getPreferenceScreen());
}
if (!isCatalystEnabled()) {
if (!bluetoothAvailable) {
@@ -228,8 +230,10 @@ public class TetherSettings extends RestrictedDashboardFragment
@VisibleForTesting
void setupViewModel() {
TetheringManagerModel model = new ViewModelProvider(this).get(TetheringManagerModel.class);
mWifiTetherPreferenceController =
new WifiTetherPreferenceController(getContext(), getSettingsLifecycle(), model);
if (!isCatalystEnabled()) {
mWifiTetherPreferenceController =
new WifiTetherPreferenceController(getContext(), getSettingsLifecycle(), model);
}
mTm = model.getTetheringManager();
model.getTetheredInterfaces().observe(this, this::onTetheredInterfacesChanged);
}
@@ -266,7 +270,9 @@ public class TetherSettings extends RestrictedDashboardFragment
@Override
public void onDataSaverChanged(boolean isDataSaving) {
mDataSaverEnabled = isDataSaving;
mWifiTetherPreferenceController.setDataSaverEnabled(mDataSaverEnabled);
if (!isCatalystEnabled()) {
mWifiTetherPreferenceController.setDataSaverEnabled(mDataSaverEnabled);
}
mUsbTether.setEnabled(!mDataSaverEnabled);
if (!isCatalystEnabled()) {
mBluetoothTether.setEnabled(!mDataSaverEnabled);

View File

@@ -0,0 +1,241 @@
/*
* Copyright (C) 2024 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.wifi.tether
import android.app.settings.SettingsEnums
import android.content.Context
import android.content.Intent
import android.net.TetheringManager
import android.net.wifi.WifiClient
import android.net.wifi.WifiManager
import android.os.UserManager
import android.text.BidiFormatter
import android.util.Log
import androidx.preference.Preference
import com.android.settings.PreferenceRestrictionMixin
import com.android.settings.R
import com.android.settings.Utils
import com.android.settings.core.SubSettingLauncher
import com.android.settings.datausage.DataSaverBackend
import com.android.settings.wifi.WifiUtils.canShowWifiHotspot
import com.android.settingslib.PrimarySwitchPreference
import com.android.settingslib.TetherUtil
import com.android.settingslib.datastore.AbstractKeyedDataObservable
import com.android.settingslib.datastore.DataChangeReason
import com.android.settingslib.datastore.HandlerExecutor
import com.android.settingslib.datastore.KeyValueStore
import com.android.settingslib.metadata.PreferenceAvailabilityProvider
import com.android.settingslib.metadata.PreferenceLifecycleContext
import com.android.settingslib.metadata.PreferenceLifecycleProvider
import com.android.settingslib.metadata.PreferenceMetadata
import com.android.settingslib.metadata.PreferenceSummaryProvider
import com.android.settingslib.metadata.ReadWritePermit
import com.android.settingslib.metadata.SensitivityLevel
import com.android.settingslib.metadata.SwitchPreference
import com.android.settingslib.preference.PreferenceBinding
import com.android.settingslib.wifi.WifiUtils.Companion.getWifiTetherSummaryForConnectedDevices
// LINT.IfChange
@Deprecated("Deprecated in Java")
@Suppress("MissingPermission", "NewApi", "UNCHECKED_CAST")
class WifiHotspotSwitchPreference(context: Context) :
SwitchPreference(KEY, R.string.wifi_hotspot_checkbox_text),
PreferenceBinding,
PreferenceAvailabilityProvider,
PreferenceSummaryProvider,
PreferenceLifecycleProvider,
PreferenceRestrictionMixin {
private val wifiHotspotStore = WifiHotspotStore(context)
private val dataSaverBackend = DataSaverBackend(context)
private var dataSaverBackendListener: DataSaverBackend.Listener? = null
override fun isAvailable(context: Context) =
canShowWifiHotspot(context) &&
TetherUtil.isTetherAvailable(context) &&
!Utils.isMonkeyRunning()
override fun getSummary(context: Context): CharSequence? =
when (wifiHotspotStore.sapState) {
WifiManager.WIFI_AP_STATE_ENABLING -> context.getString(R.string.wifi_tether_starting)
WifiManager.WIFI_AP_STATE_ENABLED ->
when (wifiHotspotStore.sapClientsSize) {
null ->
context.getString(
R.string.wifi_tether_enabled_subtext,
BidiFormatter.getInstance()
.unicodeWrap(context.getSoftApConfiguration()?.ssid),
)
else ->
getWifiTetherSummaryForConnectedDevices(
context,
wifiHotspotStore.sapClientsSize!!,
)
}
WifiManager.WIFI_AP_STATE_DISABLING -> context.getString(R.string.wifi_tether_stopping)
WifiManager.WIFI_AP_STATE_DISABLED ->
context.getString(R.string.wifi_hotspot_off_subtext)
else ->
when (wifiHotspotStore.sapFailureReason) {
WifiManager.SAP_START_FAILURE_NO_CHANNEL ->
context.getString(R.string.wifi_sap_no_channel_error)
else -> context.getString(R.string.wifi_error)
}
}
override fun intent(context: Context): Intent? =
SubSettingLauncher(context)
.apply {
setDestination(WifiTetherSettings::class.java.name)
setTitleRes(R.string.wifi_hotspot_checkbox_text)
setSourceMetricsCategory(SettingsEnums.WIFI_TETHER_SETTINGS)
}
.toIntent()
override fun isEnabled(context: Context) =
!dataSaverBackend.isDataSaverEnabled && super<PreferenceRestrictionMixin>.isEnabled(context)
override val restrictionKeys
get() = arrayOf(UserManager.DISALLOW_WIFI_TETHERING)
override fun getReadPermit(context: Context, myUid: Int, callingUid: Int) =
ReadWritePermit.ALLOW
override fun getWritePermit(context: Context, value: Boolean?, myUid: Int, callingUid: Int) =
when {
dataSaverBackend.isDataSaverEnabled -> ReadWritePermit.DISALLOW
else -> ReadWritePermit.ALLOW
}
override val sensitivityLevel
get() = SensitivityLevel.HIGH_SENSITIVITY
override fun createWidget(context: Context) = PrimarySwitchPreference(context)
override fun storage(context: Context): KeyValueStore = wifiHotspotStore
private class WifiHotspotStore(private val context: Context) :
AbstractKeyedDataObservable<String>(), KeyValueStore {
private var wifiTetherSoftApManager: WifiTetherSoftApManager? = null
var sapState: Int = WifiManager.WIFI_AP_STATE_DISABLED
var sapFailureReason: Int? = null
var sapClientsSize: Int? = null
override fun contains(key: String) =
key == KEY && context.wifiManager != null && context.tetheringManager != null
override fun <T : Any> getValue(key: String, valueType: Class<T>): T? {
val wifiApState = context.wifiManager?.wifiApState
val value =
wifiApState == WifiManager.WIFI_AP_STATE_ENABLING ||
wifiApState == WifiManager.WIFI_AP_STATE_ENABLED
return value as T?
}
override fun <T : Any> setValue(key: String, valueType: Class<T>, value: T?) {
if (value !is Boolean) return
context.tetheringManager?.let {
if (value) {
val startTetheringCallback =
object : TetheringManager.StartTetheringCallback {
override fun onTetheringStarted() {
Log.d(TAG, "onTetheringStarted()")
}
override fun onTetheringFailed(error: Int) {
Log.e(TAG, "onTetheringFailed(),error=$error")
}
}
it.startTethering(
TetheringManager.TETHERING_WIFI,
HandlerExecutor.main,
startTetheringCallback,
)
} else {
it.stopTethering(TetheringManager.TETHERING_WIFI)
}
}
}
override fun onFirstObserverAdded() {
val wifiSoftApCallback =
object : WifiTetherSoftApManager.WifiTetherSoftApCallback {
override fun onStateChanged(state: Int, failureReason: Int) {
Log.d(TAG, "onStateChanged(),state=$state,failureReason=$failureReason")
sapState = state
sapFailureReason = failureReason
if (state == WifiManager.WIFI_AP_STATE_DISABLED) sapClientsSize = null
notifyChange(KEY, DataChangeReason.UPDATE)
}
override fun onConnectedClientsChanged(clients: List<WifiClient>?) {
sapClientsSize = clients?.size ?: 0
Log.d(TAG, "onConnectedClientsChanged(),sapClientsSize=$sapClientsSize")
notifyChange(KEY, DataChangeReason.UPDATE)
}
}
wifiTetherSoftApManager =
WifiTetherSoftApManager(context.wifiManager, wifiSoftApCallback)
wifiTetherSoftApManager?.registerSoftApCallback()
}
override fun onLastObserverRemoved() {
wifiTetherSoftApManager?.unRegisterSoftApCallback()
}
}
override fun bind(preference: Preference, metadata: PreferenceMetadata) {
super.bind(preference, metadata)
(preference as PrimarySwitchPreference).apply {
isChecked = preferenceDataStore!!.getBoolean(key, false)
}
}
override fun onStart(context: PreferenceLifecycleContext) {
val listener =
DataSaverBackend.Listener { isDataSaving: Boolean ->
context.findPreference<PrimarySwitchPreference>(KEY)?.isSwitchEnabled =
!isDataSaving
context.notifyPreferenceChange(KEY)
}
dataSaverBackendListener = listener
dataSaverBackend.addListener(listener)
}
override fun onStop(context: PreferenceLifecycleContext) {
dataSaverBackendListener?.let {
dataSaverBackend.remListener(it)
dataSaverBackendListener = null
}
}
companion object {
const val TAG = "WifiHotspotSwitchPreference"
const val KEY = "wifi_tether"
private val Context.wifiManager: WifiManager?
get() = applicationContext.getSystemService(WifiManager::class.java)
private fun Context.getSoftApConfiguration() = wifiManager?.softApConfiguration
private val Context.tetheringManager: TetheringManager?
get() = applicationContext.getSystemService(TetheringManager::class.java)
}
}
// LINT.ThenChange(WifiTetherPreferenceController.java)

View File

@@ -48,6 +48,7 @@ import com.android.settingslib.wifi.WifiUtils;
import java.util.List;
// LINT.IfChange
public class WifiTetherPreferenceController extends AbstractPreferenceController
implements PreferenceControllerMixin, LifecycleObserver, OnStart, OnStop,
SwitchWidgetController.OnSwitchChangeListener {
@@ -251,3 +252,4 @@ public class WifiTetherPreferenceController extends AbstractPreferenceController
return true;
}
}
// LINT.ThenChange(WifiHotspotSwitchPreference.kt)

View File

@@ -40,6 +40,9 @@ class TetherScreenTest : CatalystScreenTestCase() {
override val flagName: String
get() = Flags.FLAG_CATALYST_TETHER_SETTINGS
// TODO: Remove override (See b/368359963#comment7)
override fun migration() {}
@Before
fun setUp() {
ShadowConnectivityManager.getShadow().setTetheringSupported(true)