Update a Slice Uri when unavailable
When a slice becomes unavailable, it should not update the underlying data even if the view has not changed. When we receive a change from an unavailable slice, notifychange on the Uri and do not change the underlying data. Change-Id: I91851ab668e4aece669fd65c14e0dc4ec2edefdf Fixes: 77980406 Test: robotests
This commit is contained in:
@@ -54,16 +54,16 @@ public class SliceBroadcastReceiver extends BroadcastReceiver {
|
|||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
final String action = intent.getAction();
|
final String action = intent.getAction();
|
||||||
final String key = intent.getStringExtra(EXTRA_SLICE_KEY);
|
final String key = intent.getStringExtra(EXTRA_SLICE_KEY);
|
||||||
final boolean isPlatformDefined = intent.getBooleanExtra(EXTRA_SLICE_PLATFORM_DEFINED,
|
final boolean isPlatformSlice = intent.getBooleanExtra(EXTRA_SLICE_PLATFORM_DEFINED,
|
||||||
false /* default */);
|
false /* default */);
|
||||||
|
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case ACTION_TOGGLE_CHANGED:
|
case ACTION_TOGGLE_CHANGED:
|
||||||
handleToggleAction(context, key, isPlatformDefined);
|
handleToggleAction(context, key, isPlatformSlice);
|
||||||
break;
|
break;
|
||||||
case ACTION_SLIDER_CHANGED:
|
case ACTION_SLIDER_CHANGED:
|
||||||
int newPosition = intent.getIntExtra(Slice.EXTRA_RANGE_VALUE, -1);
|
int newPosition = intent.getIntExtra(Slice.EXTRA_RANGE_VALUE, -1);
|
||||||
handleSliderAction(context, key, newPosition);
|
handleSliderAction(context, key, newPosition, isPlatformSlice);
|
||||||
break;
|
break;
|
||||||
case ACTION_WIFI_CHANGED:
|
case ACTION_WIFI_CHANGED:
|
||||||
WifiManager wm = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
|
WifiManager wm = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
|
||||||
@@ -95,6 +95,7 @@ public class SliceBroadcastReceiver extends BroadcastReceiver {
|
|||||||
if (!controller.isAvailable()) {
|
if (!controller.isAvailable()) {
|
||||||
Log.w(TAG, "Can't update " + key + " since the setting is unavailable");
|
Log.w(TAG, "Can't update " + key + " since the setting is unavailable");
|
||||||
updateUri(context, key, isPlatformSlice);
|
updateUri(context, key, isPlatformSlice);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO post context.getContentResolver().notifyChanged(uri, null) in the Toggle controller
|
// TODO post context.getContentResolver().notifyChanged(uri, null) in the Toggle controller
|
||||||
@@ -107,7 +108,8 @@ public class SliceBroadcastReceiver extends BroadcastReceiver {
|
|||||||
updateUri(context, key, isPlatformSlice);
|
updateUri(context, key, isPlatformSlice);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleSliderAction(Context context, String key, int newPosition) {
|
private void handleSliderAction(Context context, String key, int newPosition,
|
||||||
|
boolean isPlatformSlice) {
|
||||||
if (TextUtils.isEmpty(key)) {
|
if (TextUtils.isEmpty(key)) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"No key passed to Intent for slider controller. Use extra: " + EXTRA_SLICE_KEY);
|
"No key passed to Intent for slider controller. Use extra: " + EXTRA_SLICE_KEY);
|
||||||
@@ -123,6 +125,12 @@ public class SliceBroadcastReceiver extends BroadcastReceiver {
|
|||||||
throw new IllegalArgumentException("Slider action passed for a non-slider key: " + key);
|
throw new IllegalArgumentException("Slider action passed for a non-slider key: " + key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!controller.isAvailable()) {
|
||||||
|
Log.w(TAG, "Can't update " + key + " since the setting is unavailable");
|
||||||
|
updateUri(context, key, isPlatformSlice);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
final SliderPreferenceController sliderController = (SliderPreferenceController) controller;
|
final SliderPreferenceController sliderController = (SliderPreferenceController) controller;
|
||||||
final int maxSteps = sliderController.getMaxSteps();
|
final int maxSteps = sliderController.getMaxSteps();
|
||||||
if (newPosition < 0 || newPosition > maxSteps) {
|
if (newPosition < 0 || newPosition > maxSteps) {
|
||||||
|
@@ -18,17 +18,28 @@
|
|||||||
package com.android.settings.slices;
|
package com.android.settings.slices;
|
||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.ArgumentMatchers.eq;
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
|
import static org.mockito.Mockito.doReturn;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.spy;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
import android.app.slice.Slice;
|
import android.app.slice.Slice;
|
||||||
|
import android.content.ContentResolver;
|
||||||
import android.content.ContentValues;
|
import android.content.ContentValues;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.database.ContentObserver;
|
||||||
import android.database.sqlite.SQLiteDatabase;
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.provider.Settings;
|
||||||
|
import android.provider.SettingsSlicesContract;
|
||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
|
|
||||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||||
|
import com.android.settings.core.BasePreferenceController;
|
||||||
import com.android.settings.search.FakeIndexProvider;
|
import com.android.settings.search.FakeIndexProvider;
|
||||||
import com.android.settings.search.SearchFeatureProvider;
|
import com.android.settings.search.SearchFeatureProvider;
|
||||||
import com.android.settings.search.SearchFeatureProviderImpl;
|
import com.android.settings.search.SearchFeatureProviderImpl;
|
||||||
@@ -36,6 +47,7 @@ import com.android.settings.testutils.DatabaseTestUtils;
|
|||||||
import com.android.settings.testutils.FakeFeatureFactory;
|
import com.android.settings.testutils.FakeFeatureFactory;
|
||||||
import com.android.settings.testutils.FakeSliderController;
|
import com.android.settings.testutils.FakeSliderController;
|
||||||
import com.android.settings.testutils.FakeToggleController;
|
import com.android.settings.testutils.FakeToggleController;
|
||||||
|
import com.android.settings.testutils.FakeUnavailablePreferenceController;
|
||||||
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||||
|
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
@@ -65,7 +77,7 @@ public class SliceBroadcastReceiverTest {
|
|||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
mContext = RuntimeEnvironment.application;
|
mContext = spy(RuntimeEnvironment.application);
|
||||||
mDb = SlicesDatabaseHelper.getInstance(mContext).getWritableDatabase();
|
mDb = SlicesDatabaseHelper.getInstance(mContext).getWritableDatabase();
|
||||||
mReceiver = new SliceBroadcastReceiver();
|
mReceiver = new SliceBroadcastReceiver();
|
||||||
SlicesDatabaseHelper helper = SlicesDatabaseHelper.getInstance(mContext);
|
SlicesDatabaseHelper helper = SlicesDatabaseHelper.getInstance(mContext);
|
||||||
@@ -192,6 +204,77 @@ public class SliceBroadcastReceiverTest {
|
|||||||
mReceiver.onReceive(mContext, intent);
|
mReceiver.onReceive(mContext, intent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void toggleUpdate_unavailableUriNotified() {
|
||||||
|
// Monitor the ContentResolver
|
||||||
|
final ContentResolver resolver = spy(mContext.getContentResolver());
|
||||||
|
doReturn(resolver).when(mContext).getContentResolver();
|
||||||
|
|
||||||
|
// Disable Setting
|
||||||
|
Settings.Global.putInt(mContext.getContentResolver(),
|
||||||
|
FakeToggleController.AVAILABILITY_KEY,
|
||||||
|
BasePreferenceController.DISABLED_UNSUPPORTED);
|
||||||
|
|
||||||
|
// Insert Fake Toggle into Database
|
||||||
|
final String key = "key";
|
||||||
|
mSearchFeatureProvider.getSearchIndexableResources().getProviderValues().clear();
|
||||||
|
insertSpecialCase(FakeToggleController.class, key);
|
||||||
|
|
||||||
|
// Turn on toggle setting
|
||||||
|
final FakeToggleController fakeToggleController = new FakeToggleController(mContext, key);
|
||||||
|
fakeToggleController.setChecked(true);
|
||||||
|
|
||||||
|
// Build Action
|
||||||
|
final Intent intent = new Intent(SettingsSliceProvider.ACTION_TOGGLE_CHANGED);
|
||||||
|
intent.putExtra(SettingsSliceProvider.EXTRA_SLICE_KEY, key);
|
||||||
|
|
||||||
|
// Trigger Slice change
|
||||||
|
mReceiver.onReceive(mContext, intent);
|
||||||
|
|
||||||
|
// Check the value is the same and the Uri has been notified.
|
||||||
|
assertThat(fakeToggleController.isChecked()).isTrue();
|
||||||
|
final Uri expectedUri = SliceBuilderUtils.getUri(
|
||||||
|
SettingsSlicesContract.PATH_SETTING_ACTION + "/" + key, false);
|
||||||
|
verify(resolver).notifyChange(eq(expectedUri), eq(null));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void sliderUpdate_unavailableUriNotified() {
|
||||||
|
// Monitor the ContentResolver
|
||||||
|
final ContentResolver resolver = spy(mContext.getContentResolver());
|
||||||
|
doReturn(resolver).when(mContext).getContentResolver();
|
||||||
|
|
||||||
|
// Disable Setting
|
||||||
|
Settings.Global.putInt(mContext.getContentResolver(),
|
||||||
|
FakeSliderController.AVAILABILITY_KEY,
|
||||||
|
BasePreferenceController.DISABLED_UNSUPPORTED);
|
||||||
|
|
||||||
|
// Insert Fake Slider into Database
|
||||||
|
final String key = "key";
|
||||||
|
final int position = FakeSliderController.MAX_STEPS - 1;
|
||||||
|
final int oldPosition = FakeSliderController.MAX_STEPS;
|
||||||
|
mSearchFeatureProvider.getSearchIndexableResources().getProviderValues().clear();
|
||||||
|
insertSpecialCase(FakeSliderController.class, key);
|
||||||
|
|
||||||
|
// Set slider setting
|
||||||
|
final FakeSliderController fakeSliderController = new FakeSliderController(mContext, key);
|
||||||
|
fakeSliderController.setSliderPosition(oldPosition);
|
||||||
|
|
||||||
|
// Build action
|
||||||
|
final Intent intent = new Intent(SettingsSliceProvider.ACTION_SLIDER_CHANGED);
|
||||||
|
intent.putExtra(Slice.EXTRA_RANGE_VALUE, position);
|
||||||
|
intent.putExtra(SettingsSliceProvider.EXTRA_SLICE_KEY, key);
|
||||||
|
|
||||||
|
// Trigger Slice change
|
||||||
|
mReceiver.onReceive(mContext, intent);
|
||||||
|
|
||||||
|
// Check position is the same and the Uri has been notified.
|
||||||
|
assertThat(fakeSliderController.getSliderPosition()).isEqualTo(oldPosition);
|
||||||
|
final Uri expectedUri = SliceBuilderUtils.getUri(
|
||||||
|
SettingsSlicesContract.PATH_SETTING_ACTION + "/" + key, false);
|
||||||
|
verify(resolver).notifyChange(eq(expectedUri), eq(null));
|
||||||
|
}
|
||||||
|
|
||||||
private void insertSpecialCase(String key) {
|
private void insertSpecialCase(String key) {
|
||||||
insertSpecialCase(fakeControllerName, key);
|
insertSpecialCase(fakeControllerName, key);
|
||||||
}
|
}
|
||||||
|
@@ -24,7 +24,6 @@ import static org.mockito.Mockito.doReturn;
|
|||||||
import static org.mockito.Mockito.spy;
|
import static org.mockito.Mockito.spy;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
import android.app.PendingIntent;
|
|
||||||
import android.content.ContentResolver;
|
import android.content.ContentResolver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
@@ -40,6 +39,7 @@ import com.android.settings.core.BasePreferenceController;
|
|||||||
import com.android.settings.testutils.FakeFeatureFactory;
|
import com.android.settings.testutils.FakeFeatureFactory;
|
||||||
import com.android.settings.testutils.FakeSliderController;
|
import com.android.settings.testutils.FakeSliderController;
|
||||||
import com.android.settings.testutils.FakeToggleController;
|
import com.android.settings.testutils.FakeToggleController;
|
||||||
|
import com.android.settings.testutils.FakeUnavailablePreferenceController;
|
||||||
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||||
import com.android.settings.testutils.SliceTester;
|
import com.android.settings.testutils.SliceTester;
|
||||||
|
|
||||||
@@ -324,7 +324,7 @@ public class SliceBuilderUtilsTest {
|
|||||||
public void testUnsupportedSlice_validTitleSummary() {
|
public void testUnsupportedSlice_validTitleSummary() {
|
||||||
final SliceData data = getDummyData(FakeUnavailablePreferenceController.class,
|
final SliceData data = getDummyData(FakeUnavailablePreferenceController.class,
|
||||||
SliceData.SliceType.SWITCH);
|
SliceData.SliceType.SWITCH);
|
||||||
Settings.System.putInt(mContext.getContentResolver(),
|
Settings.Global.putInt(mContext.getContentResolver(),
|
||||||
FakeUnavailablePreferenceController.AVAILABILITY_KEY,
|
FakeUnavailablePreferenceController.AVAILABILITY_KEY,
|
||||||
BasePreferenceController.DISABLED_UNSUPPORTED);
|
BasePreferenceController.DISABLED_UNSUPPORTED);
|
||||||
|
|
||||||
@@ -337,7 +337,7 @@ public class SliceBuilderUtilsTest {
|
|||||||
public void testDisabledForUserSlice_validTitleSummary() {
|
public void testDisabledForUserSlice_validTitleSummary() {
|
||||||
final SliceData data = getDummyData(FakeUnavailablePreferenceController.class,
|
final SliceData data = getDummyData(FakeUnavailablePreferenceController.class,
|
||||||
SliceData.SliceType.SWITCH);
|
SliceData.SliceType.SWITCH);
|
||||||
Settings.System.putInt(mContext.getContentResolver(),
|
Settings.Global.putInt(mContext.getContentResolver(),
|
||||||
FakeUnavailablePreferenceController.AVAILABILITY_KEY,
|
FakeUnavailablePreferenceController.AVAILABILITY_KEY,
|
||||||
BasePreferenceController.DISABLED_FOR_USER);
|
BasePreferenceController.DISABLED_FOR_USER);
|
||||||
|
|
||||||
@@ -350,7 +350,7 @@ public class SliceBuilderUtilsTest {
|
|||||||
public void testDisabledDependentSettingSlice_validTitleSummary() {
|
public void testDisabledDependentSettingSlice_validTitleSummary() {
|
||||||
final SliceData data = getDummyData(FakeUnavailablePreferenceController.class,
|
final SliceData data = getDummyData(FakeUnavailablePreferenceController.class,
|
||||||
SliceData.SliceType.INTENT);
|
SliceData.SliceType.INTENT);
|
||||||
Settings.System.putInt(mContext.getContentResolver(),
|
Settings.Global.putInt(mContext.getContentResolver(),
|
||||||
FakeUnavailablePreferenceController.AVAILABILITY_KEY,
|
FakeUnavailablePreferenceController.AVAILABILITY_KEY,
|
||||||
BasePreferenceController.DISABLED_DEPENDENT_SETTING);
|
BasePreferenceController.DISABLED_DEPENDENT_SETTING);
|
||||||
|
|
||||||
@@ -372,7 +372,7 @@ public class SliceBuilderUtilsTest {
|
|||||||
public void testUnavailableUnknownSlice_validTitleSummary() {
|
public void testUnavailableUnknownSlice_validTitleSummary() {
|
||||||
final SliceData data = getDummyData(FakeUnavailablePreferenceController.class,
|
final SliceData data = getDummyData(FakeUnavailablePreferenceController.class,
|
||||||
SliceData.SliceType.SWITCH);
|
SliceData.SliceType.SWITCH);
|
||||||
Settings.System.putInt(mContext.getContentResolver(),
|
Settings.Global.putInt(mContext.getContentResolver(),
|
||||||
FakeUnavailablePreferenceController.AVAILABILITY_KEY,
|
FakeUnavailablePreferenceController.AVAILABILITY_KEY,
|
||||||
BasePreferenceController.UNAVAILABLE_UNKNOWN);
|
BasePreferenceController.UNAVAILABLE_UNKNOWN);
|
||||||
|
|
||||||
|
@@ -19,13 +19,14 @@ package com.android.settings.testutils;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
|
|
||||||
import com.android.settings.core.BasePreferenceController;
|
|
||||||
import com.android.settings.core.SliderPreferenceController;
|
import com.android.settings.core.SliderPreferenceController;
|
||||||
|
|
||||||
public class FakeSliderController extends SliderPreferenceController {
|
public class FakeSliderController extends SliderPreferenceController {
|
||||||
|
|
||||||
private final String settingKey = "fake_slider_key";
|
private final String settingKey = "fake_slider_key";
|
||||||
|
|
||||||
|
public static final String AVAILABILITY_KEY = "fake_slider_availability_key";
|
||||||
|
|
||||||
public static final int MAX_STEPS = 9;
|
public static final int MAX_STEPS = 9;
|
||||||
|
|
||||||
public FakeSliderController(Context context, String key) {
|
public FakeSliderController(Context context, String key) {
|
||||||
@@ -49,6 +50,7 @@ public class FakeSliderController extends SliderPreferenceController {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getAvailabilityStatus() {
|
public int getAvailabilityStatus() {
|
||||||
return BasePreferenceController.AVAILABLE;
|
return Settings.Global.getInt(mContext.getContentResolver(),
|
||||||
|
AVAILABILITY_KEY, AVAILABLE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -26,6 +26,8 @@ public class FakeToggleController extends TogglePreferenceController {
|
|||||||
|
|
||||||
private String settingKey = "toggle_key";
|
private String settingKey = "toggle_key";
|
||||||
|
|
||||||
|
public static final String AVAILABILITY_KEY = "fake_toggle_availability_key";
|
||||||
|
|
||||||
private final int ON = 1;
|
private final int ON = 1;
|
||||||
private final int OFF = 0;
|
private final int OFF = 0;
|
||||||
|
|
||||||
@@ -47,6 +49,7 @@ public class FakeToggleController extends TogglePreferenceController {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getAvailabilityStatus() {
|
public int getAvailabilityStatus() {
|
||||||
return AVAILABLE;
|
return Settings.Global.getInt(mContext.getContentResolver(),
|
||||||
|
AVAILABILITY_KEY, AVAILABLE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
package com.android.settings.slices;
|
package com.android.settings.testutils;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
@@ -15,7 +15,7 @@ public class FakeUnavailablePreferenceController extends BasePreferenceControlle
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getAvailabilityStatus() {
|
public int getAvailabilityStatus() {
|
||||||
return Settings.System.getInt(mContext.getContentResolver(),
|
return Settings.Global.getInt(mContext.getContentResolver(),
|
||||||
AVAILABILITY_KEY, 0);
|
AVAILABILITY_KEY, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
Reference in New Issue
Block a user