Fall back to Wi-Fi data display in data usage screen with no SIM.
Bug: 70950124
Test: manual
Test: make RunSettingsRoboTests
Change-Id: I06bf78e54119819be87e15baca7e5b6a241958cb
diff --git a/src/com/android/settings/SettingsPreferenceFragment.java b/src/com/android/settings/SettingsPreferenceFragment.java
index bf4da66..95a039b 100644
--- a/src/com/android/settings/SettingsPreferenceFragment.java
+++ b/src/com/android/settings/SettingsPreferenceFragment.java
@@ -375,7 +375,8 @@
return mPreferenceCache != null ? mPreferenceCache.size() : 0;
}
- protected boolean removePreference(String key) {
+ @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)
+ public boolean removePreference(String key) {
return removePreference(getPreferenceScreen(), key);
}
diff --git a/src/com/android/settings/datausage/DataUsageBaseFragment.java b/src/com/android/settings/datausage/DataUsageBaseFragment.java
index 344f2b8..e9c73ff 100644
--- a/src/com/android/settings/datausage/DataUsageBaseFragment.java
+++ b/src/com/android/settings/datausage/DataUsageBaseFragment.java
@@ -48,13 +48,14 @@
@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 @@
/**
* 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) {
diff --git a/src/com/android/settings/datausage/DataUsageSummary.java b/src/com/android/settings/datausage/DataUsageSummary.java
index b087787..02e6268 100644
--- a/src/com/android/settings/datausage/DataUsageSummary.java
+++ b/src/com/android/settings/datausage/DataUsageSummary.java
@@ -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 @@
@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 @@
if (!hasMobileData || !isAdmin()) {
removePreference(KEY_RESTRICT_BACKGROUND);
}
- if (hasMobileData) {
- SubscriptionInfo subInfo
- = services.mSubscriptionManager.getDefaultDataSubscriptionInfo();
- if (subInfo != null) {
- addMobileSection(subInfo.getSubscriptionId());
- }
- }
boolean hasWifiRadio = DataUsageUtils.hasWifiRadio(context);
- if (hasWifiRadio) {
+ if (hasMobileData) {
+ 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();
+ }
+ // 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 @@
return controllers;
}
- private void addMobileSection(int subId) {
+ @VisibleForTesting
+ void addMobileSection(int subId) {
addMobileSection(subId, null);
}
@@ -178,7 +182,8 @@
}
}
- 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 @@
@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));
+ }
}
}
}
diff --git a/src/com/android/settings/datausage/DataUsageSummaryPreference.java b/src/com/android/settings/datausage/DataUsageSummaryPreference.java
index 1e90282..8fee1b4 100644
--- a/src/com/android/settings/datausage/DataUsageSummaryPreference.java
+++ b/src/com/android/settings/datausage/DataUsageSummaryPreference.java
@@ -20,6 +20,8 @@
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.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 @@
/** 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 @@
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 @@
updateDataUsageLabels(holder);
TextView usageTitle = (TextView) holder.findViewById(R.id.usage_title);
- usageTitle.setVisibility(mNumPlans > 1 ? View.VISIBLE : View.GONE);
-
- updateCycleTimeText(holder);
-
-
- updateCarrierInfo((TextView) holder.findViewById(R.id.carrier_and_update));
-
+ TextView carrierInfo = (TextView) holder.findViewById(R.id.carrier_and_update);
Button launchButton = (Button) holder.findViewById(R.id.launch_mdp_app_button);
- launchButton.setOnClickListener((view) -> {
- getContext().sendBroadcast(mLaunchIntent);
- });
- if (mLaunchIntent != null) {
+ TextView limitInfo = (TextView) holder.findViewById(R.id.data_limits);
+
+ 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);
+
+ 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);
diff --git a/src/com/android/settings/datausage/DataUsageSummaryPreferenceController.java b/src/com/android/settings/datausage/DataUsageSummaryPreferenceController.java
index 55e7392..752d6fa 100644
--- a/src/com/android/settings/datausage/DataUsageSummaryPreferenceController.java
+++ b/src/com/android/settings/datausage/DataUsageSummaryPreferenceController.java
@@ -27,6 +27,7 @@
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 @@
@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);
diff --git a/src/com/android/settings/datausage/DataUsageUtils.java b/src/com/android/settings/datausage/DataUsageUtils.java
index af2d257..9c83047 100644
--- a/src/com/android/settings/datausage/DataUsageUtils.java
+++ b/src/com/android/settings/datausage/DataUsageUtils.java
@@ -14,11 +14,17 @@
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 @@
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 @@
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