Merge "Remove flag, use new api for auto on in settings." into main

This commit is contained in:
Chelsea Hao
2024-03-21 13:09:03 +00:00
committed by Android (Google) Code Review
3 changed files with 83 additions and 94 deletions

View File

@@ -16,11 +16,8 @@
package com.android.settings.bluetooth; package com.android.settings.bluetooth;
import android.bluetooth.BluetoothAdapter;
import android.content.Context; import android.content.Context;
import android.database.ContentObserver;
import android.os.Handler;
import android.os.UserHandle;
import android.provider.Settings;
import android.util.Log; import android.util.Log;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
@@ -30,27 +27,33 @@ import androidx.preference.PreferenceScreen;
import androidx.preference.TwoStatePreference; import androidx.preference.TwoStatePreference;
import com.android.settings.core.TogglePreferenceController; import com.android.settings.core.TogglePreferenceController;
import com.android.settingslib.bluetooth.BluetoothCallback;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.core.lifecycle.LifecycleObserver; import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnStart; import com.android.settingslib.core.lifecycle.events.OnStart;
import com.android.settingslib.core.lifecycle.events.OnStop; import com.android.settingslib.core.lifecycle.events.OnStop;
import com.android.settingslib.flags.Flags;
import com.android.settingslib.utils.ThreadUtils; import com.android.settingslib.utils.ThreadUtils;
public class BluetoothAutoOnPreferenceController extends TogglePreferenceController public class BluetoothAutoOnPreferenceController extends TogglePreferenceController
implements LifecycleObserver, OnStart, OnStop { implements BluetoothCallback, LifecycleObserver, OnStart, OnStop {
private static final String TAG = "BluetoothAutoOnPreferenceController"; private static final String TAG = "BluetoothAutoOnPrefCtlr";
@VisibleForTesting static final String PREF_KEY = "bluetooth_auto_on_settings_toggle"; @VisibleForTesting static final String PREF_KEY = "bluetooth_auto_on_settings_toggle";
static final String SETTING_NAME = "bluetooth_automatic_turn_on"; @VisibleForTesting BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
static final int UNSET = -1; private final LocalBluetoothManager mLocalBluetoothManager = Utils.getLocalBtManager(mContext);
@VisibleForTesting static final int ENABLED = 1; private boolean mAutoOnValue = false;
@VisibleForTesting static final int DISABLED = 0; @Nullable private TwoStatePreference mPreference;
private final ContentObserver mContentObserver =
new ContentObserver(new Handler(/* async= */ true)) { public BluetoothAutoOnPreferenceController(
@NonNull Context context, @NonNull String preferenceKey) {
super(context, preferenceKey);
}
@Override @Override
public void onChange(boolean selfChange) { public void onAutoOnStateChanged(int state) {
var unused = var unused =
ThreadUtils.postOnBackgroundThread( ThreadUtils.postOnBackgroundThread(
() -> { () -> {
Log.i(TAG, "onAutoOnStateChanged() state: " + state);
updateValue(); updateValue();
mContext.getMainExecutor() mContext.getMainExecutor()
.execute( .execute(
@@ -61,36 +64,39 @@ public class BluetoothAutoOnPreferenceController extends TogglePreferenceControl
}); });
}); });
} }
};
private int mAutoOnValue = UNSET;
@Nullable private TwoStatePreference mPreference;
public BluetoothAutoOnPreferenceController(
@NonNull Context context, @NonNull String preferenceKey) {
super(context, preferenceKey);
}
@Override @Override
public void onStart() { public void onStart() {
mContext.getContentResolver() if (mLocalBluetoothManager == null) {
.registerContentObserver( return;
Settings.Secure.getUriFor(SETTING_NAME), }
/* notifyForDescendants= */ false, mLocalBluetoothManager.getEventManager().registerCallback(this);
mContentObserver);
} }
@Override @Override
public void onStop() { public void onStop() {
mContext.getContentResolver().unregisterContentObserver(mContentObserver); if (mLocalBluetoothManager == null) {
return;
}
mLocalBluetoothManager.getEventManager().unregisterCallback(this);
} }
@Override @Override
public int getAvailabilityStatus() { public int getAvailabilityStatus() {
if (!Flags.bluetoothQsTileDialogAutoOnToggle()) { if (mBluetoothAdapter == null) {
return UNSUPPORTED_ON_DEVICE;
}
try {
boolean isSupported = mBluetoothAdapter.isAutoOnSupported();
Log.i(TAG, "getAvailabilityStatus() isSupported: " + isSupported);
if (isSupported) {
var unused = ThreadUtils.postOnBackgroundThread(this::updateValue);
}
return isSupported ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
} catch (Exception e) {
// Server could throw TimeoutException, InterruptedException or ExecutionException
return UNSUPPORTED_ON_DEVICE; return UNSUPPORTED_ON_DEVICE;
} }
updateValue();
return mAutoOnValue != UNSET ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
} }
@Override @Override
@@ -106,26 +112,20 @@ public class BluetoothAutoOnPreferenceController extends TogglePreferenceControl
@Override @Override
public boolean isChecked() { public boolean isChecked() {
return mAutoOnValue == ENABLED; return mAutoOnValue;
} }
@Override @Override
public boolean setChecked(boolean isChecked) { public boolean setChecked(boolean isChecked) {
if (getAvailabilityStatus() != AVAILABLE) {
Log.w(TAG, "Trying to set toggle value while feature not available.");
return false;
}
var unused = var unused =
ThreadUtils.postOnBackgroundThread( ThreadUtils.postOnBackgroundThread(
() -> { () -> {
boolean updated = try {
Settings.Secure.putIntForUser( mBluetoothAdapter.setAutoOnEnabled(isChecked);
mContext.getContentResolver(), } catch (Exception e) {
SETTING_NAME, // Server could throw IllegalStateException, TimeoutException,
isChecked ? ENABLED : DISABLED, // InterruptedException or ExecutionException
UserHandle.myUserId()); Log.e(TAG, "Error calling setAutoOnEnabled()", e);
if (updated) {
updateValue();
} }
}); });
return true; return true;
@@ -137,8 +137,14 @@ public class BluetoothAutoOnPreferenceController extends TogglePreferenceControl
} }
private void updateValue() { private void updateValue() {
mAutoOnValue = if (mBluetoothAdapter == null) {
Settings.Secure.getIntForUser( return;
mContext.getContentResolver(), SETTING_NAME, UNSET, UserHandle.myUserId()); }
try {
mAutoOnValue = mBluetoothAdapter.isAutoOnEnabled();
} catch (Exception e) {
// Server could throw TimeoutException, InterruptedException or ExecutionException
Log.e(TAG, "Error calling isAutoOnEnabled()", e);
}
} }
} }

View File

@@ -15,13 +15,10 @@
*/ */
package com.android.settings.bluetooth; package com.android.settings.bluetooth;
import static com.android.settings.bluetooth.BluetoothAutoOnPreferenceController.SETTING_NAME;
import static com.android.settings.bluetooth.BluetoothAutoOnPreferenceController.UNSET;
import android.app.settings.SettingsEnums; import android.app.settings.SettingsEnums;
import android.bluetooth.BluetoothAdapter;
import android.content.Context; import android.content.Context;
import android.os.UserHandle; import android.util.Log;
import android.provider.Settings;
import android.view.View; import android.view.View;
import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting;
@@ -34,7 +31,6 @@ import com.android.settings.widget.SwitchWidgetController;
import com.android.settingslib.core.lifecycle.LifecycleObserver; import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnStart; import com.android.settingslib.core.lifecycle.events.OnStart;
import com.android.settingslib.core.lifecycle.events.OnStop; import com.android.settingslib.core.lifecycle.events.OnStop;
import com.android.settingslib.flags.Flags;
import com.android.settingslib.widget.FooterPreference; import com.android.settingslib.widget.FooterPreference;
/** /**
@@ -47,11 +43,13 @@ public class BluetoothSwitchPreferenceController
OnStop, OnStop,
SwitchWidgetController.OnSwitchChangeListener, SwitchWidgetController.OnSwitchChangeListener,
View.OnClickListener { View.OnClickListener {
private static final String TAG = "BluetoothSwitchPrefCtrl";
private BluetoothEnabler mBluetoothEnabler; private BluetoothEnabler mBluetoothEnabler;
private RestrictionUtils mRestrictionUtils; private RestrictionUtils mRestrictionUtils;
private SwitchWidgetController mSwitch; private SwitchWidgetController mSwitch;
private Context mContext; private Context mContext;
private BluetoothAdapter mBluetoothAdapter;
private FooterPreference mFooterPreference; private FooterPreference mFooterPreference;
private boolean mIsAlwaysDiscoverable; private boolean mIsAlwaysDiscoverable;
@@ -87,6 +85,7 @@ public class BluetoothSwitchPreferenceController
mRestrictionUtils); mRestrictionUtils);
mBluetoothEnabler.setToggleCallback(this); mBluetoothEnabler.setToggleCallback(this);
mAlwaysDiscoverable = new AlwaysDiscoverable(context); mAlwaysDiscoverable = new AlwaysDiscoverable(context);
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
} }
@Override @Override
@@ -157,11 +156,15 @@ public class BluetoothSwitchPreferenceController
} }
private boolean isAutoOnFeatureAvailable() { private boolean isAutoOnFeatureAvailable() {
if (!Flags.bluetoothQsTileDialogAutoOnToggle()) { if (mBluetoothAdapter == null) {
return false;
}
try {
return mBluetoothAdapter.isAutoOnSupported();
} catch (Exception e) {
// Server could throw TimeoutException, InterruptedException or ExecutionException
Log.e(TAG, "Error calling isAutoOnFeatureAvailable()", e);
return false; return false;
} }
return Settings.Secure.getIntForUser(
mContext.getContentResolver(), SETTING_NAME, UNSET, UserHandle.myUserId())
!= UNSET;
} }
} }

View File

@@ -16,82 +16,62 @@
package com.android.settings.bluetooth; package com.android.settings.bluetooth;
import static com.android.settings.bluetooth.BluetoothAutoOnPreferenceController.DISABLED;
import static com.android.settings.bluetooth.BluetoothAutoOnPreferenceController.ENABLED;
import static com.android.settings.bluetooth.BluetoothAutoOnPreferenceController.PREF_KEY; import static com.android.settings.bluetooth.BluetoothAutoOnPreferenceController.PREF_KEY;
import static com.android.settings.bluetooth.BluetoothAutoOnPreferenceController.SETTING_NAME;
import static com.android.settings.bluetooth.BluetoothAutoOnPreferenceController.UNSET;
import static com.android.settings.core.BasePreferenceController.AVAILABLE; import static com.android.settings.core.BasePreferenceController.AVAILABLE;
import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE; import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE;
import static com.android.settingslib.flags.Flags.FLAG_BLUETOOTH_QS_TILE_DIALOG_AUTO_ON_TOGGLE;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy; import static org.mockito.Mockito.spy;
import android.bluetooth.BluetoothAdapter;
import android.content.ContentResolver; import android.content.ContentResolver;
import android.content.Context; import android.content.Context;
import android.platform.test.flag.junit.SetFlagsRule;
import android.provider.Settings;
import androidx.test.core.app.ApplicationProvider; import androidx.test.core.app.ApplicationProvider;
import org.junit.Before; import org.junit.Before;
import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner; import org.robolectric.RobolectricTestRunner;
@RunWith(RobolectricTestRunner.class) @RunWith(RobolectricTestRunner.class)
public class BluetoothAutoOnPreferenceControllerTest { public class BluetoothAutoOnPreferenceControllerTest {
@Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
private Context mContext; private Context mContext;
private ContentResolver mContentResolver; private ContentResolver mContentResolver;
private BluetoothAutoOnPreferenceController mController; private BluetoothAutoOnPreferenceController mController;
private BluetoothAdapter mBluetoothAdapter;
@Before @Before
public void setUp() { public void setUp() {
mSetFlagsRule.enableFlags(FLAG_BLUETOOTH_QS_TILE_DIALOG_AUTO_ON_TOGGLE);
mContext = spy(ApplicationProvider.getApplicationContext()); mContext = spy(ApplicationProvider.getApplicationContext());
mContentResolver = mContext.getContentResolver(); mContentResolver = mContext.getContentResolver();
mController = new BluetoothAutoOnPreferenceController(mContext, PREF_KEY); mController = new BluetoothAutoOnPreferenceController(mContext, PREF_KEY);
mBluetoothAdapter = spy(BluetoothAdapter.getDefaultAdapter());
mController.mBluetoothAdapter = mBluetoothAdapter;
} }
@Test @Test
public void getAvailability_valueUnset_returnUnsupported() { public void getAvailability_valueUnset_returnUnsupported() {
Settings.Secure.putInt(mContentResolver, SETTING_NAME, UNSET); doReturn(false).when(mBluetoothAdapter).isAutoOnSupported();
assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE); assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
} }
@Test @Test
public void getAvailability_valueSet_returnAvailable() { public void getAvailability_valueSet_returnAvailable() {
Settings.Secure.putInt(mContentResolver, SETTING_NAME, DISABLED); doReturn(true).when(mBluetoothAdapter).isAutoOnSupported();
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE); assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
} }
@Test @Test
public void isChecked_valueEnabled_returnTrue() { public void isChecked_valueEnabled_returnTrue() {
Settings.Secure.putInt(mContentResolver, SETTING_NAME, ENABLED); doReturn(true).when(mBluetoothAdapter).isAutoOnSupported();
doReturn(true).when(mBluetoothAdapter).isAutoOnEnabled();
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE); assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
assertThat(mController.isChecked()).isEqualTo(true); assertThat(mController.isChecked()).isEqualTo(true);
} }
@Test
public void setChecked_returnTrue() {
Settings.Secure.putInt(mContentResolver, SETTING_NAME, DISABLED);
mController.setChecked(true);
assertThat(mController.isChecked()).isEqualTo(true);
}
@Test
public void setChecked_returnFalse() {
Settings.Secure.putInt(mContentResolver, SETTING_NAME, ENABLED);
mController.setChecked(false);
assertThat(mController.isChecked()).isEqualTo(false);
}
} }