OSDN Git Service

Create special case mobile data slice
authorMatthew Fritze <mfritze@google.com>
Thu, 10 Jan 2019 18:02:49 +0000 (10:02 -0800)
committerMatthew Fritze <mfritze@google.com>
Fri, 8 Feb 2019 21:13:28 +0000 (13:13 -0800)
Build the special case mobile data slice for general use,
and for the Internet Connectivity Panel. The Slice controls
the default data subscription, and links to the subscriptions
page.

Bug: 117804089
Fixse: 119411534
Test: robotests & test app.

Change-Id: I31b524a8fe3182a244d940848090e97250632f39

13 files changed:
AndroidManifest.xml
src/com/android/settings/network/telephony/MobileDataPreferenceController.java
src/com/android/settings/network/telephony/MobileDataSlice.java [new file with mode: 0644]
src/com/android/settings/panel/InternetConnectivityPanel.java
src/com/android/settings/slices/CustomSliceManager.java
src/com/android/settings/slices/CustomSliceRegistry.java
src/com/android/settings/slices/CustomSliceable.java
src/com/android/settings/slices/SettingsSliceProvider.java
src/com/android/settings/slices/SliceBackgroundWorker.java
src/com/android/settings/wifi/slice/WifiSlice.java
tests/robotests/src/com/android/settings/network/telephony/MobileDataSliceTest.java [new file with mode: 0644]
tests/robotests/src/com/android/settings/panel/InternetConnectivityPanelTest.java
tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java

index 90aa55f..829425c 100644 (file)
             android:label="@string/settings_panel_title"
             android:theme="@style/Theme.BottomDialog"
             android:excludeFromRecents="true"
-            android:launchMode="singleTask"
+            android:launchMode="singleTop"
             android:exported="true">
                  <intent-filter>
                      <action android:name="android.settings.panel.action.INTERNET_CONNECTIVITY" />
index 47822b6..bdcc727 100644 (file)
@@ -122,6 +122,14 @@ public class MobileDataPreferenceController extends TogglePreferenceController
                 && mSubId == SubscriptionManager.getDefaultDataSubscriptionId();
     }
 
+    public static Uri getObservableUri(int subId) {
+        Uri uri = Settings.Global.getUriFor(Settings.Global.MOBILE_DATA);
+        if (TelephonyManager.getDefault().getSimCount() != 1) {
+            uri = Settings.Global.getUriFor(Settings.Global.MOBILE_DATA + subId);
+        }
+        return uri;
+    }
+
     public void init(FragmentManager fragmentManager, int subId) {
         mFragmentManager = fragmentManager;
         mSubId = subId;
@@ -172,10 +180,7 @@ public class MobileDataPreferenceController extends TogglePreferenceController
         }
 
         public void register(Context context, int subId) {
-            Uri uri = Settings.Global.getUriFor(Settings.Global.MOBILE_DATA);
-            if (TelephonyManager.getDefault().getSimCount() != 1) {
-                uri = Settings.Global.getUriFor(Settings.Global.MOBILE_DATA + subId);
-            }
+            final Uri uri = getObservableUri(subId);
             context.getContentResolver().registerContentObserver(uri, false, this);
 
         }
diff --git a/src/com/android/settings/network/telephony/MobileDataSlice.java b/src/com/android/settings/network/telephony/MobileDataSlice.java
new file mode 100644 (file)
index 0000000..6efd8c3
--- /dev/null
@@ -0,0 +1,249 @@
+/*
+ * Copyright (C) 2019 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.network.telephony;
+
+import static android.app.slice.Slice.EXTRA_TOGGLE_STATE;
+
+import android.annotation.ColorInt;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.Looper;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+
+import androidx.core.graphics.drawable.IconCompat;
+import androidx.slice.Slice;
+import androidx.slice.builders.ListBuilder;
+import androidx.slice.builders.SliceAction;
+
+import com.android.settings.R;
+import com.android.settings.Utils;
+import com.android.settings.network.AirplaneModePreferenceController;
+import com.android.settings.slices.CustomSliceRegistry;
+import com.android.settings.slices.CustomSliceable;
+import com.android.settings.slices.SliceBackgroundWorker;
+
+import com.google.common.annotations.VisibleForTesting;
+
+import java.io.IOException;
+
+/**
+ * Custom {@link Slice} for Mobile Data.
+ * <p>
+ *     We make a custom slice instead of using {@link MobileDataPreferenceController} because the
+ *     pref controller is generalized across any carrier, and thus does not control a specific
+ *     subscription. We attempt to reuse any telephony-specific code from the preference controller.
+ *
+ * </p>
+ *
+ */
+public class MobileDataSlice implements CustomSliceable {
+
+    private final Context mContext;
+    private final SubscriptionManager mSubscriptionManager;
+    private final TelephonyManager mTelephonyManager;
+
+    public MobileDataSlice(Context context) {
+        mContext = context;
+        mSubscriptionManager = mContext.getSystemService(SubscriptionManager.class);
+        mTelephonyManager = mContext.getSystemService(TelephonyManager.class);
+    }
+
+    @Override
+    public Slice getSlice() {
+        final IconCompat icon = IconCompat.createWithResource(mContext,
+                R.drawable.ic_network_cell);
+        final String title = mContext.getText(R.string.mobile_data_settings_title).toString();
+        final CharSequence summary = getSummary();
+        @ColorInt final int color = Utils.getColorAccentDefaultColor(mContext);
+        final PendingIntent toggleAction = getBroadcastIntent(mContext);
+        final PendingIntent primaryAction = getPrimaryAction();
+        final SliceAction primarySliceAction = SliceAction.createDeeplink(primaryAction, icon,
+                ListBuilder.ICON_IMAGE, title);
+        final SliceAction toggleSliceAction = SliceAction.createToggle(toggleAction,
+                null /* actionTitle */, isMobileDataEnabled());
+
+        final ListBuilder listBuilder = new ListBuilder(mContext, getUri(),
+                ListBuilder.INFINITY)
+                .setAccentColor(color)
+                .addRow(new ListBuilder.RowBuilder()
+                        .setTitle(title)
+                        .setSubtitle(summary)
+                        .addEndItem(toggleSliceAction)
+                        .setPrimaryAction(primarySliceAction));
+        return listBuilder.build();
+    }
+
+    @Override
+    public Uri getUri() {
+        return CustomSliceRegistry.MOBILE_DATA_SLICE_URI;
+    }
+
+    @Override
+    public void onNotifyChange(Intent intent) {
+        // Don't make a change if we are in Airplane Mode.
+        if (isAirplaneModeEnabled()) {
+            return;
+        }
+
+        final boolean newState = intent.getBooleanExtra(EXTRA_TOGGLE_STATE,
+                    isMobileDataEnabled());
+
+        final int defaultSubId = getDefaultSubscriptionId(mSubscriptionManager);
+        if (defaultSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+            return; // No subscription - do nothing.
+        }
+
+        MobileNetworkUtils.setMobileDataEnabled(mContext, defaultSubId, newState,
+                false /* disableOtherSubscriptions */);
+        // Do not notifyChange on Uri. The service takes longer to update the current value than it
+        // does for the Slice to check the current value again. Let {@link WifiScanWorker}
+        // handle it.
+    }
+
+    @Override
+    public IntentFilter getIntentFilter() {
+        final IntentFilter filter = new IntentFilter();
+        filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
+        return filter;
+    }
+
+    @Override
+    public Intent getIntent() {
+        return new Intent(mContext, MobileNetworkActivity.class);
+    }
+
+    @Override
+    public Class<? extends SliceBackgroundWorker> getBackgroundWorkerClass() {
+        return MobileDataWorker.class;
+    }
+
+    protected static int getDefaultSubscriptionId(SubscriptionManager subscriptionManager) {
+        final SubscriptionInfo defaultSubscription =
+                subscriptionManager.getDefaultDataSubscriptionInfo();
+        if (defaultSubscription == null) {
+            return SubscriptionManager.INVALID_SUBSCRIPTION_ID; // No default subscription
+        }
+
+        return defaultSubscription.getSubscriptionId();
+    }
+
+    private CharSequence getSummary() {
+        final SubscriptionInfo defaultSubscription =
+                mSubscriptionManager.getDefaultDataSubscriptionInfo();
+        if (defaultSubscription == null) {
+            return null; // no summary text
+        }
+
+        return defaultSubscription.getDisplayName();
+    }
+
+    private PendingIntent getPrimaryAction() {
+        final Intent intent = getIntent();
+        return PendingIntent.getActivity(mContext, 0 /* requestCode */,
+                intent, 0 /* flags */);
+    }
+
+    @VisibleForTesting
+    boolean isAirplaneModeEnabled() {
+        // Generic key since we only want the method check - no UI.
+        AirplaneModePreferenceController controller = new AirplaneModePreferenceController(mContext,
+                "key" /* Key */);
+        return controller.isChecked();
+    }
+
+    @VisibleForTesting
+    boolean isMobileDataEnabled() {
+        if (mTelephonyManager == null) {
+            return false;
+        }
+
+        return mTelephonyManager.isDataEnabled();
+    }
+
+    /**
+     * Listener for mobile data state changes.
+     *
+     * <p>
+     *     Listen to individual subscription changes since there is no framework broadcast.
+     *
+     *     This worker registers a ContentObserver in the background and updates the MobileData
+     *     Slice when the value changes.
+     */
+    public static class MobileDataWorker extends SliceBackgroundWorker<Void> {
+
+        DataContentObserver mMobileDataObserver;
+
+        public MobileDataWorker(Context context, Uri uri) {
+            super(context, uri);
+            final Handler handler = new Handler(Looper.getMainLooper());
+            mMobileDataObserver = new DataContentObserver(handler, this);
+        }
+
+        @Override
+        protected void onSlicePinned() {
+            final SubscriptionManager subscriptionManager =
+                    getContext().getSystemService(SubscriptionManager.class);
+            mMobileDataObserver.register(getContext(),
+                    getDefaultSubscriptionId(subscriptionManager));
+        }
+
+        @Override
+        protected void onSliceUnpinned() {
+            mMobileDataObserver.unRegister(getContext());
+        }
+
+        @Override
+        public void close() throws IOException {
+            mMobileDataObserver = null;
+        }
+
+        public void updateSlice() {
+            notifySliceChange();
+        }
+
+        public class DataContentObserver extends ContentObserver {
+
+            private final MobileDataWorker mSliceBackgroundWorker;
+
+            public DataContentObserver(Handler handler, MobileDataWorker backgroundWorker) {
+                super(handler);
+                mSliceBackgroundWorker = backgroundWorker;
+            }
+
+            @Override
+            public void onChange(boolean selfChange) {
+                mSliceBackgroundWorker.updateSlice();
+            }
+
+            public void register(Context context, int subId) {
+                final Uri uri = MobileDataPreferenceController.getObservableUri(subId);
+                context.getContentResolver().registerContentObserver(uri, false, this);
+            }
+
+            public void unRegister(Context context) {
+                context.getContentResolver().unregisterContentObserver(this);
+            }
+        }
+    }
+}
index aae42f8..d20b75a 100644 (file)
@@ -55,6 +55,7 @@ public class InternetConnectivityPanel implements PanelContent {
     public List<Uri> getSlices() {
         final List<Uri> uris = new ArrayList<>();
         uris.add(CustomSliceRegistry.WIFI_SLICE_URI);
+        uris.add(CustomSliceRegistry.MOBILE_DATA_SLICE_URI);
         uris.add(CustomSliceRegistry.AIRPLANE_URI);
         return uris;
     }
index 3786c5c..c9e473a 100644 (file)
@@ -18,7 +18,6 @@ package com.android.settings.slices;
 
 import android.content.Context;
 import android.net.Uri;
-import android.text.TextUtils;
 import android.util.ArrayMap;
 
 import androidx.annotation.VisibleForTesting;
@@ -35,6 +34,7 @@ import com.android.settings.homepage.contextualcards.slices.LowStorageSlice;
 import com.android.settings.homepage.contextualcards.slices.NotificationChannelSlice;
 import com.android.settings.location.LocationSlice;
 import com.android.settings.media.MediaOutputSlice;
+import com.android.settings.network.telephony.MobileDataSlice;
 import com.android.settings.wifi.slice.ContextualWifiSlice;
 import com.android.settings.wifi.slice.WifiSlice;
 
@@ -123,6 +123,7 @@ public class CustomSliceManager {
         mUriMap.put(CustomSliceRegistry.FLASHLIGHT_SLICE_URI, FlashlightSlice.class);
         mUriMap.put(CustomSliceRegistry.LOCATION_SLICE_URI, LocationSlice.class);
         mUriMap.put(CustomSliceRegistry.LOW_STORAGE_SLICE_URI, LowStorageSlice.class);
+        mUriMap.put(CustomSliceRegistry.MOBILE_DATA_SLICE_URI, MobileDataSlice.class);
         mUriMap.put(CustomSliceRegistry.NOTIFICATION_CHANNEL_SLICE_URI,
                 NotificationChannelSlice.class);
         mUriMap.put(CustomSliceRegistry.STORAGE_SLICE_URI, StorageSlice.class);
index 66e85c0..ab1b248 100644 (file)
@@ -164,6 +164,16 @@ public class CustomSliceRegistry {
             .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
             .appendPath("toggle_nfc")
             .build();
+
+    /**
+     * Backing Uri for Mobile Data Slice.
+     */
+    public static final Uri MOBILE_DATA_SLICE_URI = new Uri.Builder()
+            .scheme(ContentResolver.SCHEME_CONTENT)
+            .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+            .appendEncodedPath(SettingsSlicesContract.PATH_SETTING_ACTION)
+            .appendPath("mobile_data")
+            .build();
     /**
      * Backing Uri for Notification channel Slice.
      */
index b538b89..220cdc8 100644 (file)
@@ -71,7 +71,7 @@ public interface CustomSliceable {
      *
      * @param intent which has the action taken on a {@link Slice}.
      */
-    void onNotifyChange(Intent intent);
+    default void onNotifyChange(Intent intent) {}
 
     /**
      * @return an {@link Intent} to the source of the Slice data.
@@ -90,11 +90,12 @@ public interface CustomSliceable {
     }
 
     /**
-     * Settings Slices which can represent component lists that are updatable by the
-     * {@link SliceBackgroundWorker} class returned here.
+     * Settings Slices which require background work, such as updating lists should implement a
+     * {@link SliceBackgroundWorker} and return it here. An example of background work is updating
+     * a list of Wifi networks available in the area.
      *
-     * @return a {@link SliceBackgroundWorker} class for fetching the list of results in the
-     * background.
+     * @return a {@link Class<? extends SliceBackgroundWorker>} to perform background work for the
+     * slice.
      */
     default Class<? extends SliceBackgroundWorker> getBackgroundWorkerClass() {
         return null;
index 80b7133..7b9acee 100644 (file)
@@ -464,8 +464,9 @@ public class SettingsSliceProvider extends SliceProvider {
 
     private List<Uri> getSpecialCaseOemUris() {
         return Arrays.asList(
-                CustomSliceRegistry.ZEN_MODE_SLICE_URI,
-                CustomSliceRegistry.FLASHLIGHT_SLICE_URI
+                CustomSliceRegistry.FLASHLIGHT_SLICE_URI,
+                CustomSliceRegistry.MOBILE_DATA_SLICE_URI,
+                CustomSliceRegistry.ZEN_MODE_SLICE_URI
         );
     }
 
index 6df45ba..995394e 100644 (file)
@@ -59,6 +59,14 @@ public abstract class SliceBackgroundWorker<E> implements Closeable {
         mUri = uri;
     }
 
+    protected Uri getUri() {
+        return mUri;
+    }
+
+    protected Context getContext() {
+        return mContext;
+    }
+
     /**
      * Returns the singleton instance of the {@link SliceBackgroundWorker} for specified {@link Uri}
      * if exists
@@ -151,7 +159,7 @@ public abstract class SliceBackgroundWorker<E> implements Closeable {
     /**
      * Notify that data was updated and attempt to sync changes to the Slice.
      */
-    protected void notifySliceChange() {
+    protected final void notifySliceChange() {
         mContext.getContentResolver().notifyChange(mUri, null);
     }
 }
\ No newline at end of file
index 1a0ed0c..bee643d 100644 (file)
@@ -142,7 +142,7 @@ public class WifiSlice implements CustomSliceable {
                 .setTitle(title)
                 .setSubtitle(!TextUtils.isEmpty(apSummary)
                         ? apSummary
-                        : mContext.getText(R.string.summary_placeholder))
+                        : null)
                 .setPrimaryAction(SliceAction.create(
                         getAccessPointAction(accessPoint), levelIcon, ListBuilder.ICON_IMAGE,
                         title));
@@ -247,7 +247,7 @@ public class WifiSlice implements CustomSliceable {
                 return mContext.getText(R.string.switch_off_text);
             case WifiManager.WIFI_STATE_UNKNOWN:
             default:
-                return "";
+                return null;
         }
     }
 
diff --git a/tests/robotests/src/com/android/settings/network/telephony/MobileDataSliceTest.java b/tests/robotests/src/com/android/settings/network/telephony/MobileDataSliceTest.java
new file mode 100644 (file)
index 0000000..c497cf8
--- /dev/null
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2019 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.network.telephony;
+
+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.times;
+import static org.mockito.Mockito.verify;
+
+import android.content.Context;
+import android.content.Intent;
+import android.provider.Settings;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+
+import androidx.core.graphics.drawable.IconCompat;
+import androidx.slice.Slice;
+import androidx.slice.SliceMetadata;
+import androidx.slice.SliceProvider;
+import androidx.slice.core.SliceAction;
+import androidx.slice.widget.SliceLiveData;
+
+import com.android.settings.R;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+import java.util.List;
+
+@RunWith(RobolectricTestRunner.class)
+public class MobileDataSliceTest {
+
+    private static final int SUB_ID = 2;
+
+    @Mock
+    private TelephonyManager mTelephonyManager;
+    @Mock
+    private SubscriptionManager mSubscriptionManager;
+    @Mock
+    private SubscriptionInfo mSubscriptionInfo;
+
+    private Context mContext;
+    private MobileDataSlice mMobileDataSlice;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mContext = spy(RuntimeEnvironment.application);
+
+        doReturn(mTelephonyManager).when(mContext).getSystemService(Context.TELEPHONY_SERVICE);
+        doReturn(mSubscriptionManager).when(mContext).getSystemService(SubscriptionManager.class);
+        doReturn(mTelephonyManager).when(mTelephonyManager).createForSubscriptionId(SUB_ID);
+        doReturn(mSubscriptionInfo).when(mSubscriptionManager).getDefaultDataSubscriptionInfo();
+        doReturn(SUB_ID).when(mSubscriptionInfo).getSubscriptionId();
+
+        // Set-up specs for SliceMetadata.
+        SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS);
+
+        mMobileDataSlice = spy(new MobileDataSlice(mContext));
+    }
+
+    @Test
+    public void getSlice_shouldHaveTitleAndToggle() {
+        final Slice mobileData = mMobileDataSlice.getSlice();
+
+        final SliceMetadata metadata = SliceMetadata.from(mContext, mobileData);
+        assertThat(metadata.getTitle())
+                .isEqualTo(mContext.getString(R.string.mobile_data_settings_title));
+
+        final List<SliceAction> toggles = metadata.getToggles();
+        assertThat(toggles).hasSize(1);
+
+        final SliceAction primaryAction = metadata.getPrimaryAction();
+        final IconCompat expectedToggleIcon = IconCompat.createWithResource(mContext,
+                R.drawable.ic_network_cell);
+        assertThat(primaryAction.getIcon().toString()).isEqualTo(expectedToggleIcon.toString());
+    }
+
+    @Test
+    public void handleUriChange_turnedOn_updatesMobileData() {
+        doReturn(false).when(mMobileDataSlice).isAirplaneModeEnabled();
+        doReturn(mSubscriptionInfo).when(mSubscriptionManager).getActiveSubscriptionInfo(SUB_ID);
+        final Intent intent = mMobileDataSlice.getIntent();
+        intent.putExtra(android.app.slice.Slice.EXTRA_TOGGLE_STATE, true);
+
+        mMobileDataSlice.onNotifyChange(intent);
+
+        verify(mTelephonyManager).setDataEnabled(true);
+    }
+
+    @Test
+    public void handleUriChange_turnedOff_updatesMobileData() {
+        doReturn(false).when(mMobileDataSlice).isAirplaneModeEnabled();
+        doReturn(mSubscriptionInfo).when(mSubscriptionManager).getActiveSubscriptionInfo(SUB_ID);
+        final Intent intent = mMobileDataSlice.getIntent();
+        intent.putExtra(android.app.slice.Slice.EXTRA_TOGGLE_STATE, false);
+
+        mMobileDataSlice.onNotifyChange(intent);
+
+        verify(mTelephonyManager).setDataEnabled(false);
+    }
+
+    @Test
+    public void handleUriChange_turnedOff_airplaneModeOn_mobileDataDoesNotUpdate() {
+        doReturn(true).when(mMobileDataSlice).isAirplaneModeEnabled();
+        doReturn(mSubscriptionInfo).when(mSubscriptionManager).getActiveSubscriptionInfo(SUB_ID);
+        final Intent intent = mMobileDataSlice.getIntent();
+        intent.putExtra(android.app.slice.Slice.EXTRA_TOGGLE_STATE, false);
+
+        mMobileDataSlice.onNotifyChange(intent);
+
+        verify(mTelephonyManager, times(0)).setDataEnabled(true);
+    }
+
+    @Test
+    public void isAirplaneModeEnabled_correctlyReturnsTrue() {
+        Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 1);
+
+        final boolean isAirplaneModeEnabled = mMobileDataSlice.isAirplaneModeEnabled();
+
+        assertThat(isAirplaneModeEnabled).isTrue();
+    }
+
+    @Test
+    public void isAirplaneModeEnabled_correctlyReturnsFalse() {
+        Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 0);
+
+        final boolean isAirplaneModeEnabled = mMobileDataSlice.isAirplaneModeEnabled();
+
+        assertThat(isAirplaneModeEnabled).isFalse();
+    }
+
+    @Test
+    public void isMobileDataEnabled_mobileDataEnabled() {
+        final boolean seed = true;
+        doReturn(seed).when(mTelephonyManager).isDataEnabled();
+
+        final boolean isMobileDataEnabled = mMobileDataSlice.isMobileDataEnabled();
+
+        assertThat(isMobileDataEnabled).isEqualTo(seed);
+    }
+}
index 3a4cf7b..42867fb 100644 (file)
@@ -46,8 +46,10 @@ public class InternetConnectivityPanelTest {
     public void getSlices_containsNecessarySlices() {
         final List<Uri> uris = mPanel.getSlices();
 
-        assertThat(uris).containsExactly(CustomSliceRegistry.WIFI_SLICE_URI,
-                CustomSliceRegistry.AIRPLANE_URI);
+        assertThat(uris).containsExactly(
+                CustomSliceRegistry.AIRPLANE_URI,
+                CustomSliceRegistry.MOBILE_DATA_SLICE_URI,
+                CustomSliceRegistry.WIFI_SLICE_URI);
     }
 
     @Test
index 7eae3e4..efdcc26 100644 (file)
@@ -116,7 +116,8 @@ public class SettingsSliceProviderTest {
 
     private static final List<Uri> SPECIAL_CASE_OEM_URIS = Arrays.asList(
             CustomSliceRegistry.ZEN_MODE_SLICE_URI,
-            CustomSliceRegistry.FLASHLIGHT_SLICE_URI
+            CustomSliceRegistry.FLASHLIGHT_SLICE_URI,
+            CustomSliceRegistry.MOBILE_DATA_SLICE_URI
     );
 
     @Before