OSDN Git Service

Fall back to Wi-Fi data display in data usage screen with no SIM.
authorJan Nordqvist <jannq@google.com>
Mon, 26 Mar 2018 22:29:44 +0000 (15:29 -0700)
committerJan Nordqvist <jannq@google.com>
Thu, 5 Apr 2018 14:58:23 +0000 (07:58 -0700)
Bug: 70950124

Test: manual
Test: make RunSettingsRoboTests
Change-Id: I06bf78e54119819be87e15baca7e5b6a241958cb

13 files changed:
res/values/strings.xml
src/com/android/settings/SettingsPreferenceFragment.java
src/com/android/settings/datausage/DataUsageBaseFragment.java
src/com/android/settings/datausage/DataUsageSummary.java
src/com/android/settings/datausage/DataUsageSummaryPreference.java
src/com/android/settings/datausage/DataUsageSummaryPreferenceController.java
src/com/android/settings/datausage/DataUsageUtils.java
tests/robotests/src/com/android/settings/LegalSettingsTest.java
tests/robotests/src/com/android/settings/datausage/DataUsageSummaryPreferenceControllerTest.java
tests/robotests/src/com/android/settings/datausage/DataUsageSummaryPreferenceTest.java
tests/robotests/src/com/android/settings/datausage/DataUsageSummaryTest.java
tests/robotests/src/com/android/settings/datausage/DataUsageUtilsTest.java
tests/robotests/src/com/android/settings/testutils/shadow/ShadowDataUsageUtils.java

index 7507de2..1e65b37 100644 (file)
     <!-- Summary of data usage [CHAR LIMIT=NONE] -->
     <string name="data_usage_summary_format"><xliff:g id="amount" example="50%">%1$s</xliff:g> of data used</string>
 
+    <!-- Summary of data usage [CHAR LIMIT=NONE] -->
+    <string name="data_usage_wifi_format"><xliff:g id="amount" example="50%">^1</xliff:g> used on Wi\u2011Fi</string>
+
     <!-- Summary of notifications [CHAR LIMIT=NONE] -->
     <plurals name="notification_summary">
         <item quantity="one">Off for 1 app</item>
     <string name="app_cellular_data_usage">App data usage</string>
 
     <!-- Label for wifi data usage in data usage screen [CHAR LIMIT=60] -->
-    <string name="wifi_data_usage">Wi-Fi data usage</string>
+    <string name="wifi_data_usage">Wi\u2011Fi data usage</string>
 
     <!-- Label for ethernet data usage in data usage screen [CHAR LIMIT=60] -->
     <string name="ethernet_data_usage">Ethernet data usage</string>
     <!-- Data usage title text [CHAR LIMIT=30] -->
     <string name="data_usage_title">Primary data</string>
 
+    <!-- Alternative data usage title text for Wi-Fi only mode [CHAR LIMIT=30] -->
+    <string name="data_usage_wifi_title">Wi\u2011Fi data</string>
+
     <!-- Data usage remaining string [CHAR LIMIT=30] -->
     <string name="data_used"><xliff:g name="bytes" example="2 GB">^1</xliff:g> used</string>
 
     <!-- Button to launch external data plan app [CHAR LIMIT=30] -->
     <string name="launch_mdp_app_text">View plan</string>
 
+    <!-- Alternate launch button text for Wi-Fi only mode [CHAR LIMIT=30] -->
+    <string name="launch_wifi_text">View details</string>
+
     <!-- Name of Data Saver screens [CHAR LIMIT=30] -->
     <string name="data_saver_title">Data Saver</string>
 
index bf4da66..95a039b 100644 (file)
@@ -375,7 +375,8 @@ public abstract class SettingsPreferenceFragment extends InstrumentedPreferenceF
         return mPreferenceCache != null ? mPreferenceCache.size() : 0;
     }
 
-    protected boolean removePreference(String key) {
+    @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)
+    public boolean removePreference(String key) {
         return removePreference(getPreferenceScreen(), key);
     }
 
index 344f2b8..e9c73ff 100644 (file)
@@ -48,13 +48,14 @@ public abstract class DataUsageBaseFragment extends DashboardFragment {
     @Override
     public void onCreate(Bundle icicle) {
         super.onCreate(icicle);
-        final Context context = getActivity();
+        Context context = getContext();
 
         services.mNetworkService = INetworkManagementService.Stub.asInterface(
                 ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE));
         services.mStatsService = INetworkStatsService.Stub.asInterface(
                 ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
-        services.mPolicyManager = NetworkPolicyManager.from(context);
+        services.mPolicyManager = (NetworkPolicyManager)context
+                .getSystemService(Context.NETWORK_POLICY_SERVICE);
 
         services.mPolicyEditor = new NetworkPolicyEditor(services.mPolicyManager);
 
@@ -100,6 +101,7 @@ public abstract class DataUsageBaseFragment extends DashboardFragment {
 
     /**
      * Test if device has an ethernet network connection.
+     * TODO(b/77590489): Remove this method when DataUsageSummaryLegacy is deprecated.
      */
     public boolean hasEthernet(Context context) {
         if (DataUsageUtils.TEST_RADIOS) {
index b087787..02e6268 100644 (file)
@@ -14,6 +14,7 @@
 
 package com.android.settings.datausage;
 
+import android.util.Log;
 import android.app.Activity;
 import android.content.ComponentName;
 import android.content.Context;
@@ -87,8 +88,7 @@ public class DataUsageSummary extends DataUsageBaseFragment implements Indexable
     @Override
     public void onCreate(Bundle icicle) {
         super.onCreate(icicle);
-
-        final Context context = getContext();
+        Context context = getContext();
 
         boolean hasMobileData = DataUsageUtils.hasMobileData(context);
 
@@ -102,18 +102,21 @@ public class DataUsageSummary extends DataUsageBaseFragment implements Indexable
         if (!hasMobileData || !isAdmin()) {
             removePreference(KEY_RESTRICT_BACKGROUND);
         }
+        boolean hasWifiRadio = DataUsageUtils.hasWifiRadio(context);
         if (hasMobileData) {
-            SubscriptionInfo subInfo
-                    = services.mSubscriptionManager.getDefaultDataSubscriptionInfo();
-            if (subInfo != null) {
-                addMobileSection(subInfo.getSubscriptionId());
+            addMobileSection(defaultSubId);
+            if (DataUsageUtils.hasSim(context) && hasWifiRadio) {
+                // If the device has a SIM installed, the data usage section shows usage for mobile,
+                // and the WiFi section is added if there is a WiFi radio - legacy behavior.
+                addWifiSection();
             }
-        }
-        boolean hasWifiRadio = DataUsageUtils.hasWifiRadio(context);
-        if (hasWifiRadio) {
+            // Do not add the WiFi section if either there is no WiFi radio (obviously) or if no
+            // SIM is installed. In the latter case the data usage section will show WiFi usage and
+            // there should be no explicit WiFi section added.
+        } else if (hasWifiRadio) {
             addWifiSection();
         }
-        if (hasEthernet(context)) {
+        if (DataUsageUtils.hasEthernet(context)) {
             addEthernetSection();
         }
         setHasOptionsMenu(true);
@@ -163,7 +166,8 @@ public class DataUsageSummary extends DataUsageBaseFragment implements Indexable
         return controllers;
     }
 
-    private void addMobileSection(int subId) {
+    @VisibleForTesting
+    void addMobileSection(int subId) {
         addMobileSection(subId, null);
     }
 
@@ -178,7 +182,8 @@ public class DataUsageSummary extends DataUsageBaseFragment implements Indexable
         }
     }
 
-    private void addWifiSection() {
+    @VisibleForTesting
+    void addWifiSection() {
         TemplatePreferenceCategory category = (TemplatePreferenceCategory)
                 inflatePreferences(R.xml.data_usage_wifi);
         category.setTemplate(NetworkTemplate.buildTemplateWifiWildcard(), 0, services);
@@ -291,17 +296,25 @@ public class DataUsageSummary extends DataUsageBaseFragment implements Indexable
         @Override
         public void setListening(boolean listening) {
             if (listening) {
-                TelephonyManager telephonyManager = (TelephonyManager) mActivity
-                        .getSystemService(Context.TELEPHONY_SERVICE);
-                final int simState = telephonyManager.getSimState();
-                // Note that pulling the SIM card returns UNKNOWN, not ABSENT.
-                if (simState == TelephonyManager.SIM_STATE_ABSENT
-                        || simState == TelephonyManager.SIM_STATE_UNKNOWN) {
-                    mSummaryLoader.setSummary(this, null);
-                } else {
+                if (DataUsageUtils.hasSim(mActivity)) {
                     mSummaryLoader.setSummary(this,
                             mActivity.getString(R.string.data_usage_summary_format,
                                     formatUsedData()));
+                } else {
+                    final DataUsageController.DataUsageInfo info =
+                            mDataController
+                                    .getDataUsageInfo(NetworkTemplate.buildTemplateWifiWildcard());
+
+                    if (info == null) {
+                        mSummaryLoader.setSummary(this, null);
+                    } else {
+                        final CharSequence wifiFormat = mActivity
+                                .getText(R.string.data_usage_wifi_format);
+                        final CharSequence sizeText =
+                                Formatter.formatFileSize(mActivity, info.usageLevel);
+                        mSummaryLoader.setSummary(this,
+                                TextUtils.expandTemplate(wifiFormat, sizeText));
+                    }
                 }
             }
         }
index 1e90282..8fee1b4 100644 (file)
@@ -20,6 +20,8 @@ import android.annotation.AttrRes;
 import android.content.Context;
 import android.content.Intent;
 import android.graphics.Typeface;
+import android.net.NetworkTemplate;
+import android.os.Bundle;
 import android.support.v7.preference.Preference;
 import android.support.v7.preference.PreferenceViewHolder;
 import android.text.Spannable;
@@ -34,7 +36,10 @@ import android.widget.ProgressBar;
 import android.widget.TextView;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.logging.nano.MetricsProto;
 import com.android.settings.R;
+import com.android.settings.core.SubSettingLauncher;
+import com.android.settingslib.AppItem;
 import com.android.settingslib.Utils;
 import com.android.settingslib.utils.StringUtil;
 
@@ -83,6 +88,10 @@ public class DataUsageSummaryPreference extends Preference {
     /** The number of bytes used since the start of the cycle. */
     private long mDataplanUse;
 
+    /** WiFi only mode */
+    private boolean mWifiMode;
+    private String mUsagePeriod;
+
     public DataUsageSummaryPreference(Context context, AttributeSet attrs) {
         super(context, attrs);
         setLayoutResource(R.layout.data_usage_summary_preference);
@@ -130,6 +139,12 @@ public class DataUsageSummaryPreference extends Preference {
         notifyChanged();
     }
 
+    void setWifiMode(boolean isWifiMode, String usagePeriod) {
+        mWifiMode = isWifiMode;
+        mUsagePeriod = usagePeriod;
+        notifyChanged();
+    }
+
     @Override
     public void onBindViewHolder(PreferenceViewHolder holder) {
         super.onBindViewHolder(holder);
@@ -149,28 +164,52 @@ public class DataUsageSummaryPreference extends Preference {
         updateDataUsageLabels(holder);
 
         TextView usageTitle = (TextView) holder.findViewById(R.id.usage_title);
-        usageTitle.setVisibility(mNumPlans > 1 ? View.VISIBLE : View.GONE);
-
-        updateCycleTimeText(holder);
-
+        TextView carrierInfo = (TextView) holder.findViewById(R.id.carrier_and_update);
+        Button launchButton = (Button) holder.findViewById(R.id.launch_mdp_app_button);
+        TextView limitInfo = (TextView) holder.findViewById(R.id.data_limits);
 
-        updateCarrierInfo((TextView) holder.findViewById(R.id.carrier_and_update));
+        if (mWifiMode) {
+            usageTitle.setText(R.string.data_usage_wifi_title);
+            usageTitle.setVisibility(View.VISIBLE);
+            TextView cycleTime = (TextView) holder.findViewById(R.id.cycle_left_time);
+            cycleTime.setText(mUsagePeriod);
+            carrierInfo.setVisibility(View.GONE);
+            limitInfo.setVisibility(View.GONE);
 
-        Button launchButton = (Button) holder.findViewById(R.id.launch_mdp_app_button);
-        launchButton.setOnClickListener((view) -> {
-            getContext().sendBroadcast(mLaunchIntent);
-        });
-        if (mLaunchIntent != null) {
+            launchButton.setOnClickListener((view) -> {
+                launchWifiDataUsage(getContext());
+            });
+            launchButton.setText(R.string.launch_wifi_text);
             launchButton.setVisibility(View.VISIBLE);
         } else {
-            launchButton.setVisibility(View.GONE);
+            usageTitle.setVisibility(mNumPlans > 1 ? View.VISIBLE : View.GONE);
+            updateCycleTimeText(holder);
+            updateCarrierInfo(carrierInfo);
+            if (mLaunchIntent != null) {
+                launchButton.setOnClickListener((view) -> {
+                    getContext().sendBroadcast(mLaunchIntent);
+                });
+                launchButton.setVisibility(View.VISIBLE);
+            } else {
+                launchButton.setVisibility(View.GONE);
+            }
+            limitInfo.setVisibility(
+                    TextUtils.isEmpty(mLimitInfoText) ? View.GONE : View.VISIBLE);
+            limitInfo.setText(mLimitInfoText);
         }
-
-        TextView limitInfo = (TextView) holder.findViewById(R.id.data_limits);
-        limitInfo.setVisibility(TextUtils.isEmpty(mLimitInfoText) ? View.GONE : View.VISIBLE);
-        limitInfo.setText(mLimitInfoText);
     }
 
+    private static void launchWifiDataUsage(Context context) {
+        final Bundle args = new Bundle(1);
+        args.putParcelable(DataUsageList.EXTRA_NETWORK_TEMPLATE,
+                NetworkTemplate.buildTemplateWifiWildcard());
+        final SubSettingLauncher launcher = new SubSettingLauncher(context)
+                .setArguments(args)
+                .setDestination(DataUsageList.class.getName())
+                .setSourceMetricsCategory(MetricsProto.MetricsEvent.VIEW_UNKNOWN);
+        launcher.setTitle(context.getString(R.string.wifi_data_usage));
+        launcher.launch();
+    }
 
     private void updateDataUsageLabels(PreferenceViewHolder holder) {
         TextView usageNumberField = (TextView) holder.findViewById(R.id.data_usage_view);
index 55e7392..752d6fa 100644 (file)
@@ -27,6 +27,7 @@ import android.support.v7.preference.Preference;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
 import android.telephony.SubscriptionPlan;
+import android.telephony.TelephonyManager;
 import android.text.BidiFormatter;
 import android.text.Spannable;
 import android.text.SpannableString;
@@ -183,17 +184,35 @@ public class DataUsageSummaryPreferenceController extends BasePreferenceControll
 
     @Override
     public int getAvailabilityStatus() {
-        return mSubscriptionManager.getDefaultDataSubscriptionInfo() != null
-                ? AVAILABLE : DISABLED_UNSUPPORTED;
+        return DataUsageUtils.hasSim(mActivity)
+                || DataUsageUtils.hasWifiRadio(mContext) ? AVAILABLE : DISABLED_UNSUPPORTED;
     }
 
     @Override
     public void updateState(Preference preference) {
         DataUsageSummaryPreference summaryPreference = (DataUsageSummaryPreference) preference;
-        DataUsageController.DataUsageInfo info = mDataUsageController.getDataUsageInfo(
-                mDefaultTemplate);
 
-        mDataInfoController.updateDataLimit(info, mPolicyEditor.getPolicy(mDefaultTemplate));
+        final DataUsageController.DataUsageInfo info;
+        if (DataUsageUtils.hasSim(mActivity)) {
+            info = mDataUsageController.getDataUsageInfo(mDefaultTemplate);
+            mDataInfoController.updateDataLimit(info, mPolicyEditor.getPolicy(mDefaultTemplate));
+            summaryPreference.setWifiMode(/* isWifiMode */ false, /* usagePeriod */ null);
+        } else {
+            info = mDataUsageController.getDataUsageInfo(
+                    NetworkTemplate.buildTemplateWifiWildcard());
+            summaryPreference.setWifiMode(/* isWifiMode */ true, /* usagePeriod */ info.period);
+            summaryPreference.setLimitInfo(null);
+            summaryPreference.setUsageNumbers(info.usageLevel,
+                    /* dataPlanSize */ -1L,
+                    /* hasMobileData */ true);
+            summaryPreference.setChartEnabled(false);
+            summaryPreference.setUsageInfo(info.cycleEnd,
+                    /* snapshotTime */ -1L,
+                    /* carrierName */ null,
+                    /* numPlans */ 0,
+                    /* launchIntent */ null);
+            return;
+        }
 
         if (mSubscriptionManager != null) {
             refreshDataplanInfo(info);
index af2d257..9c83047 100644 (file)
 
 package com.android.settings.datausage;
 
+import static android.net.ConnectivityManager.TYPE_ETHERNET;
 import static android.net.ConnectivityManager.TYPE_WIFI;
 
 import android.content.Context;
 import android.net.ConnectivityManager;
+import android.net.INetworkStatsService;
+import android.net.INetworkStatsSession;
 import android.net.NetworkTemplate;
+import android.net.TrafficStats;
+import android.os.RemoteException;
+import android.os.ServiceManager;
 import android.os.SystemProperties;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
@@ -31,11 +37,45 @@ import java.util.List;
 public final class DataUsageUtils {
     static final boolean TEST_RADIOS = false;
     static final String TEST_RADIOS_PROP = "test.radios";
+    private static final String ETHERNET = "ethernet";
 
     private DataUsageUtils() {
     }
 
     /**
+     * Test if device has an ethernet network connection.
+     */
+    public static boolean hasEthernet(Context context) {
+        if (DataUsageUtils.TEST_RADIOS) {
+            return SystemProperties.get(DataUsageUtils.TEST_RADIOS_PROP).contains(ETHERNET);
+        }
+
+        final ConnectivityManager conn = ConnectivityManager.from(context);
+        final boolean hasEthernet = conn.isNetworkSupported(ConnectivityManager.TYPE_ETHERNET);
+
+        final long ethernetBytes;
+        try {
+            INetworkStatsService statsService = INetworkStatsService.Stub.asInterface(
+                    ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
+
+            INetworkStatsSession statsSession = statsService.openSession();
+            if (statsSession != null) {
+                ethernetBytes = statsSession.getSummaryForNetwork(
+                        NetworkTemplate.buildTemplateEthernet(), Long.MIN_VALUE, Long.MAX_VALUE)
+                        .getTotalBytes();
+                TrafficStats.closeQuietly(statsSession);
+            } else {
+                ethernetBytes = 0;
+            }
+        } catch (RemoteException e) {
+            throw new RuntimeException(e);
+        }
+
+        // only show ethernet when both hardware present and traffic has occurred
+        return hasEthernet && ethernetBytes > 0;
+    }
+
+    /**
      * Returns whether device has mobile data.
      * TODO: This is the opposite to Utils.isWifiOnly(), it should be refactored into 1 method.
      */
@@ -53,10 +93,19 @@ public final class DataUsageUtils {
             return SystemProperties.get(TEST_RADIOS_PROP).contains("wifi");
         }
 
-        ConnectivityManager connectivityManager = ConnectivityManager.from(context);
+        ConnectivityManager connectivityManager =
+                context.getSystemService(ConnectivityManager.class);
         return connectivityManager != null && connectivityManager.isNetworkSupported(TYPE_WIFI);
     }
 
+    public static boolean hasSim(Context context) {
+        TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class);
+        final int simState = telephonyManager.getSimState();
+        // Note that pulling the SIM card returns UNKNOWN, not ABSENT.
+        return simState != TelephonyManager.SIM_STATE_ABSENT
+                && simState != TelephonyManager.SIM_STATE_UNKNOWN;
+    }
+
     /**
      * Returns the default subscription if available else returns
      * SubscriptionManager#INVALID_SUBSCRIPTION_ID
index 72c6fa1..af0b757 100644 (file)
@@ -45,7 +45,7 @@ public class LegalSettingsTest {
         mContext = spy(RuntimeEnvironment.application);
         mFragment = new LegalSettings() {
             @Override
-            protected boolean removePreference(String key) {
+            public boolean removePreference(String key) {
                 if (LegalSettings.KEY_WALLPAPER_ATTRIBUTIONS.equals(key)) {
                     mWallpaperRemoved = true;
 
index 9a38305..a616102 100644 (file)
@@ -16,6 +16,7 @@
 
 package com.android.settings.datausage;
 
+import static android.net.ConnectivityManager.TYPE_WIFI;
 import static com.android.settings.core.BasePreferenceController.AVAILABLE;
 import static com.android.settings.core.BasePreferenceController.DISABLED_UNSUPPORTED;
 import static com.google.common.truth.Truth.assertThat;
@@ -28,9 +29,11 @@ import static org.mockito.Mockito.when;
 import android.app.Activity;
 import android.content.Context;
 import android.content.Intent;
+import android.net.ConnectivityManager;
 import android.net.NetworkTemplate;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
 
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.settings.R;
@@ -89,6 +92,10 @@ public class DataUsageSummaryPreferenceControllerTest {
     private EntityHeaderController mHeaderController;
     @Mock
     private DataUsageSummary mDataUsageSummary;
+    @Mock
+    private TelephonyManager mTelephonyManager;
+    @Mock
+    private ConnectivityManager mConnectivityManager;
 
     private FakeFeatureFactory mFactory;
     private Activity mActivity;
@@ -103,12 +110,17 @@ public class DataUsageSummaryPreferenceControllerTest {
         doReturn("%1$s %2%s").when(mContext)
             .getString(com.android.internal.R.string.fileSizeSuffix);
 
-        mActivity = Robolectric.setupActivity(Activity.class);
         mFactory = FakeFeatureFactory.setupForTest();
         when(mFactory.metricsFeatureProvider.getMetricsCategory(any(Object.class)))
                 .thenReturn(MetricsProto.MetricsEvent.SETTINGS_APP_NOTIF_CATEGORY);
         ShadowEntityHeaderController.setUseMock(mHeaderController);
 
+        mActivity = spy(Robolectric.buildActivity(Activity.class).get());
+        when(mActivity.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager);
+        when(mActivity.getSystemService(ConnectivityManager.class))
+                .thenReturn(mConnectivityManager);
+        when(mTelephonyManager.getSimState()).thenReturn(TelephonyManager.SIM_STATE_READY);
+        when(mConnectivityManager.isNetworkSupported(TYPE_WIFI)).thenReturn(false);
         mController = new DataUsageSummaryPreferenceController(
                 mDataUsageController,
                 mDataInfoController,
@@ -146,6 +158,7 @@ public class DataUsageSummaryPreferenceControllerTest {
         verify(mSummaryPreference).setUsageInfo(info.cycleEnd, now - UPDATE_BACKOFF_MS,
                 CARRIER_NAME, 1 /* numPlans */, intent);
         verify(mSummaryPreference).setChartEnabled(true);
+        verify(mSummaryPreference).setWifiMode(false, null);
     }
 
     @Test
@@ -169,6 +182,7 @@ public class DataUsageSummaryPreferenceControllerTest {
         verify(mSummaryPreference).setUsageInfo(info.cycleEnd, now - UPDATE_BACKOFF_MS,
                 CARRIER_NAME, 0 /* numPlans */, intent);
         verify(mSummaryPreference).setChartEnabled(true);
+        verify(mSummaryPreference).setWifiMode(false, null);
     }
 
     @Test
@@ -194,6 +208,7 @@ public class DataUsageSummaryPreferenceControllerTest {
                 0 /* numPlans */,
                 null /* launchIntent */);
         verify(mSummaryPreference).setChartEnabled(true);
+        verify(mSummaryPreference).setWifiMode(false, null);
     }
 
     @Test
@@ -220,6 +235,7 @@ public class DataUsageSummaryPreferenceControllerTest {
                 0 /* numPlans */,
                 null /* launchIntent */);
         verify(mSummaryPreference).setChartEnabled(false);
+        verify(mSummaryPreference).setWifiMode(false, null);
     }
 
     @Test
@@ -300,6 +316,30 @@ public class DataUsageSummaryPreferenceControllerTest {
         verify(mSummaryPreference).setLimitInfo(captor.capture());
         CharSequence value = captor.getValue();
         assertThat(value.toString()).isEqualTo("1.00 MB data warning / 1.00 MB data limit");
+        verify(mSummaryPreference).setWifiMode(false, null);
+    }
+
+    @Test
+    public void testSummaryUpdate_noSim_shouldSetWifiMode() {
+        final long now = System.currentTimeMillis();
+        final DataUsageController.DataUsageInfo info = createTestDataUsageInfo(now);
+        info.warningLevel = 1000000L;
+        info.limitLevel = 1000000L;
+
+        final Intent intent = new Intent();
+
+        when(mDataUsageController.getDataUsageInfo(any())).thenReturn(info);
+        mController.setPlanValues(0 /* dataPlanCount */, LIMIT1, USAGE1);
+        mController.setCarrierValues(CARRIER_NAME, now - UPDATE_BACKOFF_MS, info.cycleEnd, intent);
+
+        when(mTelephonyManager.getSimState()).thenReturn(TelephonyManager.SIM_STATE_ABSENT);
+        mController.updateState(mSummaryPreference);
+
+        verify(mSummaryPreference).setWifiMode(true, info.period);
+        verify(mSummaryPreference).setLimitInfo(null);
+        verify(mSummaryPreference).setUsageNumbers(info.usageLevel, -1L, true);
+        verify(mSummaryPreference).setChartEnabled(false);
+        verify(mSummaryPreference).setUsageInfo(info.cycleEnd, -1L, null, 0, null);
     }
 
     @Test
@@ -321,7 +361,7 @@ public class DataUsageSummaryPreferenceControllerTest {
     }
 
     @Test
-    public void testMobileData_preferenceDisabled() {
+    public void testMobileData_noSimNoWifi_preferenceDisabled() {
         mController = new DataUsageSummaryPreferenceController(
                 mDataUsageController,
                 mDataInfoController,
@@ -332,11 +372,29 @@ public class DataUsageSummaryPreferenceControllerTest {
                 mSubscriptionManager,
                 mActivity, null, null, null);
 
-        when(mSubscriptionManager.getDefaultDataSubscriptionInfo()).thenReturn(null);
+        when(mTelephonyManager.getSimState()).thenReturn(TelephonyManager.SIM_STATE_ABSENT);
+        when(mConnectivityManager.isNetworkSupported(TYPE_WIFI)).thenReturn(false);
         assertThat(mController.getAvailabilityStatus()).isEqualTo(DISABLED_UNSUPPORTED);
     }
 
     @Test
+    public void testMobileData_noSimWifi_preferenceDisabled() {
+        mController = new DataUsageSummaryPreferenceController(
+                mDataUsageController,
+                mDataInfoController,
+                mNetworkTemplate,
+                mPolicyEditor,
+                R.string.cell_data_template,
+                true,
+                mSubscriptionManager,
+                mActivity, null, null, null);
+
+        when(mTelephonyManager.getSimState()).thenReturn(TelephonyManager.SIM_STATE_ABSENT);
+        when(mConnectivityManager.isNetworkSupported(TYPE_WIFI)).thenReturn(true);
+        assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
+    }
+
+    @Test
     public void testMobileData_entityHeaderSet() {
         final RecyclerView recyclerView = new RecyclerView(mActivity);
 
index 436ceaf..637c429 100644 (file)
 package com.android.settings.datausage;
 
 import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.verify;
 
+import android.app.Activity;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.graphics.Typeface;
+import android.net.NetworkTemplate;
+import android.os.Bundle;
 import android.support.v7.preference.PreferenceViewHolder;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -30,16 +36,23 @@ import android.widget.ProgressBar;
 import android.widget.TextView;
 
 import com.android.settings.R;
+import com.android.settings.SettingsActivity;
+import com.android.settings.SubSettings;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 import com.android.settings.testutils.shadow.SettingsShadowResourcesImpl;
 import com.android.settingslib.Utils;
+import com.android.settingslib.core.instrumentation.VisibilityLoggerMixin;
 
+import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.MockitoAnnotations;
+import org.robolectric.Robolectric;
 import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Config;
+import org.robolectric.Shadows;
+import org.robolectric.shadows.ShadowActivity;
 
 import java.util.concurrent.TimeUnit;
 
@@ -389,6 +402,48 @@ public class DataUsageSummaryPreferenceTest {
         assertThat(mDataRemaining.getText()).isEqualTo("");
     }
 
+    @Test
+    public void testSetWifiMode_withUsageInfo_dataUsageShown() {
+        final int daysLeft = 3;
+        final long cycleEnd = System.currentTimeMillis() + TimeUnit.DAYS.toMillis(daysLeft)
+                + TimeUnit.HOURS.toMillis(1);
+        final Activity activity = Robolectric.setupActivity(Activity.class);
+        mSummaryPreference.setUsageInfo(cycleEnd, mUpdateTime, DUMMY_CARRIER, 0 /* numPlans */,
+                new Intent());
+        mSummaryPreference.setUsageNumbers(1000000L, -1L, true);
+        final String cycleText = "The quick fox";
+        mSummaryPreference.setWifiMode(true, cycleText);
+
+        bindViewHolder();
+        assertThat(mUsageTitle.getText().toString())
+                .isEqualTo(mContext.getString(R.string.data_usage_wifi_title));
+        assertThat(mUsageTitle.getVisibility()).isEqualTo(View.VISIBLE);
+        assertThat(mCycleTime.getVisibility()).isEqualTo(View.VISIBLE);
+        assertThat(mCycleTime.getText()).isEqualTo(cycleText);
+        assertThat(mCarrierInfo.getVisibility()).isEqualTo(View.GONE);
+        assertThat(mDataLimits.getVisibility()).isEqualTo(View.GONE);
+        assertThat(mLaunchButton.getVisibility()).isEqualTo(View.VISIBLE);
+        assertThat(mLaunchButton.getText())
+                .isEqualTo(mContext.getString(R.string.launch_wifi_text));
+
+        mLaunchButton.callOnClick();
+        ShadowActivity shadowActivity = Shadows.shadowOf(activity);
+        Intent startedIntent = shadowActivity.getNextStartedActivity();
+        assertThat(startedIntent.getComponent()).isEqualTo(new ComponentName("com.android.settings",
+                SubSettings.class.getName()));
+
+        final Bundle expect = new Bundle(1);
+        expect.putParcelable(DataUsageList.EXTRA_NETWORK_TEMPLATE,
+                NetworkTemplate.buildTemplateWifiWildcard());
+        final Bundle actual = startedIntent
+                .getBundleExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_ARGUMENTS);
+        assertThat((NetworkTemplate) actual.getParcelable(DataUsageList.EXTRA_NETWORK_TEMPLATE))
+                .isEqualTo(NetworkTemplate.buildTemplateWifiWildcard());
+
+        assertThat(startedIntent.getCharSequenceExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_TITLE))
+                .isEqualTo(mContext.getString(R.string.wifi_data_usage));
+    }
+
     private void bindViewHolder() {
         mSummaryPreference.onBindViewHolder(mHolder);
         mUsageTitle = (TextView) mHolder.findViewById(R.id.usage_title);
index d065c73..a6ddec1 100644 (file)
 
 package com.android.settings.datausage;
 
-import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyObject;
-import static org.mockito.Matchers.endsWith;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
 import android.app.Activity;
 import android.content.Context;
-import android.net.ConnectivityManager;
-import android.telephony.TelephonyManager;
+import android.net.NetworkPolicyManager;
+import android.os.Bundle;
 import android.text.format.Formatter;
 
-import com.android.settings.R;
 import com.android.settings.dashboard.SummaryLoader;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 import com.android.settings.testutils.shadow.SettingsShadowResources;
+import com.android.settings.testutils.shadow.SettingsShadowResourcesImpl;
+import com.android.settings.testutils.shadow.ShadowDashboardFragment;
+import com.android.settings.testutils.shadow.ShadowDataUsageUtils;
+import com.android.settings.testutils.shadow.ShadowUtils;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -41,18 +36,35 @@ import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.robolectric.Robolectric;
+import org.robolectric.annotation.Config;
 import org.robolectric.shadows.ShadowApplication;
 
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyObject;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.endsWith;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+@Config(shadows = {
+    SettingsShadowResourcesImpl.class,
+    SettingsShadowResources.SettingsShadowTheme.class,
+    ShadowUtils.class,
+    ShadowDataUsageUtils.class,
+    ShadowDashboardFragment.class
+})
 @RunWith(SettingsRobolectricTestRunner.class)
 public class DataUsageSummaryTest {
 
     @Mock
-    private ConnectivityManager mManager;
-    private Context mContext;
-    @Mock
-    TelephonyManager mTelephonyManager;
-    @Mock
     private SummaryLoader mSummaryLoader;
+    @Mock
+    private NetworkPolicyManager mNetworkPolicyManager;
+    private Context mContext;
     private Activity mActivity;
     private SummaryLoader.SummaryProvider mSummaryProvider;
 
@@ -65,12 +77,10 @@ public class DataUsageSummaryTest {
     public void setUp() {
         MockitoAnnotations.initMocks(this);
         ShadowApplication shadowContext = ShadowApplication.getInstance();
-        shadowContext.setSystemService(Context.CONNECTIVITY_SERVICE, mManager);
-        mContext = shadowContext.getApplicationContext();
-        when(mManager.isNetworkSupported(anyInt())).thenReturn(true);
+        shadowContext.setSystemService(Context.NETWORK_POLICY_SERVICE, mNetworkPolicyManager);
 
+        mContext = shadowContext.getApplicationContext();
         mActivity = spy(Robolectric.buildActivity(Activity.class).get());
-        when(mActivity.getSystemService(Context.TELEPHONY_SERVICE)).thenReturn(mTelephonyManager);
 
         mSummaryProvider = DataUsageSummary.SUMMARY_PROVIDER_FACTORY
                 .createSummaryProvider(mActivity, mSummaryLoader);
@@ -89,15 +99,73 @@ public class DataUsageSummaryTest {
 
     @Test
     public void setListening_shouldBlankSummaryWithNoSim() {
-        when(mTelephonyManager.getSimState()).thenReturn(TelephonyManager.SIM_STATE_ABSENT);
+        ShadowDataUsageUtils.HAS_SIM = false;
         mSummaryProvider.setListening(true);
         verify(mSummaryLoader).setSummary(mSummaryProvider, null);
     }
 
     @Test
     public void setListening_shouldSetSummaryWithSim() {
-        when(mTelephonyManager.getSimState()).thenReturn(TelephonyManager.SIM_STATE_READY);
+        ShadowDataUsageUtils.HAS_SIM = true;
         mSummaryProvider.setListening(true);
         verify(mSummaryLoader).setSummary(anyObject(), endsWith(" of data used"));
     }
+
+    @Test
+    public void configuration_withSim_shouldShowMobileAndWifi() {
+        ShadowDataUsageUtils.IS_MOBILE_DATA_SUPPORTED = true;
+        ShadowDataUsageUtils.IS_WIFI_SUPPORTED = true;
+        ShadowDataUsageUtils.DEFAULT_SUBSCRIPTION_ID = 1;
+        ShadowDataUsageUtils.HAS_SIM = true;
+
+        final DataUsageSummary dataUsageSummary = spy(new DataUsageSummary());
+        doReturn(mContext).when(dataUsageSummary).getContext();
+
+        doReturn(true).when(dataUsageSummary).removePreference(anyString());
+        doNothing().when(dataUsageSummary).addWifiSection();
+        doNothing().when(dataUsageSummary).addMobileSection(1);
+
+        dataUsageSummary.onCreate(null);
+
+        verify(dataUsageSummary).addWifiSection();
+        verify(dataUsageSummary).addMobileSection(anyInt());
+    }
+
+    @Test
+    public void configuration_withoutSim_shouldShowWifiSectionOnly() {
+        ShadowDataUsageUtils.IS_MOBILE_DATA_SUPPORTED = true;
+        ShadowDataUsageUtils.IS_WIFI_SUPPORTED = true;
+        ShadowDataUsageUtils.HAS_SIM = false;
+
+        final DataUsageSummary dataUsageSummary = spy(new DataUsageSummary());
+        doReturn(mContext).when(dataUsageSummary).getContext();
+
+        doReturn(true).when(dataUsageSummary).removePreference(anyString());
+        doNothing().when(dataUsageSummary).addWifiSection();
+        doNothing().when(dataUsageSummary).addMobileSection(1);
+
+        dataUsageSummary.onCreate(null);
+
+        verify(dataUsageSummary).addWifiSection();
+        verify(dataUsageSummary, never()).addMobileSection(anyInt());
+    }
+
+    @Test
+    public void configuration_withoutMobile_shouldShowWifiSectionOnly() {
+        ShadowDataUsageUtils.IS_MOBILE_DATA_SUPPORTED = false;
+        ShadowDataUsageUtils.IS_WIFI_SUPPORTED = true;
+        ShadowDataUsageUtils.HAS_SIM = false;
+
+        final DataUsageSummary dataUsageSummary = spy(new DataUsageSummary());
+        doReturn(mContext).when(dataUsageSummary).getContext();
+
+        doReturn(true).when(dataUsageSummary).removePreference(anyString());
+        doNothing().when(dataUsageSummary).addWifiSection();
+        doNothing().when(dataUsageSummary).addMobileSection(1);
+
+        dataUsageSummary.onCreate(null);
+
+        verify(dataUsageSummary).addWifiSection();
+        verify(dataUsageSummary, never()).addMobileSection(anyInt());
+    }
 }
index b988a6e..d59a4a8 100644 (file)
@@ -22,6 +22,7 @@ import static org.mockito.Mockito.when;
 
 import android.content.Context;
 import android.net.ConnectivityManager;
+import android.telephony.TelephonyManager;
 
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 
@@ -37,6 +38,8 @@ public final class DataUsageUtilsTest {
 
     @Mock
     private ConnectivityManager mManager;
+    @Mock
+    private TelephonyManager mTelephonyManager;
     private Context mContext;
 
     @Before
@@ -45,6 +48,7 @@ public final class DataUsageUtilsTest {
         ShadowApplication shadowContext = ShadowApplication.getInstance();
         mContext = shadowContext.getApplicationContext();
         shadowContext.setSystemService(Context.CONNECTIVITY_SERVICE, mManager);
+        shadowContext.setSystemService(Context.TELEPHONY_SERVICE, mTelephonyManager);
     }
 
     @Test
@@ -60,4 +64,18 @@ public final class DataUsageUtilsTest {
         boolean hasMobileData = DataUsageUtils.hasMobileData(mContext);
         assertThat(hasMobileData).isFalse();
     }
+
+    @Test
+    public void hasSim_simStateReady() {
+        when(mTelephonyManager.getSimState()).thenReturn(TelephonyManager.SIM_STATE_READY);
+        boolean hasSim = DataUsageUtils.hasSim(mContext);
+        assertThat(hasSim).isTrue();
+    }
+
+    @Test
+    public void hasSim_simStateMissing() {
+        when(mTelephonyManager.getSimState()).thenReturn(TelephonyManager.SIM_STATE_ABSENT);
+        boolean hasSim = DataUsageUtils.hasSim(mContext);
+        assertThat(hasSim).isFalse();
+    }
 }
index fecceb6..73cabfb 100644 (file)
@@ -1,6 +1,7 @@
 package com.android.settings.testutils.shadow;
 
 import android.content.Context;
+import android.telephony.SubscriptionManager;
 
 import com.android.settings.datausage.DataUsageUtils;
 import org.robolectric.annotation.Implementation;
@@ -11,6 +12,8 @@ public class ShadowDataUsageUtils {
 
     public static boolean IS_MOBILE_DATA_SUPPORTED = true;
     public static boolean IS_WIFI_SUPPORTED = true;
+    public static boolean HAS_SIM = true;
+    public static int DEFAULT_SUBSCRIPTION_ID = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
 
     @Implementation
     public static boolean hasMobileData(Context context) {
@@ -21,4 +24,17 @@ public class ShadowDataUsageUtils {
     public static boolean hasWifiRadio(Context context) {
         return IS_WIFI_SUPPORTED;
     }
+
+    @Implementation
+    public static int getDefaultSubscriptionId(Context context) {
+        return DEFAULT_SUBSCRIPTION_ID;
+    }
+
+    @Implementation
+    public static boolean hasSim(Context context) {
+        return HAS_SIM;
+    }
+
+    @Implementation
+    public static boolean hasEthernet(Context context) { return false; }
 }