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:
Matthew Fritze
2018-04-12 16:40:07 -07:00
parent d743f20618
commit 7acd13f3e4
6 changed files with 111 additions and 15 deletions

View File

@@ -54,16 +54,16 @@ public class SliceBroadcastReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
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 */);
switch (action) {
case ACTION_TOGGLE_CHANGED:
handleToggleAction(context, key, isPlatformDefined);
handleToggleAction(context, key, isPlatformSlice);
break;
case ACTION_SLIDER_CHANGED:
int newPosition = intent.getIntExtra(Slice.EXTRA_RANGE_VALUE, -1);
handleSliderAction(context, key, newPosition);
handleSliderAction(context, key, newPosition, isPlatformSlice);
break;
case ACTION_WIFI_CHANGED:
WifiManager wm = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
@@ -95,6 +95,7 @@ public class SliceBroadcastReceiver extends BroadcastReceiver {
if (!controller.isAvailable()) {
Log.w(TAG, "Can't update " + key + " since the setting is unavailable");
updateUri(context, key, isPlatformSlice);
return;
}
// TODO post context.getContentResolver().notifyChanged(uri, null) in the Toggle controller
@@ -107,7 +108,8 @@ public class SliceBroadcastReceiver extends BroadcastReceiver {
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)) {
throw new IllegalArgumentException(
"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);
}
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 int maxSteps = sliderController.getMaxSteps();
if (newPosition < 0 || newPosition > maxSteps) {

View File

@@ -18,17 +18,28 @@
package com.android.settings.slices;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
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 android.app.slice.Slice;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.database.ContentObserver;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.provider.Settings;
import android.provider.SettingsSlicesContract;
import android.util.Pair;
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.SearchFeatureProvider;
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.FakeSliderController;
import com.android.settings.testutils.FakeToggleController;
import com.android.settings.testutils.FakeUnavailablePreferenceController;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import org.junit.After;
@@ -65,7 +77,7 @@ public class SliceBroadcastReceiverTest {
@Before
public void setUp() {
mContext = RuntimeEnvironment.application;
mContext = spy(RuntimeEnvironment.application);
mDb = SlicesDatabaseHelper.getInstance(mContext).getWritableDatabase();
mReceiver = new SliceBroadcastReceiver();
SlicesDatabaseHelper helper = SlicesDatabaseHelper.getInstance(mContext);
@@ -192,6 +204,77 @@ public class SliceBroadcastReceiverTest {
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) {
insertSpecialCase(fakeControllerName, key);
}

View File

@@ -24,7 +24,6 @@ import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import android.app.PendingIntent;
import android.content.ContentResolver;
import android.content.Context;
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.FakeSliderController;
import com.android.settings.testutils.FakeToggleController;
import com.android.settings.testutils.FakeUnavailablePreferenceController;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.SliceTester;
@@ -324,7 +324,7 @@ public class SliceBuilderUtilsTest {
public void testUnsupportedSlice_validTitleSummary() {
final SliceData data = getDummyData(FakeUnavailablePreferenceController.class,
SliceData.SliceType.SWITCH);
Settings.System.putInt(mContext.getContentResolver(),
Settings.Global.putInt(mContext.getContentResolver(),
FakeUnavailablePreferenceController.AVAILABILITY_KEY,
BasePreferenceController.DISABLED_UNSUPPORTED);
@@ -337,7 +337,7 @@ public class SliceBuilderUtilsTest {
public void testDisabledForUserSlice_validTitleSummary() {
final SliceData data = getDummyData(FakeUnavailablePreferenceController.class,
SliceData.SliceType.SWITCH);
Settings.System.putInt(mContext.getContentResolver(),
Settings.Global.putInt(mContext.getContentResolver(),
FakeUnavailablePreferenceController.AVAILABILITY_KEY,
BasePreferenceController.DISABLED_FOR_USER);
@@ -350,7 +350,7 @@ public class SliceBuilderUtilsTest {
public void testDisabledDependentSettingSlice_validTitleSummary() {
final SliceData data = getDummyData(FakeUnavailablePreferenceController.class,
SliceData.SliceType.INTENT);
Settings.System.putInt(mContext.getContentResolver(),
Settings.Global.putInt(mContext.getContentResolver(),
FakeUnavailablePreferenceController.AVAILABILITY_KEY,
BasePreferenceController.DISABLED_DEPENDENT_SETTING);
@@ -372,7 +372,7 @@ public class SliceBuilderUtilsTest {
public void testUnavailableUnknownSlice_validTitleSummary() {
final SliceData data = getDummyData(FakeUnavailablePreferenceController.class,
SliceData.SliceType.SWITCH);
Settings.System.putInt(mContext.getContentResolver(),
Settings.Global.putInt(mContext.getContentResolver(),
FakeUnavailablePreferenceController.AVAILABILITY_KEY,
BasePreferenceController.UNAVAILABLE_UNKNOWN);

View File

@@ -19,13 +19,14 @@ package com.android.settings.testutils;
import android.content.Context;
import android.provider.Settings;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.core.SliderPreferenceController;
public class FakeSliderController extends SliderPreferenceController {
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 FakeSliderController(Context context, String key) {
@@ -49,6 +50,7 @@ public class FakeSliderController extends SliderPreferenceController {
@Override
public int getAvailabilityStatus() {
return BasePreferenceController.AVAILABLE;
return Settings.Global.getInt(mContext.getContentResolver(),
AVAILABILITY_KEY, AVAILABLE);
}
}

View File

@@ -26,6 +26,8 @@ public class FakeToggleController extends TogglePreferenceController {
private String settingKey = "toggle_key";
public static final String AVAILABILITY_KEY = "fake_toggle_availability_key";
private final int ON = 1;
private final int OFF = 0;
@@ -47,6 +49,7 @@ public class FakeToggleController extends TogglePreferenceController {
@Override
public int getAvailabilityStatus() {
return AVAILABLE;
return Settings.Global.getInt(mContext.getContentResolver(),
AVAILABILITY_KEY, AVAILABLE);
}
}

View File

@@ -1,4 +1,4 @@
package com.android.settings.slices;
package com.android.settings.testutils;
import android.content.Context;
import android.provider.Settings;
@@ -15,7 +15,7 @@ public class FakeUnavailablePreferenceController extends BasePreferenceControlle
@Override
public int getAvailabilityStatus() {
return Settings.System.getInt(mContext.getContentResolver(),
return Settings.Global.getInt(mContext.getContentResolver(),
AVAILABILITY_KEY, 0);
}
}