Merge "Import translations. DO NOT MERGE" into pi-dev
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 7507de2..1e65b37 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -8710,6 +8710,9 @@
     <!-- 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>
@@ -8947,7 +8950,7 @@
     <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>
@@ -9040,6 +9043,9 @@
     <!-- 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>
 
@@ -9079,6 +9085,9 @@
     <!-- 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>
 
diff --git a/src/com/android/settings/SettingsInitialize.java b/src/com/android/settings/SettingsInitialize.java
index 9f2bdcc..0bc892c 100644
--- a/src/com/android/settings/SettingsInitialize.java
+++ b/src/com/android/settings/SettingsInitialize.java
@@ -22,11 +22,15 @@
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
+import android.content.pm.ShortcutInfo;
+import android.content.pm.ShortcutManager;
 import android.content.pm.UserInfo;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.support.annotation.VisibleForTesting;
 import android.util.Log;
 
+import java.util.ArrayList;
 import java.util.List;
 
 import static android.content.pm.PackageManager.GET_ACTIVITIES;
@@ -39,8 +43,8 @@
 /**
  * Listens to {@link Intent.ACTION_PRE_BOOT_COMPLETED} and {@link Intent.ACTION_USER_INITIALIZED}
  * performs setup steps for a managed profile (disables the launcher icon of the Settings app,
- * adds cross-profile intent filters for the appropriate Settings activities), and disables the
- * webview setting for non-admin users.
+ * adds cross-profile intent filters for the appropriate Settings activities), disables the
+ * webview setting for non-admin users, and updates the intent flags for any existing shortcuts.
  */
 public class SettingsInitialize extends BroadcastReceiver {
     private static final String TAG = "Settings";
@@ -56,6 +60,7 @@
         final PackageManager pm  = context.getPackageManager();
         managedProfileSetup(context, pm, broadcast, userInfo);
         webviewSettingSetup(context, pm, userInfo);
+        refreshExistingShortcuts(context);
     }
 
     private void managedProfileSetup(Context context, final PackageManager pm, Intent broadcast,
@@ -113,4 +118,22 @@
                         PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
                 PackageManager.DONT_KILL_APP);
     }
+
+    // Refresh settings shortcuts to have correct intent flags
+    @VisibleForTesting
+    void refreshExistingShortcuts(Context context) {
+        final ShortcutManager shortcutManager = context.getSystemService(ShortcutManager.class);
+        final List<ShortcutInfo> pinnedShortcuts = shortcutManager.getPinnedShortcuts();
+        final List<ShortcutInfo> updates = new ArrayList<>();
+        for (ShortcutInfo info : pinnedShortcuts) {
+            final Intent shortcutIntent = info.getIntent();
+            shortcutIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
+            final ShortcutInfo updatedInfo = new ShortcutInfo.Builder(context, info.getId())
+                    .setIntent(shortcutIntent)
+                    .build();
+            updates.add(updatedInfo);
+        }
+        shortcutManager.updateShortcuts(updates);
+    }
+
 }
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/applications/AppStorageSettings.java b/src/com/android/settings/applications/AppStorageSettings.java
index 7382d20..6e85f56 100644
--- a/src/com/android/settings/applications/AppStorageSettings.java
+++ b/src/com/android/settings/applications/AppStorageSettings.java
@@ -18,12 +18,19 @@
 
 import static android.content.pm.ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA;
 import static android.content.pm.ApplicationInfo.FLAG_SYSTEM;
+import static android.os.storage.StorageVolume.ScopedAccessProviderContract.AUTHORITY;
+import static android.os.storage.StorageVolume.ScopedAccessProviderContract.COL_GRANTED;
+import static android.os.storage.StorageVolume.ScopedAccessProviderContract.TABLE_PERMISSIONS;
+
+import static com.android.settings.applications.AppStateDirectoryAccessBridge.DEBUG;
 
 import android.app.ActivityManager;
 import android.app.AlertDialog;
 import android.app.AppGlobals;
 import android.app.GrantedUriPermission;
 import android.app.LoaderManager;
+import android.content.ContentResolver;
+import android.content.ContentValues;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.Intent;
@@ -32,6 +39,7 @@
 import android.content.pm.IPackageDataObserver;
 import android.content.pm.PackageManager;
 import android.content.pm.ProviderInfo;
+import android.net.Uri;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Message;
@@ -369,7 +377,7 @@
         boolean res = am.clearApplicationUserData(packageName, mClearDataObserver);
         if (!res) {
             // Clearing data failed for some obscure reason. Just log error for now
-            Log.i(TAG, "Couldnt clear application user data for package:" + packageName);
+            Log.i(TAG, "Couldn't clear application user data for package:" + packageName);
             showDialogInner(DLG_CANNOT_CLEAR_DATA, 0);
         } else {
             mButtonsPref.setButton1Text(R.string.recompute_size);
@@ -449,10 +457,23 @@
     }
 
     private void clearUriPermissions() {
+        final Context context = getActivity();
+        final String packageName = mAppEntry.info.packageName;
         // Synchronously revoke the permissions.
-        final ActivityManager am = (ActivityManager) getActivity().getSystemService(
+        final ActivityManager am = (ActivityManager) context.getSystemService(
                 Context.ACTIVITY_SERVICE);
-        am.clearGrantedUriPermissions(mAppEntry.info.packageName);
+        am.clearGrantedUriPermissions(packageName);
+
+
+        // Also update the Scoped Directory Access UI permissions
+        final Uri providerUri = new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT)
+                .authority(AUTHORITY).appendPath(TABLE_PERMISSIONS).appendPath("*")
+                .build();
+        Log.v(TAG, "Asking " + providerUri + " to delete permissions for " + packageName);
+        final int deleted = context.getContentResolver().delete(providerUri, null, new String[] {
+                packageName
+        });
+        Log.d(TAG, "Deleted " + deleted + " entries for package " + packageName);
 
         // Update UI
         refreshGrantedUriPermissions();
diff --git a/src/com/android/settings/applications/DirectoryAccessDetails.java b/src/com/android/settings/applications/DirectoryAccessDetails.java
index 8346e78..4876e3d 100644
--- a/src/com/android/settings/applications/DirectoryAccessDetails.java
+++ b/src/com/android/settings/applications/DirectoryAccessDetails.java
@@ -121,9 +121,15 @@
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
 
-        final Context context = getPrefContext();
         addPreferencesFromResource(R.xml.directory_access_details);
+
+    }
+
+    @Override
+    protected boolean refreshUi() {
+        final Context context = getPrefContext();
         final PreferenceScreen prefsGroup = getPreferenceScreen();
+        prefsGroup.removeAll();
 
         final Map<String, ExternalVolume> externalVolumes = new HashMap<>();
 
@@ -135,14 +141,14 @@
                 TABLE_PERMISSIONS_COLUMNS, null, new String[] { mPackageName }, null)) {
             if (cursor == null) {
                 Log.w(TAG, "Didn't get cursor for " + mPackageName);
-                return;
+                return true;
             }
             final int count = cursor.getCount();
             if (count == 0) {
                 // This setting screen should not be reached if there was no permission, so just
                 // ignore it
                 Log.w(TAG, "No permissions for " + mPackageName);
-                return;
+                return true;
             }
 
             while (cursor.moveToNext()) {
@@ -163,9 +169,14 @@
                 }
 
                 if (uuid == null) {
-                    // Primary storage entry: add right away
-                    prefsGroup.addPreference(newPreference(context, dir, providerUri,
-                            /* uuid= */ null, dir, granted, /* children= */ null));
+                    if (dir == null) {
+                        // Sanity check, shouldn't happen
+                        Log.wtf(TAG, "Ignoring permission on primary storage root");
+                    } else {
+                        // Primary storage entry: add right away
+                        prefsGroup.addPreference(newPreference(context, dir, providerUri,
+                                /* uuid= */ null, dir, granted, /* children= */ null));
+                    }
                 } else {
                     // External volume entry: save it for later.
                     ExternalVolume externalVolume = externalVolumes.get(uuid);
@@ -190,7 +201,7 @@
 
         if (externalVolumes.isEmpty()) {
             // We're done!
-            return;
+            return true;
         }
 
         // Add entries from external volumes
@@ -200,7 +211,7 @@
         final List<VolumeInfo> volumes = sm.getVolumes();
         if (volumes.isEmpty()) {
             Log.w(TAG, "StorageManager returned no secondary volumes");
-            return;
+            return true;
         }
         final Map<String, String> volumeNames = new HashMap<>(volumes.size());
         for (VolumeInfo volume : volumes) {
@@ -243,6 +254,7 @@
                 children.add(childPref);
             });
         }
+        return true;
     }
 
     private SwitchPreference newPreference(Context context, String title, Uri providerUri,
@@ -288,11 +300,6 @@
     }
 
     @Override
-    protected boolean refreshUi() {
-        return true;
-    }
-
-    @Override
     protected AlertDialog createDialog(int id, int errorCode) {
         return null;
     }
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 f0c2549..14f70a5 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;
@@ -85,8 +86,7 @@
     @Override
     public void onCreate(Bundle icicle) {
         super.onCreate(icicle);
-
-        final Context context = getContext();
+        Context context = getContext();
 
         boolean hasMobileData = DataUsageUtils.hasMobileData(context);
 
@@ -100,18 +100,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);
@@ -161,7 +164,8 @@
         return controllers;
     }
 
-    private void addMobileSection(int subId) {
+    @VisibleForTesting
+    void addMobileSection(int subId) {
         addMobileSection(subId, null);
     }
 
@@ -176,7 +180,8 @@
         }
     }
 
-    private void addWifiSection() {
+    @VisibleForTesting
+    void addWifiSection() {
         TemplatePreferenceCategory category = (TemplatePreferenceCategory)
                 inflatePreferences(R.xml.data_usage_wifi);
         category.setTemplate(NetworkTemplate.buildTemplateWifiWildcard(), 0, services);
@@ -289,17 +294,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 6b00a68..6473ca7 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,29 +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(
-                mLimitInfoText == null || mLimitInfoText.isEmpty() ? 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 dea71fe..44e5cf2 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
diff --git a/tests/robotests/src/com/android/settings/LegalSettingsTest.java b/tests/robotests/src/com/android/settings/LegalSettingsTest.java
index 72c6fa1..af0b757 100644
--- a/tests/robotests/src/com/android/settings/LegalSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/LegalSettingsTest.java
@@ -45,7 +45,7 @@
         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;
 
diff --git a/tests/robotests/src/com/android/settings/SettingsInitializeTest.java b/tests/robotests/src/com/android/settings/SettingsInitializeTest.java
new file mode 100644
index 0000000..f09723f
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/SettingsInitializeTest.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2018 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;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ShortcutInfo;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settings.testutils.shadow.ShadowShortcutManager;
+import java.util.ArrayList;
+import java.util.List;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(shadows = {ShadowShortcutManager.class})
+public class SettingsInitializeTest {
+
+    private Context mContext;
+    private SettingsInitialize mSettingsInitialize;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        mContext = RuntimeEnvironment.application;
+        mSettingsInitialize = new SettingsInitialize();
+    }
+
+    @Test
+    public void refreshExistingShortcuts_shouldUpdateLaunchIntentFlagsForExistingShortcut() {
+        final String id = "test_shortcut_id";
+        final Intent intent = new Intent(Intent.ACTION_DEFAULT);
+        intent.setFlags(Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+        final ShortcutInfo info = new ShortcutInfo.Builder(mContext, id)
+                .setShortLabel("test123")
+                .setIntent(intent)
+                .build();
+        final List<ShortcutInfo> shortcuts = new ArrayList<>();
+        shortcuts.add(info);
+        ShadowShortcutManager.get().setPinnedShortcuts(shortcuts);
+
+        mSettingsInitialize.refreshExistingShortcuts(mContext);
+
+        final List<ShortcutInfo> updatedShortcuts =
+                ShadowShortcutManager.get().getLastUpdatedShortcuts();
+        assertThat(updatedShortcuts).hasSize(1);
+        final ShortcutInfo updateInfo = updatedShortcuts.get(0);
+        assertThat(updateInfo.getId()).isEqualTo(id);
+        final int flags = updateInfo.getIntent().getFlags();
+        // The original flag should be removed
+        assertThat(flags & Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED).isEqualTo(0);
+        // The new flags should be set
+        assertThat(flags & Intent.FLAG_ACTIVITY_NEW_TASK).isEqualTo(Intent.FLAG_ACTIVITY_NEW_TASK);
+        assertThat(flags & Intent.FLAG_ACTIVITY_CLEAR_TOP).isEqualTo(
+                Intent.FLAG_ACTIVITY_CLEAR_TOP);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/datausage/DataUsageSummaryPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/datausage/DataUsageSummaryPreferenceControllerTest.java
index cd7de00..67caed4 100644
--- a/tests/robotests/src/com/android/settings/datausage/DataUsageSummaryPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/datausage/DataUsageSummaryPreferenceControllerTest.java
@@ -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 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;
@@ -88,6 +91,10 @@
     private EntityHeaderController mHeaderController;
     @Mock
     private DataUsageSummary mDataUsageSummary;
+    @Mock
+    private TelephonyManager mTelephonyManager;
+    @Mock
+    private ConnectivityManager mConnectivityManager;
 
     private FakeFeatureFactory mFactory;
     private Activity mActivity;
@@ -102,12 +109,17 @@
         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,
@@ -140,6 +152,7 @@
         verify(mSummaryPreference).setUsageInfo(info.cycleEnd, now - UPDATE_BACKOFF_MS,
                 CARRIER_NAME, 1 /* numPlans */, intent);
         verify(mSummaryPreference).setChartEnabled(true);
+        verify(mSummaryPreference).setWifiMode(false, null);
     }
 
     @Test
@@ -158,6 +171,7 @@
         verify(mSummaryPreference).setUsageInfo(info.cycleEnd, now - UPDATE_BACKOFF_MS,
                 CARRIER_NAME, 0 /* numPlans */, intent);
         verify(mSummaryPreference).setChartEnabled(true);
+        verify(mSummaryPreference).setWifiMode(false, null);
     }
 
     @Test
@@ -179,6 +193,7 @@
                 0 /* numPlans */,
                 null /* launchIntent */);
         verify(mSummaryPreference).setChartEnabled(true);
+        verify(mSummaryPreference).setWifiMode(false, null);
     }
 
     @Test
@@ -201,6 +216,7 @@
                 0 /* numPlans */,
                 null /* launchIntent */);
         verify(mSummaryPreference).setChartEnabled(false);
+        verify(mSummaryPreference).setWifiMode(false, null);
     }
 
     @Test
@@ -269,6 +285,30 @@
 
         mController.updateState(mSummaryPreference);
         verify(mSummaryPreference).setLimitInfo("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
@@ -290,7 +330,7 @@
     }
 
     @Test
-    public void testMobileData_preferenceDisabled() {
+    public void testMobileData_noSimNoWifi_preferenceDisabled() {
         mController = new DataUsageSummaryPreferenceController(
                 mDataUsageController,
                 mDataInfoController,
@@ -301,11 +341,29 @@
                 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);
 
diff --git a/tests/robotests/src/com/android/settings/datausage/DataUsageSummaryPreferenceTest.java b/tests/robotests/src/com/android/settings/datausage/DataUsageSummaryPreferenceTest.java
index eee961d..6bc76cf 100644
--- a/tests/robotests/src/com/android/settings/datausage/DataUsageSummaryPreferenceTest.java
+++ b/tests/robotests/src/com/android/settings/datausage/DataUsageSummaryPreferenceTest.java
@@ -17,10 +17,16 @@
 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.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;
 
@@ -380,6 +393,48 @@
         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);
diff --git a/tests/robotests/src/com/android/settings/datausage/DataUsageSummaryTest.java b/tests/robotests/src/com/android/settings/datausage/DataUsageSummaryTest.java
index d065c73..a6ddec1 100644
--- a/tests/robotests/src/com/android/settings/datausage/DataUsageSummaryTest.java
+++ b/tests/robotests/src/com/android/settings/datausage/DataUsageSummaryTest.java
@@ -16,24 +16,19 @@
 
 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.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 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 @@
 
     @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());
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/datausage/DataUsageUtilsTest.java b/tests/robotests/src/com/android/settings/datausage/DataUsageUtilsTest.java
index b988a6e..d59a4a8 100644
--- a/tests/robotests/src/com/android/settings/datausage/DataUsageUtilsTest.java
+++ b/tests/robotests/src/com/android/settings/datausage/DataUsageUtilsTest.java
@@ -22,6 +22,7 @@
 
 import android.content.Context;
 import android.net.ConnectivityManager;
+import android.telephony.TelephonyManager;
 
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 
@@ -37,6 +38,8 @@
 
     @Mock
     private ConnectivityManager mManager;
+    @Mock
+    private TelephonyManager mTelephonyManager;
     private Context mContext;
 
     @Before
@@ -45,6 +48,7 @@
         ShadowApplication shadowContext = ShadowApplication.getInstance();
         mContext = shadowContext.getApplicationContext();
         shadowContext.setSystemService(Context.CONNECTIVITY_SERVICE, mManager);
+        shadowContext.setSystemService(Context.TELEPHONY_SERVICE, mTelephonyManager);
     }
 
     @Test
@@ -60,4 +64,18 @@
         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();
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowDataUsageUtils.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowDataUsageUtils.java
index fecceb6..73cabfb 100644
--- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowDataUsageUtils.java
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowDataUsageUtils.java
@@ -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 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 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; }
 }
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowShortcutManager.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowShortcutManager.java
new file mode 100644
index 0000000..8e24bd7
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowShortcutManager.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2018 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.testutils.shadow;
+
+import static org.robolectric.RuntimeEnvironment.application;
+
+import android.content.pm.ShortcutInfo;
+import android.content.pm.ShortcutManager;
+import java.util.List;
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+import org.robolectric.annotation.Resetter;
+import org.robolectric.shadow.api.Shadow;
+
+@Implements(ShortcutManager.class)
+public class ShadowShortcutManager extends org.robolectric.shadows.ShadowShortcutManager {
+
+    private List<ShortcutInfo> mPinnedShortcuts;
+    private List<ShortcutInfo> mLastUpdatedShortcuts;
+
+    @Resetter
+    public void reset() {
+        mPinnedShortcuts = null;
+        mLastUpdatedShortcuts = null;
+    }
+
+    public static ShadowShortcutManager get() {
+        return Shadow.extract(application.getSystemService(ShortcutManager.class));
+    }
+
+    @Implementation
+    public boolean updateShortcuts(List<ShortcutInfo> shortcutInfoList) {
+        mLastUpdatedShortcuts = shortcutInfoList;
+        return true;
+    }
+
+    public List<ShortcutInfo> getLastUpdatedShortcuts() {
+        return mLastUpdatedShortcuts;
+    }
+
+    @Implementation
+    public List<ShortcutInfo> getPinnedShortcuts() {
+        return mPinnedShortcuts;
+    }
+
+    public void setPinnedShortcuts(List<ShortcutInfo> shortcutInfos) {
+        mPinnedShortcuts = shortcutInfos;
+    }
+}