Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4fbe0f83 authored by Jan Nordqvist's avatar Jan Nordqvist Committed by Eric Schwarzenbach
Browse files

Update DataUsageSummary to include carrier provided information.

This CL augments the existing data usage display with carrier provided
information about data usage and plans when available from the new
frameworks API.

Test: manual
Test: make RunSettingsRoboTests
Bug: 70950124

Change-Id: Idde1ff786e8c5dbc04e58ffbcc0fd18789682699
parent 525d757c
Loading
Loading
Loading
Loading
+112 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!--
     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.
-->

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:paddingStart="@dimen/preference_no_icon_padding_start"
    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
    android:orientation="vertical"
    android:background="@drawable/selectable_card_grey"
    android:selectable="false"
    style="@style/EntityHeader">

    <TextView
        android:id="@+id/usage_title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceListItemSecondary"
        android:textColor="?android:attr/textColorSecondary"
        android:paddingBottom="5dp"
        android:text="@string/data_usage_title" />

    <TextView
        android:id="@android:id/title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="5dp"
        android:fontFamily="@*android:string/config_headlineFontFamily"
        android:textColor="?android:attr/colorAccent"
        android:textAppearance="@android:style/TextAppearance.Material.Large" />

    <TextView
        android:id="@android:id/summary"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceListItemSecondary"
        android:textColor="?android:attr/textColorSecondary"
        android:paddingBottom="5dp" />

    <com.android.settings.widget.LinearColorBar
        android:id="@+id/color_bar"
        android:layout_width="match_parent"
        android:layout_height="28dp" />

    <LinearLayout
        android:id="@+id/label_bar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingTop="2dp"
        android:orientation="horizontal">

        <TextView android:id="@android:id/text1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textAppearance="?android:attr/textAppearanceListItemSecondary"
            android:textColor="?android:attr/textColorSecondary" />

        <Space
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1" />

        <TextView android:id="@android:id/text2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textAppearance="?android:attr/textAppearanceListItemSecondary"
            android:textColor="?android:attr/textColorSecondary" />

    </LinearLayout>

    <TextView
        android:id="@+id/cycle_left_time"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingBottom="5dp" />

    <TextView
        android:id="@+id/carrier_and_update"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingBottom="5dp" />

    <Button
        android:id="@+id/launch_mdp_app_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="left"
        android:text="@string/launch_mdp_app_text"
        style="@style/ActionPrimaryButton" />

    <TextView
        android:id="@+id/data_limits"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingBottom="5dp" />

</LinearLayout>
+23 −0
Original line number Diff line number Diff line
@@ -5844,6 +5844,8 @@
    <string name="data_usage_enable_3g">2G-3G data</string>
    <!-- Toggle switch title for enabling 4G data network connection. [CHAR LIMIT=32] -->
    <string name="data_usage_enable_4g">4G data</string>
    <!-- Toggle switch title for enabling roaming on the primary data SIM card. [CHAR LIMIT=32] -->
    <string name="data_roaming_enable_mobile">Roaming</string>
    <!-- Data Usage Foreground label.  [CHAR LIMIT=40] -->
    <string name="data_usage_forground_label">Foreground:</string>
@@ -8655,6 +8657,27 @@
        <item quantity="other"><xliff:g id="count" example="10">%1$d</xliff:g> apps allowed to use unrestricted data when Data Saver is on</item>
    </plurals>
    <!-- Data usage title text [CHAR LIMIT=30] -->
    <string name="data_usage_title">Primary data</string>
    <!-- Data usage string [CHAR LIMIT=30] -->
    <string name="data_used"><xliff:g name="bytes" example="2 GB">^1</xliff:g> used</string>
    <!-- Optional part of data usage showing the remaining amount [CHAR LIMIT=30] -->
    <string name="data_remaining"><xliff:g name="bytes" example="2 GB">, ^1</xliff:g> left</string>
    <!-- Informational text about time left in billing cycle [CHAR LIMIT=30] -->
    <string name="cycle_left_time_text"><xliff:g name="time" example="2d">%1$s</xliff:g> left in this cycle</string>
    <!-- Informational text about carrier and update time [CHAR LIMIT=30] -->
    <string name="carrier_and_update_text">Updated by <xliff:g name="carrier" example="T-mobile">%1$s</xliff:g> <xliff:g name="time" example="3m">%2$s</xliff:g></string>
    <!-- Informational text about update time only, without carrier [CHAR LIMIT=30] -->
    <string name="no_carrier_update_text">Updated <xliff:g name="time" example="3m">%1$s</xliff:g></string>
    <!-- Button to launch external data plan app [CHAR LIMIT=30] -->
    <string name="launch_mdp_app_text">VIEW PLAN</string>
    <!-- Name of Data Saver screens [CHAR LIMIT=30] -->
    <string name="data_saver_title">Data saver</string>
+1 −17
Original line number Diff line number Diff line
@@ -20,24 +20,8 @@
    android:key="data_usage_screen"
    android:title="@string/data_usage_summary_title">

    <PreferenceCategory
        android:key="data_usage_category"
        android:title="@string/usage">

        <com.android.settings.SummaryPreference
    <com.android.settings.datausage.DataUsageSummaryPreference
            android:key="status_header"
            android:selectable="false" />

        <Preference
            android:key="limit_summary"
            android:selectable="false"
            settings:allowDividerBelow="true" />

        <com.android.settings.datausage.DataSaverPreference
            android:key="restrict_background"
            android:title="@string/data_saver_title"
            android:fragment="com.android.settings.datausage.DataSaverSummary" />

    </PreferenceCategory>

</PreferenceScreen>
+42 −64
Original line number Diff line number Diff line
@@ -18,7 +18,6 @@ import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.net.NetworkPolicyManager;
import android.net.NetworkTemplate;
import android.os.Bundle;
import android.os.UserManager;
@@ -28,6 +27,7 @@ import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceScreen;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.SubscriptionPlan;
import android.text.BidiFormatter;
import android.text.Spannable;
import android.text.SpannableString;
@@ -40,7 +40,6 @@ import android.view.MenuItem;

import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.SummaryPreference;
import com.android.settings.Utils;
import com.android.settings.dashboard.SummaryLoader;
import com.android.settings.search.BaseSearchIndexProvider;
@@ -65,7 +64,6 @@ public class DataUsageSummary extends DataUsageBaseFragment implements Indexable
    public static final String KEY_RESTRICT_BACKGROUND = "restrict_background";

    private static final String KEY_STATUS_HEADER = "status_header";
    private static final String KEY_LIMIT_SUMMARY = "limit_summary";

    // Mobile data keys
    public static final String KEY_MOBILE_USAGE_TITLE = "mobile_category";
@@ -77,13 +75,9 @@ public class DataUsageSummary extends DataUsageBaseFragment implements Indexable
    public static final String KEY_WIFI_USAGE_TITLE = "wifi_category";
    public static final String KEY_WIFI_DATA_USAGE = "wifi_data_usage";

    private DataUsageController mDataUsageController;
    private DataUsageInfoController mDataInfoController;
    private SummaryPreference mSummaryPreference;
    private Preference mLimitPreference;
    private DataUsageSummaryPreference mSummaryPreference;
    private DataUsageSummaryPreferenceController mSummaryController;
    private NetworkTemplate mDefaultTemplate;
    private int mDataUsageTemplate;
    private NetworkPolicyEditor mPolicyEditor;

    @Override
    public int getHelpResource() {
@@ -95,25 +89,20 @@ public class DataUsageSummary extends DataUsageBaseFragment implements Indexable
        super.onCreate(icicle);

        final Context context = getContext();
        NetworkPolicyManager policyManager = NetworkPolicyManager.from(context);
        mPolicyEditor = new NetworkPolicyEditor(policyManager);

        boolean hasMobileData = DataUsageUtils.hasMobileData(context);
        mDataUsageController = new DataUsageController(context);
        mDataInfoController = new DataUsageInfoController();

        int defaultSubId = DataUsageUtils.getDefaultSubscriptionId(context);
        if (defaultSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
            hasMobileData = false;
        }
        mDefaultTemplate = DataUsageUtils.getDefaultTemplate(context, defaultSubId);
        mSummaryPreference = (SummaryPreference) findPreference(KEY_STATUS_HEADER);
        mSummaryPreference = (DataUsageSummaryPreference) findPreference(KEY_STATUS_HEADER);

        if (!hasMobileData || !isAdmin()) {
            removePreference(KEY_RESTRICT_BACKGROUND);
        }
        if (hasMobileData) {
            mLimitPreference = findPreference(KEY_LIMIT_SUMMARY);
            List<SubscriptionInfo> subscriptions =
                    services.mSubscriptionManager.getActiveSubscriptionInfoList();
            if (subscriptions == null || subscriptions.size() == 0) {
@@ -127,10 +116,6 @@ public class DataUsageSummary extends DataUsageBaseFragment implements Indexable
                    addMobileSection(subInfo.getSubscriptionId());
                }
            }
            mSummaryPreference.setSelectable(true);
        } else {
            removePreference(KEY_LIMIT_SUMMARY);
            mSummaryPreference.setSelectable(false);
        }
        boolean hasWifiRadio = DataUsageUtils.hasWifiRadio(context);
        if (hasWifiRadio) {
@@ -139,10 +124,6 @@ public class DataUsageSummary extends DataUsageBaseFragment implements Indexable
        if (hasEthernet(context)) {
            addEthernetSection();
        }
        mDataUsageTemplate = hasMobileData ? R.string.cell_data_template
                : hasWifiRadio ? R.string.wifi_data_template
                : R.string.ethernet_data_template;

        setHasOptionsMenu(true);
    }

@@ -189,7 +170,11 @@ public class DataUsageSummary extends DataUsageBaseFragment implements Indexable

    @Override
    protected List<AbstractPreferenceController> getPreferenceControllers(Context context) {
        return null;
        final ArrayList<AbstractPreferenceController> controllers = new ArrayList<>();
        mSummaryController =
                new DataUsageSummaryPreferenceController(context);
        controllers.add(mSummaryController);
        return controllers;
    }

    private void addMobileSection(int subId) {
@@ -269,36 +254,6 @@ public class DataUsageSummary extends DataUsageBaseFragment implements Indexable
    }

    private void updateState() {
        DataUsageController.DataUsageInfo info = mDataUsageController.getDataUsageInfo(
                mDefaultTemplate);
        Context context = getContext();
        mDataInfoController.updateDataLimit(info,
                services.mPolicyEditor.getPolicy(mDefaultTemplate));

        if (mSummaryPreference != null) {
            mSummaryPreference.setTitle(
                    formatUsage(context, getString(mDataUsageTemplate), info.usageLevel));
            final long limit = mDataInfoController.getSummaryLimit(info);
            mSummaryPreference.setSummary(info.period);
            if (limit <= 0) {
                mSummaryPreference.setChartEnabled(false);
            } else {
                mSummaryPreference.setChartEnabled(true);
                mSummaryPreference.setLabels(Formatter.formatFileSize(context, 0),
                        Formatter.formatFileSize(context, limit));
                mSummaryPreference.setRatios(info.usageLevel / (float) limit, 0,
                        (limit - info.usageLevel) / (float) limit);
            }
        }
        if (mLimitPreference != null && (info.warningLevel > 0 || info.limitLevel > 0)) {
            String warning = Formatter.formatFileSize(context, info.warningLevel);
            String limit = Formatter.formatFileSize(context, info.limitLevel);
            mLimitPreference.setSummary(getString(info.limitLevel <= 0 ? R.string.cell_warning_only
                    : R.string.cell_warning_and_limit, warning, limit));
        } else if (mLimitPreference != null) {
            mLimitPreference.setSummary(null);
        }

        PreferenceScreen screen = getPreferenceScreen();
        for (int i = 1; i < screen.getPreferenceCount(); i++) {
            ((TemplatePreferenceCategory) screen.getPreference(i)).pushTemplates(services);
@@ -323,6 +278,7 @@ public class DataUsageSummary extends DataUsageBaseFragment implements Indexable
    @Override
    public void updateDataUsage() {
        updateState();
        mSummaryController.updateState(mSummaryPreference);
    }

    private static class SummaryProvider
@@ -341,17 +297,39 @@ public class DataUsageSummary extends DataUsageBaseFragment implements Indexable
        @Override
        public void setListening(boolean listening) {
            if (listening) {
                mSummaryLoader.setSummary(this,
                        mActivity.getString(R.string.data_usage_summary_format, formatUsedData()));
            }
        }

        private String formatUsedData() {
            SubscriptionManager subscriptionManager = (SubscriptionManager) mActivity
                .getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
            int defaultSubId = subscriptionManager.getDefaultSubscriptionId();
            if (defaultSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
                return formatFallbackData();
            }
            SubscriptionPlan dfltPlan = DataUsageSummaryPreferenceController
                    .getPrimaryPlan(subscriptionManager, defaultSubId);
            if (dfltPlan == null) {
                return formatFallbackData();
            }
            if (DataUsageSummaryPreferenceController.unlimited(dfltPlan.getDataLimitBytes())) {
                return Formatter.formatFileSize(mActivity, dfltPlan.getDataUsageBytes());
            } else {
                return Utils.formatPercentage(dfltPlan.getDataUsageBytes(),
                    dfltPlan.getDataLimitBytes());
            }
        }

        private String formatFallbackData() {
            DataUsageController.DataUsageInfo info = mDataController.getDataUsageInfo();
                String used;
            if (info == null) {
                    used = Formatter.formatFileSize(mActivity, 0);
                return Formatter.formatFileSize(mActivity, 0);
            } else if (info.limitLevel <= 0) {
                    used = Formatter.formatFileSize(mActivity, info.usageLevel);
                return Formatter.formatFileSize(mActivity, info.usageLevel);
            } else {
                    used = Utils.formatPercentage(info.usageLevel, info.limitLevel);
                }
                mSummaryLoader.setSummary(this,
                        mActivity.getString(R.string.data_usage_summary_format, used));
                return Utils.formatPercentage(info.usageLevel, info.limitLevel);
            }
        }
    }
+117 −0
Original line number Diff line number Diff line
/*
 * 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.datausage;

import android.content.Context;
import android.content.Intent;
import android.support.v7.preference.PreferenceViewHolder;
import android.util.AttributeSet;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import com.android.settings.R;
import com.android.settings.SummaryPreference;
import com.android.settingslib.utils.StringUtil;

import libcore.util.Objects;

/**
 * Provides a summary of data usage.
 */
public class DataUsageSummaryPreference extends SummaryPreference {

    private int mNumPlans;
    /** The ending time of the billing cycle in milliseconds since epoch. */
    private long mCycleEndTimeMs;
    /** The time of the last update in standard milliseconds since the epoch */
    private long mSnapshotTimeMs;
    /** Name of carrier, or null if not available */
    private CharSequence mCarrierName;
    private String mLimitInfoText;
    private Intent mLaunchIntent;

    public DataUsageSummaryPreference(Context context, AttributeSet attrs) {
        super(context, attrs);
        setLayoutResource(R.layout.data_usage_summary_preference);
    }

    public void setLimitInfo(String text) {
        if (!Objects.equal(text, mLimitInfoText)) {
            mLimitInfoText = text;
            notifyChanged();
        }
    }

    public void setUsageInfo(long cycleEnd, long snapshotTime, CharSequence carrierName,
            int numPlans, Intent launchIntent) {
        mCycleEndTimeMs = cycleEnd;
        mSnapshotTimeMs = snapshotTime;
        mCarrierName = carrierName;
        mNumPlans = numPlans;
        mLaunchIntent = launchIntent;
        notifyChanged();
    }

    @Override
    public void onBindViewHolder(PreferenceViewHolder holder) {
        super.onBindViewHolder(holder);

        TextView usageTitle = (TextView) holder.findViewById(R.id.usage_title);
        usageTitle.setVisibility(mNumPlans > 1 ? View.VISIBLE : View.GONE);

        TextView cycleTime = (TextView) holder.findViewById(R.id.cycle_left_time);
        cycleTime.setText(getContext().getString(R.string.cycle_left_time_text,
                StringUtil.formatElapsedTime(getContext(),
                        mCycleEndTimeMs - System.currentTimeMillis(),false /* withSeconds */)));

        TextView carrierInfo = (TextView) holder.findViewById(R.id.carrier_and_update);
        setCarrierInfo(carrierInfo, mCarrierName, mSnapshotTimeMs);

        Button launchButton = (Button) holder.findViewById(R.id.launch_mdp_app_button);
        launchButton.setOnClickListener((view) -> {
            getContext().sendBroadcast(mLaunchIntent);
        });
        if (mLaunchIntent != null) {
            launchButton.setVisibility(View.VISIBLE);
        } else {
            launchButton.setVisibility(View.GONE);
        }

        TextView limitInfo = (TextView) holder.findViewById(R.id.data_limits);
        limitInfo.setVisibility(
                mLimitInfoText == null || mLimitInfoText.isEmpty() ? View.GONE : View.VISIBLE);
        limitInfo.setText(mLimitInfoText);
    }

    private void setCarrierInfo(TextView carrierInfo, CharSequence carrierName, long updateAge) {
        if (mNumPlans > 0 && updateAge >= 0L) {
            carrierInfo.setVisibility(View.VISIBLE);
            if (carrierName != null) {
                carrierInfo.setText(getContext().getString(R.string.carrier_and_update_text,
                        carrierName, StringUtil.formatRelativeTime(
                                getContext(), updateAge, false /* withSeconds */)));
            } else {
                carrierInfo.setText(getContext().getString(R.string.no_carrier_update_text,
                        StringUtil.formatRelativeTime(
                                getContext(), updateAge, false /* withSeconds */)));
            }
        } else {
            carrierInfo.setVisibility(View.GONE);
        }
    }
}
 No newline at end of file
Loading