/* * Copyright (C) 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.car.settings.datausage; import android.content.Context; import android.net.NetworkStats; import android.net.NetworkTemplate; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.telephony.SubscriptionPlan; import android.telephony.TelephonyManager; import android.text.BidiFormatter; import android.text.format.DateUtils; import android.text.format.Formatter; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import com.android.car.settings.R; import com.android.internal.util.CollectionUtils; import java.util.Calendar; import java.util.List; import java.util.Set; /** Provides helpful utilities related to data usage. */ public final class DataUsageUtils { @VisibleForTesting static final long PETA = 1000000000000000L; private DataUsageUtils() { } /** * Returns the mobile network template given the subscription id. */ public static NetworkTemplate getMobileNetworkTemplate(TelephonyManager telephonyManager, int subscriptionId) { String subscriberId = telephonyManager.getSubscriberId(subscriptionId); NetworkTemplate.Builder builder = new NetworkTemplate.Builder(NetworkTemplate.MATCH_MOBILE) .setMeteredness(NetworkStats.METERED_YES); if (subscriberId != null) { builder.setSubscriberIds(Set.of(subscriberId)); } return normalizeMobileTemplate(builder.build(), telephonyManager.getMergedSubscriberIds()); } private static NetworkTemplate normalizeMobileTemplate( @NonNull NetworkTemplate template, @Nullable String[] mergedSet) { if (template.getSubscriberIds().isEmpty() || mergedSet == null) return template; // The input template should have at most 1 subscriberId. String subscriberId = template.getSubscriberIds().iterator().next(); if (Set.of(mergedSet).contains(subscriberId)) { // Requested template subscriber is part of the merge group; return // a template that matches all merged subscribers. return new NetworkTemplate.Builder(template.getMatchRule()) .setSubscriberIds(Set.of(mergedSet)) .setMeteredness(template.getMeteredness()).build(); } return template; } /** * Returns the default subscription if available else returns * {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID}. */ public static int getDefaultSubscriptionId(SubscriptionManager subscriptionManager) { if (subscriptionManager == null) { return SubscriptionManager.INVALID_SUBSCRIPTION_ID; } SubscriptionInfo subscriptionInfo = subscriptionManager.getDefaultDataSubscriptionInfo(); if (subscriptionInfo == null) { List list = subscriptionManager.getAllSubscriptionInfoList(); if (list.size() == 0) { return SubscriptionManager.INVALID_SUBSCRIPTION_ID; } subscriptionInfo = list.get(0); } return subscriptionInfo.getSubscriptionId(); } /** * Format byte value to readable string using IEC units. */ public static CharSequence bytesToIecUnits(Context context, long byteValue) { Formatter.BytesResult res = Formatter.formatBytes(context.getResources(), byteValue, Formatter.FLAG_IEC_UNITS); return BidiFormatter.getInstance().unicodeWrap(context.getString( com.android.internal.R.string.fileSizeSuffix, res.value, res.units)); } /** * Generate a string that lists byte value to readable string using IEC units, and date range * from specified start date to current date. */ public static CharSequence formatDataUsageInCycle(Context context, long byteValue, long fromTimeInMillis) { CharSequence usage = bytesToIecUnits(context, byteValue); int flags = DateUtils.FORMAT_ABBREV_MONTH | DateUtils.FORMAT_NO_YEAR; String fromText = DateUtils.formatDateTime(context, fromTimeInMillis, flags); String toText = DateUtils.formatDateTime(context, Calendar.getInstance().getTimeInMillis(), flags); return context.getString(R.string.network_and_internet_data_usage_time_range_summary, usage, fromText, toText); } /** * Returns the primary subscription plan. Returns {@code null} if {@link SubscriptionPlan} * doesn't exist for a given subscriptionId or if the first {@link SubscriptionPlan} has * invalid properties. */ @Nullable public static SubscriptionPlan getPrimaryPlan(SubscriptionManager subManager, int subscriptionId) { List plans = subManager.getSubscriptionPlans(subscriptionId); if (CollectionUtils.isEmpty(plans)) { return null; } // First plan in the list is the primary plan SubscriptionPlan plan = plans.get(0); return plan.getDataLimitBytes() > 0 && saneSize(plan.getDataUsageBytes()) && plan.getCycleRule() != null ? plan : null; } private static boolean saneSize(long value) { return value >= 0L && value < PETA; } }